NetSurf
duktape.c
Go to the documentation of this file.
1/* Omit from static analysis. */
2#ifndef __clang_analyzer__
3/*
4 * Single source autogenerated distributable for Duktape 2.7.0.
5 *
6 * Git commit external (external).
7 * Git branch external.
8 *
9 * See Duktape AUTHORS.rst and LICENSE.txt for copyright and
10 * licensing information.
11 */
12
13/* LICENSE.txt */
14/*
15* ===============
16* Duktape license
17* ===============
18*
19* (http://opensource.org/licenses/MIT)
20*
21* Copyright (c) 2013-present by Duktape authors (see AUTHORS.rst)
22*
23* Permission is hereby granted, free of charge, to any person obtaining a copy
24* of this software and associated documentation files (the "Software"), to deal
25* in the Software without restriction, including without limitation the rights
26* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
27* copies of the Software, and to permit persons to whom the Software is
28* furnished to do so, subject to the following conditions:
29*
30* The above copyright notice and this permission notice shall be included in
31* all copies or substantial portions of the Software.
32*
33* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
34* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
35* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
36* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
37* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
38* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
39* THE SOFTWARE.
40*/
41
42/* AUTHORS.rst */
43/*
44* ===============
45* Duktape authors
46* ===============
47*
48* Copyright
49* =========
50*
51* Duktape copyrights are held by its authors. Each author has a copyright
52* to their contribution, and agrees to irrevocably license the contribution
53* under the Duktape ``LICENSE.txt``.
54*
55* Authors
56* =======
57*
58* Please include an e-mail address, a link to your GitHub profile, or something
59* similar to allow your contribution to be identified accurately.
60*
61* The following people have contributed code, website contents, or Wiki contents,
62* and agreed to irrevocably license their contributions under the Duktape
63* ``LICENSE.txt`` (in order of appearance):
64*
65* * Sami Vaarala <sami.vaarala@iki.fi>
66* * Niki Dobrev
67* * Andreas \u00d6man <andreas@lonelycoder.com>
68* * L\u00e1szl\u00f3 Lang\u00f3 <llango.u-szeged@partner.samsung.com>
69* * Legimet <legimet.calc@gmail.com>
70* * Karl Skomski <karl@skomski.com>
71* * Bruce Pascoe <fatcerberus1@gmail.com>
72* * Ren\u00e9 Hollander <rene@rene8888.at>
73* * Julien Hamaide (https://github.com/crazyjul)
74* * Sebastian G\u00f6tte (https://github.com/jaseg)
75* * Tomasz Magulski (https://github.com/magul)
76* * \D. Bohdan (https://github.com/dbohdan)
77* * Ond\u0159ej Jirman (https://github.com/megous)
78* * Sa\u00fal Ibarra Corretg\u00e9 <saghul@gmail.com>
79* * Jeremy HU <huxingyi@msn.com>
80* * Ole Andr\u00e9 Vadla Ravn\u00e5s (https://github.com/oleavr)
81* * Harold Brenes (https://github.com/harold-b)
82* * Oliver Crow (https://github.com/ocrow)
83* * Jakub Ch\u0142api\u0144ski (https://github.com/jchlapinski)
84* * Brett Vickers (https://github.com/beevik)
85* * Dominik Okwieka (https://github.com/okitec)
86* * Remko Tron\u00e7on (https://el-tramo.be)
87* * Romero Malaquias (rbsm@ic.ufal.br)
88* * Michael Drake <michael.drake@codethink.co.uk>
89* * Steven Don (https://github.com/shdon)
90* * Simon Stone (https://github.com/sstone1)
91* * \J. McC. (https://github.com/jmhmccr)
92* * Jakub Nowakowski (https://github.com/jimvonmoon)
93* * Tommy Nguyen (https://github.com/tn0502)
94* * Fabrice Fontaine (https://github.com/ffontaine)
95* * Christopher Hiller (https://github.com/boneskull)
96* * Gonzalo Diethelm (https://github.com/gonzus)
97* * Michal Kasperek (https://github.com/michalkas)
98* * Andrew Janke (https://github.com/apjanke)
99* * Steve Fan (https://github.com/stevefan1999)
100* * Edward Betts (https://github.com/edwardbetts)
101* * Ozhan Duz (https://github.com/webfolderio)
102* * Akos Kiss (https://github.com/akosthekiss)
103* * TheBrokenRail (https://github.com/TheBrokenRail)
104* * Jesse Doyle (https://github.com/jessedoyle)
105* * Gero Kuehn (https://github.com/dc6jgk)
106* * James Swift (https://github.com/phraemer)
107* * Luis de Bethencourt (https://github.com/luisbg)
108* * Ian Whyman (https://github.com/v00d00)
109* * Rick Sayre (https://github.com/whorfin)
110* * Craig Leres (https://github.com/leres)
111* * Maurici Abad (https://github.com/mauriciabad)
112* * Nancy Li (https://github.com/NancyLi1013)
113* * William Parks (https://github.com/WilliamParks)
114* * Sam Hellawell (https://github.com/samhellawell)
115* * Vladislavs Sokurenko (https://github.com/sokurenko)
116*
117* Other contributions
118* ===================
119*
120* The following people have contributed something other than code (e.g. reported
121* bugs, provided ideas, etc; roughly in order of appearance):
122*
123* * Greg Burns
124* * Anthony Rabine
125* * Carlos Costa
126* * Aur\u00e9lien Bouilland
127* * Preet Desai (Pris Matic)
128* * judofyr (http://www.reddit.com/user/judofyr)
129* * Jason Woofenden
130* * Micha\u0142 Przyby\u015b
131* * Anthony Howe
132* * Conrad Pankoff
133* * Jim Schimpf
134* * Rajaran Gaunker (https://github.com/zimbabao)
135* * Andreas \u00d6man
136* * Doug Sanden
137* * Josh Engebretson (https://github.com/JoshEngebretson)
138* * Remo Eichenberger (https://github.com/remoe)
139* * Mamod Mehyar (https://github.com/mamod)
140* * David Demelier (https://github.com/markand)
141* * Tim Caswell (https://github.com/creationix)
142* * Mitchell Blank Jr (https://github.com/mitchblank)
143* * https://github.com/yushli
144* * Seo Sanghyeon (https://github.com/sanxiyn)
145* * Han ChoongWoo (https://github.com/tunz)
146* * Joshua Peek (https://github.com/josh)
147* * Bruce E. Pascoe (https://github.com/fatcerberus)
148* * https://github.com/Kelledin
149* * https://github.com/sstruchtrup
150* * Michael Drake (https://github.com/tlsa)
151* * https://github.com/chris-y
152* * Laurent Zubiaur (https://github.com/lzubiaur)
153* * Neil Kolban (https://github.com/nkolban)
154* * Wilhelm Wanecek (https://github.com/wanecek)
155* * Andrew Janke (https://github.com/apjanke)
156* * Unamer (https://github.com/unamer)
157* * Karl Dahlke (eklhad@gmail.com)
158*
159* If you are accidentally missing from this list, send me an e-mail
160* (``sami.vaarala@iki.fi``) and I'll fix the omission.
161*/
162
163/*
164 * Replacements for missing platform functions.
165 *
166 * Unlike the originals, fpclassify() and signbit() replacements don't
167 * work on any floating point types, only doubles. The C typing here
168 * mimics the standard prototypes.
169 */
170
171/* #include duk_internal.h */
172/*
173 * Top-level include file to be used for all (internal) source files.
174 *
175 * Source files should not include individual header files, as they
176 * have not been designed to be individually included.
177 */
178
179#if !defined(DUK_INTERNAL_H_INCLUDED)
180#define DUK_INTERNAL_H_INCLUDED
181
182/*
183 * The 'duktape.h' header provides the public API, but also handles all
184 * compiler and platform specific feature detection, Duktape feature
185 * resolution, inclusion of system headers, etc. These have been merged
186 * because the public API is also dependent on e.g. detecting appropriate
187 * C types which is quite platform/compiler specific especially for a non-C99
188 * build. The public API is also dependent on the resolved feature set.
189 *
190 * Some actions taken by the merged header (such as including system headers)
191 * are not appropriate for building a user application. The define
192 * DUK_COMPILING_DUKTAPE allows the merged header to skip/include some
193 * sections depending on what is being built.
194 */
195
196#define DUK_COMPILING_DUKTAPE
197#include "duktape.h"
198
199/*
200 * Duktape includes (other than duk_features.h)
201 *
202 * The header files expect to be included in an order which satisfies header
203 * dependencies correctly (the headers themselves don't include any other
204 * includes). Forward declarations are used to break circular struct/typedef
205 * dependencies.
206 */
207
208/* #include duk_dblunion.h */
209/*
210 * Union to access IEEE double memory representation, indexes for double
211 * memory representation, and some macros for double manipulation.
212 *
213 * Also used by packed duk_tval. Use a union for bit manipulation to
214 * minimize aliasing issues in practice. The C99 standard does not
215 * guarantee that this should work, but it's a very widely supported
216 * practice for low level manipulation.
217 *
218 * IEEE double format summary:
219 *
220 * seeeeeee eeeeffff ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff
221 * A B C D E F G H
222 *
223 * s sign bit
224 * eee... exponent field
225 * fff... fraction
226 *
227 * See http://en.wikipedia.org/wiki/Double_precision_floating-point_format.
228 *
229 * NaNs are represented as exponent 0x7ff and mantissa != 0. The NaN is a
230 * signaling NaN when the highest bit of the mantissa is zero, and a quiet
231 * NaN when the highest bit is set.
232 *
233 * At least three memory layouts are relevant here:
234 *
235 * A B C D E F G H Big endian (e.g. 68k) DUK_USE_DOUBLE_BE
236 * H G F E D C B A Little endian (e.g. x86) DUK_USE_DOUBLE_LE
237 * D C B A H G F E Mixed endian (e.g. ARM FPA) DUK_USE_DOUBLE_ME
238 *
239 * Legacy ARM (FPA) is a special case: ARM double values are in mixed
240 * endian format while ARM duk_uint64_t values are in standard little endian
241 * format (H G F E D C B A). When a double is read as a duk_uint64_t
242 * from memory, the register will contain the (logical) value
243 * E F G H A B C D. This requires some special handling below.
244 * See http://infocenter.arm.com/help/index.jsp?topic=/com.arm.doc.dui0056d/Bcfhgcgd.html.
245 *
246 * Indexes of various types (8-bit, 16-bit, 32-bit) in memory relative to
247 * the logical (big endian) order:
248 *
249 * byte order duk_uint8_t duk_uint16_t duk_uint32_t
250 * BE 01234567 0123 01
251 * LE 76543210 3210 10
252 * ME (ARM) 32107654 1032 01
253 *
254 * Some processors may alter NaN values in a floating point load+store.
255 * For instance, on X86 a FLD + FSTP may convert a signaling NaN to a
256 * quiet one. This is catastrophic when NaN space is used in packed
257 * duk_tval values. See: misc/clang_aliasing.c.
258 */
259
260#if !defined(DUK_DBLUNION_H_INCLUDED)
261#define DUK_DBLUNION_H_INCLUDED
262
263/*
264 * Union for accessing double parts, also serves as packed duk_tval
265 */
266
268 double d;
269 float f[2];
270#if defined(DUK_USE_64BIT_OPS)
271 duk_uint64_t ull[1];
272#endif
273 duk_uint32_t ui[2];
274 duk_uint16_t us[4];
275 duk_uint8_t uc[8];
276#if defined(DUK_USE_PACKED_TVAL)
277 void *vp[2]; /* used by packed duk_tval, assumes sizeof(void *) == 4 */
278#endif
279};
280
282
283/*
284 * Indexes of various types with respect to big endian (logical) layout
285 */
286
287#if defined(DUK_USE_DOUBLE_LE)
288#if defined(DUK_USE_64BIT_OPS)
289#define DUK_DBL_IDX_ULL0 0
290#endif
291#define DUK_DBL_IDX_UI0 1
292#define DUK_DBL_IDX_UI1 0
293#define DUK_DBL_IDX_US0 3
294#define DUK_DBL_IDX_US1 2
295#define DUK_DBL_IDX_US2 1
296#define DUK_DBL_IDX_US3 0
297#define DUK_DBL_IDX_UC0 7
298#define DUK_DBL_IDX_UC1 6
299#define DUK_DBL_IDX_UC2 5
300#define DUK_DBL_IDX_UC3 4
301#define DUK_DBL_IDX_UC4 3
302#define DUK_DBL_IDX_UC5 2
303#define DUK_DBL_IDX_UC6 1
304#define DUK_DBL_IDX_UC7 0
305#define DUK_DBL_IDX_VP0 DUK_DBL_IDX_UI0 /* packed tval */
306#define DUK_DBL_IDX_VP1 DUK_DBL_IDX_UI1 /* packed tval */
307#elif defined(DUK_USE_DOUBLE_BE)
308#if defined(DUK_USE_64BIT_OPS)
309#define DUK_DBL_IDX_ULL0 0
310#endif
311#define DUK_DBL_IDX_UI0 0
312#define DUK_DBL_IDX_UI1 1
313#define DUK_DBL_IDX_US0 0
314#define DUK_DBL_IDX_US1 1
315#define DUK_DBL_IDX_US2 2
316#define DUK_DBL_IDX_US3 3
317#define DUK_DBL_IDX_UC0 0
318#define DUK_DBL_IDX_UC1 1
319#define DUK_DBL_IDX_UC2 2
320#define DUK_DBL_IDX_UC3 3
321#define DUK_DBL_IDX_UC4 4
322#define DUK_DBL_IDX_UC5 5
323#define DUK_DBL_IDX_UC6 6
324#define DUK_DBL_IDX_UC7 7
325#define DUK_DBL_IDX_VP0 DUK_DBL_IDX_UI0 /* packed tval */
326#define DUK_DBL_IDX_VP1 DUK_DBL_IDX_UI1 /* packed tval */
327#elif defined(DUK_USE_DOUBLE_ME)
328#if defined(DUK_USE_64BIT_OPS)
329#define DUK_DBL_IDX_ULL0 0 /* not directly applicable, byte order differs from a double */
330#endif
331#define DUK_DBL_IDX_UI0 0
332#define DUK_DBL_IDX_UI1 1
333#define DUK_DBL_IDX_US0 1
334#define DUK_DBL_IDX_US1 0
335#define DUK_DBL_IDX_US2 3
336#define DUK_DBL_IDX_US3 2
337#define DUK_DBL_IDX_UC0 3
338#define DUK_DBL_IDX_UC1 2
339#define DUK_DBL_IDX_UC2 1
340#define DUK_DBL_IDX_UC3 0
341#define DUK_DBL_IDX_UC4 7
342#define DUK_DBL_IDX_UC5 6
343#define DUK_DBL_IDX_UC6 5
344#define DUK_DBL_IDX_UC7 4
345#define DUK_DBL_IDX_VP0 DUK_DBL_IDX_UI0 /* packed tval */
346#define DUK_DBL_IDX_VP1 DUK_DBL_IDX_UI1 /* packed tval */
347#else
348#error internal error
349#endif
350
351/*
352 * Helper macros for reading/writing memory representation parts, used
353 * by duk_numconv.c and duk_tval.h.
354 */
355
356#define DUK_DBLUNION_SET_DOUBLE(u, v) \
357 do { \
358 (u)->d = (v); \
359 } while (0)
360
361#define DUK_DBLUNION_SET_HIGH32(u, v) \
362 do { \
363 (u)->ui[DUK_DBL_IDX_UI0] = (duk_uint32_t) (v); \
364 } while (0)
365
366#if defined(DUK_USE_64BIT_OPS)
367#if defined(DUK_USE_DOUBLE_ME)
368#define DUK_DBLUNION_SET_HIGH32_ZERO_LOW32(u, v) \
369 do { \
370 (u)->ull[DUK_DBL_IDX_ULL0] = (duk_uint64_t) (v); \
371 } while (0)
372#else
373#define DUK_DBLUNION_SET_HIGH32_ZERO_LOW32(u, v) \
374 do { \
375 (u)->ull[DUK_DBL_IDX_ULL0] = ((duk_uint64_t) (v)) << 32; \
376 } while (0)
377#endif
378#else /* DUK_USE_64BIT_OPS */
379#define DUK_DBLUNION_SET_HIGH32_ZERO_LOW32(u, v) \
380 do { \
381 (u)->ui[DUK_DBL_IDX_UI0] = (duk_uint32_t) (v); \
382 (u)->ui[DUK_DBL_IDX_UI1] = (duk_uint32_t) 0; \
383 } while (0)
384#endif /* DUK_USE_64BIT_OPS */
385
386#define DUK_DBLUNION_SET_LOW32(u, v) \
387 do { \
388 (u)->ui[DUK_DBL_IDX_UI1] = (duk_uint32_t) (v); \
389 } while (0)
390
391#define DUK_DBLUNION_GET_DOUBLE(u) ((u)->d)
392#define DUK_DBLUNION_GET_HIGH32(u) ((u)->ui[DUK_DBL_IDX_UI0])
393#define DUK_DBLUNION_GET_LOW32(u) ((u)->ui[DUK_DBL_IDX_UI1])
394
395#if defined(DUK_USE_64BIT_OPS)
396#if defined(DUK_USE_DOUBLE_ME)
397#define DUK_DBLUNION_SET_UINT64(u, v) \
398 do { \
399 (u)->ui[DUK_DBL_IDX_UI0] = (duk_uint32_t) ((v) >> 32); \
400 (u)->ui[DUK_DBL_IDX_UI1] = (duk_uint32_t) (v); \
401 } while (0)
402#define DUK_DBLUNION_GET_UINT64(u) ((((duk_uint64_t) (u)->ui[DUK_DBL_IDX_UI0]) << 32) | ((duk_uint64_t) (u)->ui[DUK_DBL_IDX_UI1]))
403#else
404#define DUK_DBLUNION_SET_UINT64(u, v) \
405 do { \
406 (u)->ull[DUK_DBL_IDX_ULL0] = (duk_uint64_t) (v); \
407 } while (0)
408#define DUK_DBLUNION_GET_UINT64(u) ((u)->ull[DUK_DBL_IDX_ULL0])
409#endif
410#define DUK_DBLUNION_SET_INT64(u, v) DUK_DBLUNION_SET_UINT64((u), (duk_uint64_t) (v))
411#define DUK_DBLUNION_GET_INT64(u) ((duk_int64_t) DUK_DBLUNION_GET_UINT64((u)))
412#endif /* DUK_USE_64BIT_OPS */
413
414/*
415 * Double NaN manipulation macros related to NaN normalization needed when
416 * using the packed duk_tval representation. NaN normalization is necessary
417 * to keep double values compatible with the duk_tval format.
418 *
419 * When packed duk_tval is used, the NaN space is used to store pointers
420 * and other tagged values in addition to NaNs. Actual NaNs are normalized
421 * to a specific quiet NaN. The macros below are used by the implementation
422 * to check and normalize NaN values when they might be created. The macros
423 * are essentially NOPs when the non-packed duk_tval representation is used.
424 *
425 * A FULL check is exact and checks all bits. A NOTFULL check is used by
426 * the packed duk_tval and works correctly for all NaNs except those that
427 * begin with 0x7ff0. Since the 'normalized NaN' values used with packed
428 * duk_tval begin with 0x7ff8, the partial check is reliable when packed
429 * duk_tval is used. The 0x7ff8 prefix means the normalized NaN will be a
430 * quiet NaN regardless of its remaining lower bits.
431 *
432 * The ME variant below is specifically for ARM byte order, which has the
433 * feature that while doubles have a mixed byte order (32107654), unsigned
434 * long long values has a little endian byte order (76543210). When writing
435 * a logical double value through a ULL pointer, the 32-bit words need to be
436 * swapped; hence the #if defined()s below for ULL writes with DUK_USE_DOUBLE_ME.
437 * This is not full ARM support but suffices for some environments.
438 */
439
440#if defined(DUK_USE_64BIT_OPS)
441#if defined(DUK_USE_DOUBLE_ME)
442/* Macros for 64-bit ops + mixed endian doubles. */
443#define DUK__DBLUNION_SET_NAN_FULL(u) \
444 do { \
445 (u)->ull[DUK_DBL_IDX_ULL0] = DUK_U64_CONSTANT(0x000000007ff80000); \
446 } while (0)
447#define DUK__DBLUNION_IS_NAN_FULL(u) \
448 ((((u)->ull[DUK_DBL_IDX_ULL0] & DUK_U64_CONSTANT(0x000000007ff00000)) == DUK_U64_CONSTANT(0x000000007ff00000)) && \
449 ((((u)->ull[DUK_DBL_IDX_ULL0]) & DUK_U64_CONSTANT(0xffffffff000fffff)) != 0))
450#define DUK__DBLUNION_IS_NORMALIZED_NAN_FULL(u) ((u)->ull[DUK_DBL_IDX_ULL0] == DUK_U64_CONSTANT(0x000000007ff80000))
451#define DUK__DBLUNION_IS_ANYINF(u) \
452 (((u)->ull[DUK_DBL_IDX_ULL0] & DUK_U64_CONSTANT(0xffffffff7fffffff)) == DUK_U64_CONSTANT(0x000000007ff00000))
453#define DUK__DBLUNION_IS_POSINF(u) ((u)->ull[DUK_DBL_IDX_ULL0] == DUK_U64_CONSTANT(0x000000007ff00000))
454#define DUK__DBLUNION_IS_NEGINF(u) ((u)->ull[DUK_DBL_IDX_ULL0] == DUK_U64_CONSTANT(0x00000000fff00000))
455#define DUK__DBLUNION_IS_ANYZERO(u) \
456 (((u)->ull[DUK_DBL_IDX_ULL0] & DUK_U64_CONSTANT(0xffffffff7fffffff)) == DUK_U64_CONSTANT(0x0000000000000000))
457#define DUK__DBLUNION_IS_POSZERO(u) ((u)->ull[DUK_DBL_IDX_ULL0] == DUK_U64_CONSTANT(0x0000000000000000))
458#define DUK__DBLUNION_IS_NEGZERO(u) ((u)->ull[DUK_DBL_IDX_ULL0] == DUK_U64_CONSTANT(0x0000000080000000))
459#else
460/* Macros for 64-bit ops + big/little endian doubles. */
461#define DUK__DBLUNION_SET_NAN_FULL(u) \
462 do { \
463 (u)->ull[DUK_DBL_IDX_ULL0] = DUK_U64_CONSTANT(0x7ff8000000000000); \
464 } while (0)
465#define DUK__DBLUNION_IS_NAN_FULL(u) \
466 ((((u)->ull[DUK_DBL_IDX_ULL0] & DUK_U64_CONSTANT(0x7ff0000000000000)) == DUK_U64_CONSTANT(0x7ff0000000000000)) && \
467 ((((u)->ull[DUK_DBL_IDX_ULL0]) & DUK_U64_CONSTANT(0x000fffffffffffff)) != 0))
468#define DUK__DBLUNION_IS_NORMALIZED_NAN_FULL(u) ((u)->ull[DUK_DBL_IDX_ULL0] == DUK_U64_CONSTANT(0x7ff8000000000000))
469#define DUK__DBLUNION_IS_ANYINF(u) \
470 (((u)->ull[DUK_DBL_IDX_ULL0] & DUK_U64_CONSTANT(0x7fffffffffffffff)) == DUK_U64_CONSTANT(0x7ff0000000000000))
471#define DUK__DBLUNION_IS_POSINF(u) ((u)->ull[DUK_DBL_IDX_ULL0] == DUK_U64_CONSTANT(0x7ff0000000000000))
472#define DUK__DBLUNION_IS_NEGINF(u) ((u)->ull[DUK_DBL_IDX_ULL0] == DUK_U64_CONSTANT(0xfff0000000000000))
473#define DUK__DBLUNION_IS_ANYZERO(u) \
474 (((u)->ull[DUK_DBL_IDX_ULL0] & DUK_U64_CONSTANT(0x7fffffffffffffff)) == DUK_U64_CONSTANT(0x0000000000000000))
475#define DUK__DBLUNION_IS_POSZERO(u) ((u)->ull[DUK_DBL_IDX_ULL0] == DUK_U64_CONSTANT(0x0000000000000000))
476#define DUK__DBLUNION_IS_NEGZERO(u) ((u)->ull[DUK_DBL_IDX_ULL0] == DUK_U64_CONSTANT(0x8000000000000000))
477#endif
478#else /* DUK_USE_64BIT_OPS */
479/* Macros for no 64-bit ops, any endianness. */
480#define DUK__DBLUNION_SET_NAN_FULL(u) \
481 do { \
482 (u)->ui[DUK_DBL_IDX_UI0] = (duk_uint32_t) 0x7ff80000UL; \
483 (u)->ui[DUK_DBL_IDX_UI1] = (duk_uint32_t) 0x00000000UL; \
484 } while (0)
485#define DUK__DBLUNION_IS_NAN_FULL(u) \
486 ((((u)->ui[DUK_DBL_IDX_UI0] & 0x7ff00000UL) == 0x7ff00000UL) && \
487 (((u)->ui[DUK_DBL_IDX_UI0] & 0x000fffffUL) != 0 || (u)->ui[DUK_DBL_IDX_UI1] != 0))
488#define DUK__DBLUNION_IS_NORMALIZED_NAN_FULL(u) \
489 (((u)->ui[DUK_DBL_IDX_UI0] == 0x7ff80000UL) && ((u)->ui[DUK_DBL_IDX_UI1] == 0x00000000UL))
490#define DUK__DBLUNION_IS_ANYINF(u) \
491 ((((u)->ui[DUK_DBL_IDX_UI0] & 0x7fffffffUL) == 0x7ff00000UL) && ((u)->ui[DUK_DBL_IDX_UI1] == 0x00000000UL))
492#define DUK__DBLUNION_IS_POSINF(u) (((u)->ui[DUK_DBL_IDX_UI0] == 0x7ff00000UL) && ((u)->ui[DUK_DBL_IDX_UI1] == 0x00000000UL))
493#define DUK__DBLUNION_IS_NEGINF(u) (((u)->ui[DUK_DBL_IDX_UI0] == 0xfff00000UL) && ((u)->ui[DUK_DBL_IDX_UI1] == 0x00000000UL))
494#define DUK__DBLUNION_IS_ANYZERO(u) \
495 ((((u)->ui[DUK_DBL_IDX_UI0] & 0x7fffffffUL) == 0x00000000UL) && ((u)->ui[DUK_DBL_IDX_UI1] == 0x00000000UL))
496#define DUK__DBLUNION_IS_POSZERO(u) (((u)->ui[DUK_DBL_IDX_UI0] == 0x00000000UL) && ((u)->ui[DUK_DBL_IDX_UI1] == 0x00000000UL))
497#define DUK__DBLUNION_IS_NEGZERO(u) (((u)->ui[DUK_DBL_IDX_UI0] == 0x80000000UL) && ((u)->ui[DUK_DBL_IDX_UI1] == 0x00000000UL))
498#endif /* DUK_USE_64BIT_OPS */
499
500#define DUK__DBLUNION_SET_NAN_NOTFULL(u) \
501 do { \
502 (u)->us[DUK_DBL_IDX_US0] = 0x7ff8UL; \
503 } while (0)
504
505#define DUK__DBLUNION_IS_NAN_NOTFULL(u) \
506 /* E == 0x7ff, topmost four bits of F != 0 => assume NaN */ \
507 ((((u)->us[DUK_DBL_IDX_US0] & 0x7ff0UL) == 0x7ff0UL) && (((u)->us[DUK_DBL_IDX_US0] & 0x000fUL) != 0x0000UL))
508
509#define DUK__DBLUNION_IS_NORMALIZED_NAN_NOTFULL(u) \
510 /* E == 0x7ff, F == 8 => normalized NaN */ \
511 ((u)->us[DUK_DBL_IDX_US0] == 0x7ff8UL)
512
513#define DUK__DBLUNION_NORMALIZE_NAN_CHECK_FULL(u) \
514 do { \
515 if (DUK__DBLUNION_IS_NAN_FULL((u))) { \
516 DUK__DBLUNION_SET_NAN_FULL((u)); \
517 } \
518 } while (0)
519
520#define DUK__DBLUNION_NORMALIZE_NAN_CHECK_NOTFULL(u) \
521 do { \
522 /* Check must be full. */ \
523 if (DUK__DBLUNION_IS_NAN_FULL((u))) { \
524 DUK__DBLUNION_SET_NAN_NOTFULL((u)); \
525 } \
526 } while (0)
527
528/* Concrete macros for NaN handling used by the implementation internals.
529 * Chosen so that they match the duk_tval representation: with a packed
530 * duk_tval, ensure NaNs are properly normalized; with a non-packed duk_tval
531 * these are essentially NOPs.
532 */
533
534#if defined(DUK_USE_PACKED_TVAL)
535#define DUK_DBLUNION_NORMALIZE_NAN_CHECK(u) DUK__DBLUNION_NORMALIZE_NAN_CHECK_FULL((u))
536#define DUK_DBLUNION_IS_NAN(u) DUK__DBLUNION_IS_NAN_FULL((u))
537#define DUK_DBLUNION_IS_NORMALIZED_NAN(u) DUK__DBLUNION_IS_NORMALIZED_NAN_FULL((u))
538#define DUK_DBLUNION_SET_NAN(d) DUK__DBLUNION_SET_NAN_FULL((d))
539#if 0
540#define DUK_DBLUNION_NORMALIZE_NAN_CHECK(u) DUK__DBLUNION_NORMALIZE_NAN_CHECK_NOTFULL((u))
541#define DUK_DBLUNION_IS_NAN(u) DUK__DBLUNION_IS_NAN_NOTFULL((u))
542#define DUK_DBLUNION_IS_NORMALIZED_NAN(u) DUK__DBLUNION_IS_NORMALIZED_NAN_NOTFULL((u))
543#define DUK_DBLUNION_SET_NAN(d) DUK__DBLUNION_SET_NAN_NOTFULL((d))
544#endif
545#define DUK_DBLUNION_IS_NORMALIZED(u) \
546 (!DUK_DBLUNION_IS_NAN((u)) || /* either not a NaN */ \
547 DUK_DBLUNION_IS_NORMALIZED_NAN((u))) /* or is a normalized NaN */
548#else /* DUK_USE_PACKED_TVAL */
549#define DUK_DBLUNION_NORMALIZE_NAN_CHECK(u) /* nop: no need to normalize */
550#define DUK_DBLUNION_IS_NAN(u) DUK__DBLUNION_IS_NAN_FULL((u)) /* (DUK_ISNAN((u)->d)) */
551#define DUK_DBLUNION_IS_NORMALIZED_NAN(u) DUK__DBLUNION_IS_NAN_FULL((u)) /* (DUK_ISNAN((u)->d)) */
552#define DUK_DBLUNION_IS_NORMALIZED(u) 1 /* all doubles are considered normalized */
553#define DUK_DBLUNION_SET_NAN(u) \
554 do { \
555 /* in non-packed representation we don't care about which NaN is used */ \
556 (u)->d = DUK_DOUBLE_NAN; \
557 } while (0)
558#endif /* DUK_USE_PACKED_TVAL */
559
560#define DUK_DBLUNION_IS_ANYINF(u) DUK__DBLUNION_IS_ANYINF((u))
561#define DUK_DBLUNION_IS_POSINF(u) DUK__DBLUNION_IS_POSINF((u))
562#define DUK_DBLUNION_IS_NEGINF(u) DUK__DBLUNION_IS_NEGINF((u))
563
564#define DUK_DBLUNION_IS_ANYZERO(u) DUK__DBLUNION_IS_ANYZERO((u))
565#define DUK_DBLUNION_IS_POSZERO(u) DUK__DBLUNION_IS_POSZERO((u))
566#define DUK_DBLUNION_IS_NEGZERO(u) DUK__DBLUNION_IS_NEGZERO((u))
567
568/* XXX: native 64-bit byteswaps when available */
569
570/* 64-bit byteswap, same operation independent of target endianness. */
571#define DUK_DBLUNION_BSWAP64(u) \
572 do { \
573 duk_uint32_t duk__bswaptmp1, duk__bswaptmp2; \
574 duk__bswaptmp1 = (u)->ui[0]; \
575 duk__bswaptmp2 = (u)->ui[1]; \
576 duk__bswaptmp1 = DUK_BSWAP32(duk__bswaptmp1); \
577 duk__bswaptmp2 = DUK_BSWAP32(duk__bswaptmp2); \
578 (u)->ui[0] = duk__bswaptmp2; \
579 (u)->ui[1] = duk__bswaptmp1; \
580 } while (0)
581
582/* Byteswap an IEEE double in the duk_double_union from host to network
583 * order. For a big endian target this is a no-op.
584 */
585#if defined(DUK_USE_DOUBLE_LE)
586#define DUK_DBLUNION_DOUBLE_HTON(u) \
587 do { \
588 duk_uint32_t duk__bswaptmp1, duk__bswaptmp2; \
589 duk__bswaptmp1 = (u)->ui[0]; \
590 duk__bswaptmp2 = (u)->ui[1]; \
591 duk__bswaptmp1 = DUK_BSWAP32(duk__bswaptmp1); \
592 duk__bswaptmp2 = DUK_BSWAP32(duk__bswaptmp2); \
593 (u)->ui[0] = duk__bswaptmp2; \
594 (u)->ui[1] = duk__bswaptmp1; \
595 } while (0)
596#elif defined(DUK_USE_DOUBLE_ME)
597#define DUK_DBLUNION_DOUBLE_HTON(u) \
598 do { \
599 duk_uint32_t duk__bswaptmp1, duk__bswaptmp2; \
600 duk__bswaptmp1 = (u)->ui[0]; \
601 duk__bswaptmp2 = (u)->ui[1]; \
602 duk__bswaptmp1 = DUK_BSWAP32(duk__bswaptmp1); \
603 duk__bswaptmp2 = DUK_BSWAP32(duk__bswaptmp2); \
604 (u)->ui[0] = duk__bswaptmp1; \
605 (u)->ui[1] = duk__bswaptmp2; \
606 } while (0)
607#elif defined(DUK_USE_DOUBLE_BE)
608#define DUK_DBLUNION_DOUBLE_HTON(u) \
609 do { \
610 } while (0)
611#else
612#error internal error, double endianness insane
613#endif
614
615/* Reverse operation is the same. */
616#define DUK_DBLUNION_DOUBLE_NTOH(u) DUK_DBLUNION_DOUBLE_HTON((u))
617
618/* Some sign bit helpers. */
619#if defined(DUK_USE_64BIT_OPS)
620#define DUK_DBLUNION_HAS_SIGNBIT(u) (((u)->ull[DUK_DBL_IDX_ULL0] & DUK_U64_CONSTANT(0x8000000000000000)) != 0)
621#define DUK_DBLUNION_GET_SIGNBIT(u) (((u)->ull[DUK_DBL_IDX_ULL0] >> 63U))
622#else
623#define DUK_DBLUNION_HAS_SIGNBIT(u) (((u)->ui[DUK_DBL_IDX_UI0] & 0x80000000UL) != 0)
624#define DUK_DBLUNION_GET_SIGNBIT(u) (((u)->ui[DUK_DBL_IDX_UI0] >> 31U))
625#endif
626
627#endif /* DUK_DBLUNION_H_INCLUDED */
628/* #include duk_fltunion.h */
629/*
630 * Union to access IEEE float memory representation.
631 */
632
633#if !defined(DUK_FLTUNION_H_INCLUDED)
634#define DUK_FLTUNION_H_INCLUDED
635
636/* #include duk_internal.h -> already included */
637
639 float f;
640 duk_uint32_t ui[1];
641 duk_uint16_t us[2];
642 duk_uint8_t uc[4];
643};
644
646
647#if defined(DUK_USE_DOUBLE_LE) || defined(DUK_USE_DOUBLE_ME)
648#define DUK_FLT_IDX_UI0 0
649#define DUK_FLT_IDX_US0 1
650#define DUK_FLT_IDX_US1 0
651#define DUK_FLT_IDX_UC0 3
652#define DUK_FLT_IDX_UC1 2
653#define DUK_FLT_IDX_UC2 1
654#define DUK_FLT_IDX_UC3 0
655#elif defined(DUK_USE_DOUBLE_BE)
656#define DUK_FLT_IDX_UI0 0
657#define DUK_FLT_IDX_US0 0
658#define DUK_FLT_IDX_US1 1
659#define DUK_FLT_IDX_UC0 0
660#define DUK_FLT_IDX_UC1 1
661#define DUK_FLT_IDX_UC2 2
662#define DUK_FLT_IDX_UC3 3
663#else
664#error internal error
665#endif
666
667#endif /* DUK_FLTUNION_H_INCLUDED */
668/* #include duk_replacements.h */
669#if !defined(DUK_REPLACEMENTS_H_INCLUDED)
670#define DUK_REPLACEMENTS_H_INCLUDED
671
672#if !defined(DUK_SINGLE_FILE)
673#if defined(DUK_USE_COMPUTED_INFINITY)
674DUK_INTERNAL_DECL double duk_computed_infinity;
675#endif
676#if defined(DUK_USE_COMPUTED_NAN)
677DUK_INTERNAL_DECL double duk_computed_nan;
678#endif
679#endif /* !DUK_SINGLE_FILE */
680
681#if defined(DUK_USE_REPL_FPCLASSIFY)
683#endif
684#if defined(DUK_USE_REPL_SIGNBIT)
686#endif
687#if defined(DUK_USE_REPL_ISFINITE)
689#endif
690#if defined(DUK_USE_REPL_ISNAN)
692#endif
693#if defined(DUK_USE_REPL_ISINF)
695#endif
696
697#endif /* DUK_REPLACEMENTS_H_INCLUDED */
698/* #include duk_jmpbuf.h */
699/*
700 * Wrapper for jmp_buf.
701 *
702 * This is used because jmp_buf is an array type for backward compatibility.
703 * Wrapping jmp_buf in a struct makes pointer references, sizeof, etc,
704 * behave more intuitively.
705 *
706 * http://en.wikipedia.org/wiki/Setjmp.h#Member_types
707 */
708
709#if !defined(DUK_JMPBUF_H_INCLUDED)
710#define DUK_JMPBUF_H_INCLUDED
711
712#if defined(DUK_USE_CPP_EXCEPTIONS)
713struct duk_jmpbuf {
714 duk_small_int_t dummy; /* unused */
715};
716#else
719};
720#endif
721
722#endif /* DUK_JMPBUF_H_INCLUDED */
723/* #include duk_exception.h */
724/*
725 * Exceptions for Duktape internal throws when C++ exceptions are used
726 * for long control transfers.
727 */
728
729#if !defined(DUK_EXCEPTION_H_INCLUDED)
730#define DUK_EXCEPTION_H_INCLUDED
731
732#if defined(DUK_USE_CPP_EXCEPTIONS)
733/* Internal exception used as a setjmp-longjmp replacement. User code should
734 * NEVER see or catch this exception, so it doesn't inherit from any base
735 * class which should minimize the chance of user code accidentally catching
736 * the exception.
737 */
738class duk_internal_exception {
739 /* intentionally empty */
740};
741
742/* Fatal error, thrown as a specific C++ exception with C++ exceptions
743 * enabled. It is unsafe to continue; doing so may cause crashes or memory
744 * leaks. This is intended to be either uncaught, or caught by user code
745 * aware of the "unsafe to continue" semantics.
746 */
747class duk_fatal_exception : public virtual std::runtime_error {
748 public:
749 duk_fatal_exception(const char *message) : std::runtime_error(message) {
750 }
751};
752#endif
753
754#endif /* DUK_EXCEPTION_H_INCLUDED */
755/* #include duk_forwdecl.h */
756/*
757 * Forward declarations for all Duktape structures.
758 */
759
760#if !defined(DUK_FORWDECL_H_INCLUDED)
761#define DUK_FORWDECL_H_INCLUDED
762
763/*
764 * Forward declarations
765 */
766
767#if defined(DUK_USE_CPP_EXCEPTIONS)
768class duk_internal_exception;
769#else
770struct duk_jmpbuf;
771#endif
772
773/* duk_tval intentionally skipped */
774struct duk_heaphdr;
775struct duk_heaphdr_string;
776struct duk_harray;
777struct duk_hstring;
779struct duk_hobject;
780struct duk_hcompfunc;
781struct duk_hnatfunc;
782struct duk_hboundfunc;
783struct duk_hthread;
784struct duk_hbufobj;
785struct duk_hdecenv;
786struct duk_hobjenv;
787struct duk_hproxy;
788struct duk_hbuffer;
789struct duk_hbuffer_fixed;
792
793struct duk_propaccessor;
794union duk_propvalue;
795struct duk_propdesc;
796
797struct duk_heap;
798struct duk_breakpoint;
799
800struct duk_activation;
801struct duk_catcher;
802struct duk_ljstate;
803struct duk_strcache_entry;
804struct duk_litcache_entry;
805struct duk_strtab_entry;
806
807#if defined(DUK_USE_DEBUG)
808struct duk_fixedbuffer;
809#endif
810
811struct duk_bitdecoder_ctx;
812struct duk_bitencoder_ctx;
813struct duk_bufwriter_ctx;
814
815struct duk_token;
816struct duk_re_token;
817struct duk_lexer_point;
818struct duk_lexer_ctx;
820
821struct duk_compiler_instr;
822struct duk_compiler_func;
823struct duk_compiler_ctx;
824
825struct duk_re_matcher_ctx;
827
828#if defined(DUK_USE_CPP_EXCEPTIONS)
829/* no typedef */
830#else
831typedef struct duk_jmpbuf duk_jmpbuf;
832#endif
833
834/* duk_tval intentionally skipped */
837typedef struct duk_harray duk_harray;
848typedef struct duk_hproxy duk_hproxy;
853
857
858typedef struct duk_heap duk_heap;
860
867
868#if defined(DUK_USE_DEBUG)
869typedef struct duk_fixedbuffer duk_fixedbuffer;
870#endif
871
875
876typedef struct duk_token duk_token;
881
885
888
889#endif /* DUK_FORWDECL_H_INCLUDED */
890/* #include duk_tval.h */
891/*
892 * Tagged type definition (duk_tval) and accessor macros.
893 *
894 * Access all fields through the accessor macros, as the representation
895 * is quite tricky.
896 *
897 * There are two packed type alternatives: an 8-byte representation
898 * based on an IEEE double (preferred for compactness), and a 12-byte
899 * representation (portability). The latter is needed also in e.g.
900 * 64-bit environments (it usually pads to 16 bytes per value).
901 *
902 * Selecting the tagged type format involves many trade-offs (memory
903 * use, size and performance of generated code, portability, etc).
904 *
905 * NB: because macro arguments are often expressions, macros should
906 * avoid evaluating their argument more than once.
907 */
908
909#if !defined(DUK_TVAL_H_INCLUDED)
910#define DUK_TVAL_H_INCLUDED
911
912/* sanity */
913#if !defined(DUK_USE_DOUBLE_LE) && !defined(DUK_USE_DOUBLE_ME) && !defined(DUK_USE_DOUBLE_BE)
914#error unsupported: cannot determine byte order variant
915#endif
916
917#if defined(DUK_USE_PACKED_TVAL)
918/* ======================================================================== */
919
920/*
921 * Packed 8-byte representation
922 */
923
924/* use duk_double_union as duk_tval directly */
925typedef union duk_double_union duk_tval;
926typedef struct {
927 duk_uint16_t a;
928 duk_uint16_t b;
929 duk_uint16_t c;
930 duk_uint16_t d;
932
933/* tags */
934#define DUK_TAG_NORMALIZED_NAN 0x7ff8UL /* the NaN variant we use */
935/* avoid tag 0xfff0, no risk of confusion with negative infinity */
936#define DUK_TAG_MIN 0xfff1UL
937#if defined(DUK_USE_FASTINT)
938#define DUK_TAG_FASTINT 0xfff1UL /* embed: integer value */
939#endif
940#define DUK_TAG_UNUSED 0xfff2UL /* marker; not actual tagged value */
941#define DUK_TAG_UNDEFINED 0xfff3UL /* embed: nothing */
942#define DUK_TAG_NULL 0xfff4UL /* embed: nothing */
943#define DUK_TAG_BOOLEAN 0xfff5UL /* embed: 0 or 1 (false or true) */
944/* DUK_TAG_NUMBER would logically go here, but it has multiple 'tags' */
945#define DUK_TAG_POINTER 0xfff6UL /* embed: void ptr */
946#define DUK_TAG_LIGHTFUNC 0xfff7UL /* embed: func ptr */
947#define DUK_TAG_STRING 0xfff8UL /* embed: duk_hstring ptr */
948#define DUK_TAG_OBJECT 0xfff9UL /* embed: duk_hobject ptr */
949#define DUK_TAG_BUFFER 0xfffaUL /* embed: duk_hbuffer ptr */
950#define DUK_TAG_MAX 0xfffaUL
951
952/* for convenience */
953#define DUK_XTAG_BOOLEAN_FALSE 0xfff50000UL
954#define DUK_XTAG_BOOLEAN_TRUE 0xfff50001UL
955
956#define DUK_TVAL_IS_VALID_TAG(tv) (DUK_TVAL_GET_TAG((tv)) - DUK_TAG_MIN <= DUK_TAG_MAX - DUK_TAG_MIN)
957
958/* DUK_TVAL_UNUSED initializer for duk_tval_unused, works for any endianness. */
959#define DUK_TVAL_UNUSED_INITIALIZER() \
960 { DUK_TAG_UNUSED, DUK_TAG_UNUSED, DUK_TAG_UNUSED, DUK_TAG_UNUSED }
961
962/* two casts to avoid gcc warning: "warning: cast from pointer to integer of different size [-Wpointer-to-int-cast]" */
963#if defined(DUK_USE_64BIT_OPS)
964#if defined(DUK_USE_DOUBLE_ME)
965#define DUK__TVAL_SET_TAGGEDPOINTER(tv, h, tag) \
966 do { \
967 (tv)->ull[DUK_DBL_IDX_ULL0] = (((duk_uint64_t) (tag)) << 16) | (((duk_uint64_t) (duk_uint32_t) (h)) << 32); \
968 } while (0)
969#else
970#define DUK__TVAL_SET_TAGGEDPOINTER(tv, h, tag) \
971 do { \
972 (tv)->ull[DUK_DBL_IDX_ULL0] = (((duk_uint64_t) (tag)) << 48) | ((duk_uint64_t) (duk_uint32_t) (h)); \
973 } while (0)
974#endif
975#else /* DUK_USE_64BIT_OPS */
976#define DUK__TVAL_SET_TAGGEDPOINTER(tv, h, tag) \
977 do { \
978 duk_tval *duk__tv; \
979 duk__tv = (tv); \
980 duk__tv->ui[DUK_DBL_IDX_UI0] = ((duk_uint32_t) (tag)) << 16; \
981 duk__tv->ui[DUK_DBL_IDX_UI1] = (duk_uint32_t) (h); \
982 } while (0)
983#endif /* DUK_USE_64BIT_OPS */
984
985#if defined(DUK_USE_64BIT_OPS)
986/* Double casting for pointer to avoid gcc warning (cast from pointer to integer of different size) */
987#if defined(DUK_USE_DOUBLE_ME)
988#define DUK__TVAL_SET_LIGHTFUNC(tv, fp, flags) \
989 do { \
990 (tv)->ull[DUK_DBL_IDX_ULL0] = (((duk_uint64_t) DUK_TAG_LIGHTFUNC) << 16) | ((duk_uint64_t) (flags)) | \
991 (((duk_uint64_t) (duk_uint32_t) (fp)) << 32); \
992 } while (0)
993#else
994#define DUK__TVAL_SET_LIGHTFUNC(tv, fp, flags) \
995 do { \
996 (tv)->ull[DUK_DBL_IDX_ULL0] = (((duk_uint64_t) DUK_TAG_LIGHTFUNC) << 48) | (((duk_uint64_t) (flags)) << 32) | \
997 ((duk_uint64_t) (duk_uint32_t) (fp)); \
998 } while (0)
999#endif
1000#else /* DUK_USE_64BIT_OPS */
1001#define DUK__TVAL_SET_LIGHTFUNC(tv, fp, flags) \
1002 do { \
1003 duk_tval *duk__tv; \
1004 duk__tv = (tv); \
1005 duk__tv->ui[DUK_DBL_IDX_UI0] = (((duk_uint32_t) DUK_TAG_LIGHTFUNC) << 16) | ((duk_uint32_t) (flags)); \
1006 duk__tv->ui[DUK_DBL_IDX_UI1] = (duk_uint32_t) (fp); \
1007 } while (0)
1008#endif /* DUK_USE_64BIT_OPS */
1009
1010#if defined(DUK_USE_FASTINT)
1011/* Note: masking is done for 'i' to deal with negative numbers correctly */
1012#if defined(DUK_USE_DOUBLE_ME)
1013#define DUK__TVAL_SET_I48(tv, i) \
1014 do { \
1015 duk_tval *duk__tv; \
1016 duk__tv = (tv); \
1017 duk__tv->ui[DUK_DBL_IDX_UI0] = \
1018 ((duk_uint32_t) DUK_TAG_FASTINT) << 16 | (((duk_uint32_t) ((i) >> 32)) & 0x0000ffffUL); \
1019 duk__tv->ui[DUK_DBL_IDX_UI1] = (duk_uint32_t) (i); \
1020 } while (0)
1021#define DUK__TVAL_SET_U32(tv, i) \
1022 do { \
1023 duk_tval *duk__tv; \
1024 duk__tv = (tv); \
1025 duk__tv->ui[DUK_DBL_IDX_UI0] = ((duk_uint32_t) DUK_TAG_FASTINT) << 16; \
1026 duk__tv->ui[DUK_DBL_IDX_UI1] = (duk_uint32_t) (i); \
1027 } while (0)
1028#else
1029#define DUK__TVAL_SET_I48(tv, i) \
1030 do { \
1031 (tv)->ull[DUK_DBL_IDX_ULL0] = \
1032 (((duk_uint64_t) DUK_TAG_FASTINT) << 48) | (((duk_uint64_t) (i)) & DUK_U64_CONSTANT(0x0000ffffffffffff)); \
1033 } while (0)
1034#define DUK__TVAL_SET_U32(tv, i) \
1035 do { \
1036 (tv)->ull[DUK_DBL_IDX_ULL0] = (((duk_uint64_t) DUK_TAG_FASTINT) << 48) | (duk_uint64_t) (i); \
1037 } while (0)
1038#endif
1039
1040/* This needs to go through a cast because sign extension is needed. */
1041#define DUK__TVAL_SET_I32(tv, i) \
1042 do { \
1043 duk_int64_t duk__tmp = (duk_int64_t) (i); \
1044 DUK_TVAL_SET_I48((tv), duk__tmp); \
1045 } while (0)
1046
1047/* XXX: Clumsy sign extend and masking of 16 topmost bits. */
1048#if defined(DUK_USE_DOUBLE_ME)
1049#define DUK__TVAL_GET_FASTINT(tv) \
1050 (((duk_int64_t) ((((duk_uint64_t) (tv)->ui[DUK_DBL_IDX_UI0]) << 32) | ((duk_uint64_t) (tv)->ui[DUK_DBL_IDX_UI1]))) \
1051 << 16 >> \
1052 16)
1053#else
1054#define DUK__TVAL_GET_FASTINT(tv) ((((duk_int64_t) (tv)->ull[DUK_DBL_IDX_ULL0]) << 16) >> 16)
1055#endif
1056#define DUK__TVAL_GET_FASTINT_U32(tv) ((tv)->ui[DUK_DBL_IDX_UI1])
1057#define DUK__TVAL_GET_FASTINT_I32(tv) ((duk_int32_t) (tv)->ui[DUK_DBL_IDX_UI1])
1058#endif /* DUK_USE_FASTINT */
1059
1060#define DUK_TVAL_SET_UNDEFINED(tv) \
1061 do { \
1062 (tv)->us[DUK_DBL_IDX_US0] = (duk_uint16_t) DUK_TAG_UNDEFINED; \
1063 } while (0)
1064#define DUK_TVAL_SET_UNUSED(tv) \
1065 do { \
1066 (tv)->us[DUK_DBL_IDX_US0] = (duk_uint16_t) DUK_TAG_UNUSED; \
1067 } while (0)
1068#define DUK_TVAL_SET_NULL(tv) \
1069 do { \
1070 (tv)->us[DUK_DBL_IDX_US0] = (duk_uint16_t) DUK_TAG_NULL; \
1071 } while (0)
1072
1073#define DUK_TVAL_SET_BOOLEAN(tv, val) \
1074 DUK_DBLUNION_SET_HIGH32((tv), (((duk_uint32_t) DUK_TAG_BOOLEAN) << 16) | ((duk_uint32_t) (val)))
1075
1076#define DUK_TVAL_SET_NAN(tv) DUK_DBLUNION_SET_NAN_FULL((tv))
1077
1078/* Assumes that caller has normalized NaNs, otherwise trouble ahead. */
1079#if defined(DUK_USE_FASTINT)
1080#define DUK_TVAL_SET_DOUBLE(tv, d) \
1081 do { \
1082 duk_double_t duk__dblval; \
1083 duk__dblval = (d); \
1084 DUK_ASSERT_DOUBLE_IS_NORMALIZED(duk__dblval); \
1085 DUK_DBLUNION_SET_DOUBLE((tv), duk__dblval); \
1086 } while (0)
1087#define DUK_TVAL_SET_I48(tv, i) DUK__TVAL_SET_I48((tv), (i))
1088#define DUK_TVAL_SET_I32(tv, i) DUK__TVAL_SET_I32((tv), (i))
1089#define DUK_TVAL_SET_U32(tv, i) DUK__TVAL_SET_U32((tv), (i))
1090#define DUK_TVAL_SET_NUMBER_CHKFAST_FAST(tv, d) duk_tval_set_number_chkfast_fast((tv), (d))
1091#define DUK_TVAL_SET_NUMBER_CHKFAST_SLOW(tv, d) duk_tval_set_number_chkfast_slow((tv), (d))
1092#define DUK_TVAL_SET_NUMBER(tv, d) DUK_TVAL_SET_DOUBLE((tv), (d))
1093#define DUK_TVAL_CHKFAST_INPLACE_FAST(tv) \
1094 do { \
1095 duk_tval *duk__tv; \
1096 duk_double_t duk__d; \
1097 duk__tv = (tv); \
1098 if (DUK_TVAL_IS_DOUBLE(duk__tv)) { \
1099 duk__d = DUK_TVAL_GET_DOUBLE(duk__tv); \
1100 DUK_TVAL_SET_NUMBER_CHKFAST_FAST(duk__tv, duk__d); \
1101 } \
1102 } while (0)
1103#define DUK_TVAL_CHKFAST_INPLACE_SLOW(tv) \
1104 do { \
1105 duk_tval *duk__tv; \
1106 duk_double_t duk__d; \
1107 duk__tv = (tv); \
1108 if (DUK_TVAL_IS_DOUBLE(duk__tv)) { \
1109 duk__d = DUK_TVAL_GET_DOUBLE(duk__tv); \
1110 DUK_TVAL_SET_NUMBER_CHKFAST_SLOW(duk__tv, duk__d); \
1111 } \
1112 } while (0)
1113#else /* DUK_USE_FASTINT */
1114#define DUK_TVAL_SET_DOUBLE(tv, d) \
1115 do { \
1116 duk_double_t duk__dblval; \
1117 duk__dblval = (d); \
1118 DUK_ASSERT_DOUBLE_IS_NORMALIZED(duk__dblval); \
1119 DUK_DBLUNION_SET_DOUBLE((tv), duk__dblval); \
1120 } while (0)
1121#define DUK_TVAL_SET_I48(tv, i) DUK_TVAL_SET_DOUBLE((tv), (duk_double_t) (i)) /* XXX: fast int-to-double */
1122#define DUK_TVAL_SET_I32(tv, i) DUK_TVAL_SET_DOUBLE((tv), (duk_double_t) (i))
1123#define DUK_TVAL_SET_U32(tv, i) DUK_TVAL_SET_DOUBLE((tv), (duk_double_t) (i))
1124#define DUK_TVAL_SET_NUMBER_CHKFAST_FAST(tv, d) DUK_TVAL_SET_DOUBLE((tv), (d))
1125#define DUK_TVAL_SET_NUMBER_CHKFAST_SLOW(tv, d) DUK_TVAL_SET_DOUBLE((tv), (d))
1126#define DUK_TVAL_SET_NUMBER(tv, d) DUK_TVAL_SET_DOUBLE((tv), (d))
1127#define DUK_TVAL_CHKFAST_INPLACE_FAST(tv) \
1128 do { \
1129 } while (0)
1130#define DUK_TVAL_CHKFAST_INPLACE_SLOW(tv) \
1131 do { \
1132 } while (0)
1133#endif /* DUK_USE_FASTINT */
1134
1135#define DUK_TVAL_SET_FASTINT(tv, i) DUK_TVAL_SET_I48((tv), (i)) /* alias */
1136
1137#define DUK_TVAL_SET_LIGHTFUNC(tv, fp, flags) DUK__TVAL_SET_LIGHTFUNC((tv), (fp), (flags))
1138#define DUK_TVAL_SET_STRING(tv, h) DUK__TVAL_SET_TAGGEDPOINTER((tv), (h), DUK_TAG_STRING)
1139#define DUK_TVAL_SET_OBJECT(tv, h) DUK__TVAL_SET_TAGGEDPOINTER((tv), (h), DUK_TAG_OBJECT)
1140#define DUK_TVAL_SET_BUFFER(tv, h) DUK__TVAL_SET_TAGGEDPOINTER((tv), (h), DUK_TAG_BUFFER)
1141#define DUK_TVAL_SET_POINTER(tv, p) DUK__TVAL_SET_TAGGEDPOINTER((tv), (p), DUK_TAG_POINTER)
1142
1143#define DUK_TVAL_SET_TVAL(tv, x) \
1144 do { \
1145 *(tv) = *(x); \
1146 } while (0)
1147
1148/* getters */
1149#define DUK_TVAL_GET_BOOLEAN(tv) ((duk_small_uint_t) (tv)->us[DUK_DBL_IDX_US1])
1150#if defined(DUK_USE_FASTINT)
1151#define DUK_TVAL_GET_DOUBLE(tv) ((tv)->d)
1152#define DUK_TVAL_GET_FASTINT(tv) DUK__TVAL_GET_FASTINT((tv))
1153#define DUK_TVAL_GET_FASTINT_U32(tv) DUK__TVAL_GET_FASTINT_U32((tv))
1154#define DUK_TVAL_GET_FASTINT_I32(tv) DUK__TVAL_GET_FASTINT_I32((tv))
1155#define DUK_TVAL_GET_NUMBER(tv) duk_tval_get_number_packed((tv))
1156#else
1157#define DUK_TVAL_GET_NUMBER(tv) ((tv)->d)
1158#define DUK_TVAL_GET_DOUBLE(tv) ((tv)->d)
1159#endif
1160#define DUK_TVAL_GET_LIGHTFUNC(tv, out_fp, out_flags) \
1161 do { \
1162 (out_flags) = (tv)->ui[DUK_DBL_IDX_UI0] & 0xffffUL; \
1163 (out_fp) = (duk_c_function) (tv)->ui[DUK_DBL_IDX_UI1]; \
1164 } while (0)
1165#define DUK_TVAL_GET_LIGHTFUNC_FUNCPTR(tv) ((duk_c_function) ((tv)->ui[DUK_DBL_IDX_UI1]))
1166#define DUK_TVAL_GET_LIGHTFUNC_FLAGS(tv) (((duk_small_uint_t) (tv)->ui[DUK_DBL_IDX_UI0]) & 0xffffUL)
1167#define DUK_TVAL_GET_STRING(tv) ((duk_hstring *) (tv)->vp[DUK_DBL_IDX_VP1])
1168#define DUK_TVAL_GET_OBJECT(tv) ((duk_hobject *) (tv)->vp[DUK_DBL_IDX_VP1])
1169#define DUK_TVAL_GET_BUFFER(tv) ((duk_hbuffer *) (tv)->vp[DUK_DBL_IDX_VP1])
1170#define DUK_TVAL_GET_POINTER(tv) ((void *) (tv)->vp[DUK_DBL_IDX_VP1])
1171#define DUK_TVAL_GET_HEAPHDR(tv) ((duk_heaphdr *) (tv)->vp[DUK_DBL_IDX_VP1])
1172
1173/* decoding */
1174#define DUK_TVAL_GET_TAG(tv) ((duk_small_uint_t) (tv)->us[DUK_DBL_IDX_US0])
1175
1176#define DUK_TVAL_IS_UNDEFINED(tv) (DUK_TVAL_GET_TAG((tv)) == DUK_TAG_UNDEFINED)
1177#define DUK_TVAL_IS_UNUSED(tv) (DUK_TVAL_GET_TAG((tv)) == DUK_TAG_UNUSED)
1178#define DUK_TVAL_IS_NULL(tv) (DUK_TVAL_GET_TAG((tv)) == DUK_TAG_NULL)
1179#define DUK_TVAL_IS_BOOLEAN(tv) (DUK_TVAL_GET_TAG((tv)) == DUK_TAG_BOOLEAN)
1180#define DUK_TVAL_IS_BOOLEAN_TRUE(tv) ((tv)->ui[DUK_DBL_IDX_UI0] == DUK_XTAG_BOOLEAN_TRUE)
1181#define DUK_TVAL_IS_BOOLEAN_FALSE(tv) ((tv)->ui[DUK_DBL_IDX_UI0] == DUK_XTAG_BOOLEAN_FALSE)
1182#define DUK_TVAL_IS_LIGHTFUNC(tv) (DUK_TVAL_GET_TAG((tv)) == DUK_TAG_LIGHTFUNC)
1183#define DUK_TVAL_IS_STRING(tv) (DUK_TVAL_GET_TAG((tv)) == DUK_TAG_STRING)
1184#define DUK_TVAL_IS_OBJECT(tv) (DUK_TVAL_GET_TAG((tv)) == DUK_TAG_OBJECT)
1185#define DUK_TVAL_IS_BUFFER(tv) (DUK_TVAL_GET_TAG((tv)) == DUK_TAG_BUFFER)
1186#define DUK_TVAL_IS_POINTER(tv) (DUK_TVAL_GET_TAG((tv)) == DUK_TAG_POINTER)
1187#if defined(DUK_USE_FASTINT)
1188/* 0xfff0 is -Infinity */
1189#define DUK_TVAL_IS_DOUBLE(tv) (DUK_TVAL_GET_TAG((tv)) <= 0xfff0UL)
1190#define DUK_TVAL_IS_FASTINT(tv) (DUK_TVAL_GET_TAG((tv)) == DUK_TAG_FASTINT)
1191#define DUK_TVAL_IS_NUMBER(tv) (DUK_TVAL_GET_TAG((tv)) <= 0xfff1UL)
1192#else
1193#define DUK_TVAL_IS_NUMBER(tv) (DUK_TVAL_GET_TAG((tv)) <= 0xfff0UL)
1194#define DUK_TVAL_IS_DOUBLE(tv) DUK_TVAL_IS_NUMBER((tv))
1195#endif
1196
1197/* This is performance critical because it appears in every DECREF. */
1198#define DUK_TVAL_IS_HEAP_ALLOCATED(tv) (DUK_TVAL_GET_TAG((tv)) >= DUK_TAG_STRING)
1199
1200#if defined(DUK_USE_FASTINT)
1201DUK_INTERNAL_DECL duk_double_t duk_tval_get_number_packed(duk_tval *tv);
1202#endif
1203
1204#else /* DUK_USE_PACKED_TVAL */
1205/* ======================================================================== */
1206
1207/*
1208 * Portable 12-byte representation
1209 */
1210
1211/* Note: not initializing all bytes is normally not an issue: Duktape won't
1212 * read or use the uninitialized bytes so valgrind won't issue warnings.
1213 * In some special cases a harmless valgrind warning may be issued though.
1214 * For example, the DumpHeap debugger command writes out a compiled function's
1215 * 'data' area as is, including any uninitialized bytes, which causes a
1216 * valgrind warning.
1217 */
1218
1220
1224 union {
1227#if defined(DUK_USE_FASTINT)
1228 duk_int64_t fi; /* if present, forces 16-byte duk_tval */
1229#endif
1230 void *voidptr;
1239 } v;
1240};
1241
1242typedef struct {
1245 /* The rest of the fields don't matter except for debug dumps and such
1246 * for which a partial initializer may trigger out-ot-bounds memory
1247 * reads. Include a double field which is usually as large or larger
1248 * than pointers (not always however).
1249 */
1252
1253#define DUK_TVAL_UNUSED_INITIALIZER() \
1254 { DUK_TAG_UNUSED, 0, 0.0 }
1255
1256#define DUK_TAG_MIN 0
1257#define DUK_TAG_NUMBER 0 /* DUK_TAG_NUMBER only defined for non-packed duk_tval */
1258#if defined(DUK_USE_FASTINT)
1259#define DUK_TAG_FASTINT 1
1260#endif
1261#define DUK_TAG_UNDEFINED 2
1262#define DUK_TAG_NULL 3
1263#define DUK_TAG_BOOLEAN 4
1264#define DUK_TAG_POINTER 5
1265#define DUK_TAG_LIGHTFUNC 6
1266#define DUK_TAG_UNUSED 7 /* marker; not actual tagged type */
1267#define DUK_TAG_STRING 8 /* first heap allocated, match bit boundary */
1268#define DUK_TAG_OBJECT 9
1269#define DUK_TAG_BUFFER 10
1270#define DUK_TAG_MAX 10
1271
1272#define DUK_TVAL_IS_VALID_TAG(tv) (DUK_TVAL_GET_TAG((tv)) - DUK_TAG_MIN <= DUK_TAG_MAX - DUK_TAG_MIN)
1273
1274/* DUK_TAG_NUMBER is intentionally first, as it is the default clause in code
1275 * to support the 8-byte representation. Further, it is a non-heap-allocated
1276 * type so it should come before DUK_TAG_STRING. Finally, it should not break
1277 * the tag value ranges covered by case-clauses in a switch-case.
1278 */
1279
1280/* setters */
1281#define DUK_TVAL_SET_UNDEFINED(tv) \
1282 do { \
1283 duk_tval *duk__tv; \
1284 duk__tv = (tv); \
1285 duk__tv->t = DUK_TAG_UNDEFINED; \
1286 } while (0)
1287
1288#define DUK_TVAL_SET_UNUSED(tv) \
1289 do { \
1290 duk_tval *duk__tv; \
1291 duk__tv = (tv); \
1292 duk__tv->t = DUK_TAG_UNUSED; \
1293 } while (0)
1294
1295#define DUK_TVAL_SET_NULL(tv) \
1296 do { \
1297 duk_tval *duk__tv; \
1298 duk__tv = (tv); \
1299 duk__tv->t = DUK_TAG_NULL; \
1300 } while (0)
1301
1302#define DUK_TVAL_SET_BOOLEAN(tv, val) \
1303 do { \
1304 duk_tval *duk__tv; \
1305 duk__tv = (tv); \
1306 duk__tv->t = DUK_TAG_BOOLEAN; \
1307 duk__tv->v.i = (duk_small_int_t) (val); \
1308 } while (0)
1309
1310#if defined(DUK_USE_FASTINT)
1311#define DUK_TVAL_SET_DOUBLE(tv, val) \
1312 do { \
1313 duk_tval *duk__tv; \
1314 duk_double_t duk__dblval; \
1315 duk__dblval = (val); \
1316 DUK_ASSERT_DOUBLE_IS_NORMALIZED(duk__dblval); /* nop for unpacked duk_tval */ \
1317 duk__tv = (tv); \
1318 duk__tv->t = DUK_TAG_NUMBER; \
1319 duk__tv->v.d = duk__dblval; \
1320 } while (0)
1321#define DUK_TVAL_SET_I48(tv, val) \
1322 do { \
1323 duk_tval *duk__tv; \
1324 duk__tv = (tv); \
1325 duk__tv->t = DUK_TAG_FASTINT; \
1326 duk__tv->v.fi = (val); \
1327 } while (0)
1328#define DUK_TVAL_SET_U32(tv, val) \
1329 do { \
1330 duk_tval *duk__tv; \
1331 duk__tv = (tv); \
1332 duk__tv->t = DUK_TAG_FASTINT; \
1333 duk__tv->v.fi = (duk_int64_t) (val); \
1334 } while (0)
1335#define DUK_TVAL_SET_I32(tv, val) \
1336 do { \
1337 duk_tval *duk__tv; \
1338 duk__tv = (tv); \
1339 duk__tv->t = DUK_TAG_FASTINT; \
1340 duk__tv->v.fi = (duk_int64_t) (val); \
1341 } while (0)
1342#define DUK_TVAL_SET_NUMBER_CHKFAST_FAST(tv, d) duk_tval_set_number_chkfast_fast((tv), (d))
1343#define DUK_TVAL_SET_NUMBER_CHKFAST_SLOW(tv, d) duk_tval_set_number_chkfast_slow((tv), (d))
1344#define DUK_TVAL_SET_NUMBER(tv, val) DUK_TVAL_SET_DOUBLE((tv), (val))
1345#define DUK_TVAL_CHKFAST_INPLACE_FAST(tv) \
1346 do { \
1347 duk_tval *duk__tv; \
1348 duk_double_t duk__d; \
1349 duk__tv = (tv); \
1350 if (DUK_TVAL_IS_DOUBLE(duk__tv)) { \
1351 duk__d = DUK_TVAL_GET_DOUBLE(duk__tv); \
1352 DUK_TVAL_SET_NUMBER_CHKFAST_FAST(duk__tv, duk__d); \
1353 } \
1354 } while (0)
1355#define DUK_TVAL_CHKFAST_INPLACE_SLOW(tv) \
1356 do { \
1357 duk_tval *duk__tv; \
1358 duk_double_t duk__d; \
1359 duk__tv = (tv); \
1360 if (DUK_TVAL_IS_DOUBLE(duk__tv)) { \
1361 duk__d = DUK_TVAL_GET_DOUBLE(duk__tv); \
1362 DUK_TVAL_SET_NUMBER_CHKFAST_SLOW(duk__tv, duk__d); \
1363 } \
1364 } while (0)
1365#else /* DUK_USE_FASTINT */
1366#define DUK_TVAL_SET_DOUBLE(tv, d) DUK_TVAL_SET_NUMBER((tv), (d))
1367#define DUK_TVAL_SET_I48(tv, val) DUK_TVAL_SET_NUMBER((tv), (duk_double_t) (val)) /* XXX: fast int-to-double */
1368#define DUK_TVAL_SET_U32(tv, val) DUK_TVAL_SET_NUMBER((tv), (duk_double_t) (val))
1369#define DUK_TVAL_SET_I32(tv, val) DUK_TVAL_SET_NUMBER((tv), (duk_double_t) (val))
1370#define DUK_TVAL_SET_NUMBER(tv, val) \
1371 do { \
1372 duk_tval *duk__tv; \
1373 duk_double_t duk__dblval; \
1374 duk__dblval = (val); \
1375 DUK_ASSERT_DOUBLE_IS_NORMALIZED(duk__dblval); /* nop for unpacked duk_tval */ \
1376 duk__tv = (tv); \
1377 duk__tv->t = DUK_TAG_NUMBER; \
1378 duk__tv->v.d = duk__dblval; \
1379 } while (0)
1380#define DUK_TVAL_SET_NUMBER_CHKFAST_FAST(tv, d) DUK_TVAL_SET_NUMBER((tv), (d))
1381#define DUK_TVAL_SET_NUMBER_CHKFAST_SLOW(tv, d) DUK_TVAL_SET_NUMBER((tv), (d))
1382#define DUK_TVAL_CHKFAST_INPLACE_FAST(tv) \
1383 do { \
1384 } while (0)
1385#define DUK_TVAL_CHKFAST_INPLACE_SLOW(tv) \
1386 do { \
1387 } while (0)
1388#endif /* DUK_USE_FASTINT */
1389
1390#define DUK_TVAL_SET_FASTINT(tv, i) DUK_TVAL_SET_I48((tv), (i)) /* alias */
1391
1392#define DUK_TVAL_SET_POINTER(tv, hptr) \
1393 do { \
1394 duk_tval *duk__tv; \
1395 duk__tv = (tv); \
1396 duk__tv->t = DUK_TAG_POINTER; \
1397 duk__tv->v.voidptr = (hptr); \
1398 } while (0)
1399
1400#define DUK_TVAL_SET_LIGHTFUNC(tv, fp, flags) \
1401 do { \
1402 duk_tval *duk__tv; \
1403 duk__tv = (tv); \
1404 duk__tv->t = DUK_TAG_LIGHTFUNC; \
1405 duk__tv->v_extra = (flags); \
1406 duk__tv->v.lightfunc = (duk_c_function) (fp); \
1407 } while (0)
1408
1409#define DUK_TVAL_SET_STRING(tv, hptr) \
1410 do { \
1411 duk_tval *duk__tv; \
1412 duk__tv = (tv); \
1413 duk__tv->t = DUK_TAG_STRING; \
1414 duk__tv->v.hstring = (hptr); \
1415 } while (0)
1416
1417#define DUK_TVAL_SET_OBJECT(tv, hptr) \
1418 do { \
1419 duk_tval *duk__tv; \
1420 duk__tv = (tv); \
1421 duk__tv->t = DUK_TAG_OBJECT; \
1422 duk__tv->v.hobject = (hptr); \
1423 } while (0)
1424
1425#define DUK_TVAL_SET_BUFFER(tv, hptr) \
1426 do { \
1427 duk_tval *duk__tv; \
1428 duk__tv = (tv); \
1429 duk__tv->t = DUK_TAG_BUFFER; \
1430 duk__tv->v.hbuffer = (hptr); \
1431 } while (0)
1432
1433#define DUK_TVAL_SET_NAN(tv) \
1434 do { \
1435 /* in non-packed representation we don't care about which NaN is used */ \
1436 duk_tval *duk__tv; \
1437 duk__tv = (tv); \
1438 duk__tv->t = DUK_TAG_NUMBER; \
1439 duk__tv->v.d = DUK_DOUBLE_NAN; \
1440 } while (0)
1441
1442#define DUK_TVAL_SET_TVAL(tv, x) \
1443 do { \
1444 *(tv) = *(x); \
1445 } while (0)
1446
1447/* getters */
1448#define DUK_TVAL_GET_BOOLEAN(tv) ((duk_small_uint_t) (tv)->v.i)
1449#if defined(DUK_USE_FASTINT)
1450#define DUK_TVAL_GET_DOUBLE(tv) ((tv)->v.d)
1451#define DUK_TVAL_GET_FASTINT(tv) ((tv)->v.fi)
1452#define DUK_TVAL_GET_FASTINT_U32(tv) ((duk_uint32_t) ((tv)->v.fi))
1453#define DUK_TVAL_GET_FASTINT_I32(tv) ((duk_int32_t) ((tv)->v.fi))
1454#if 0
1455#define DUK_TVAL_GET_NUMBER(tv) (DUK_TVAL_IS_FASTINT((tv)) ? (duk_double_t) DUK_TVAL_GET_FASTINT((tv)) : DUK_TVAL_GET_DOUBLE((tv)))
1456#define DUK_TVAL_GET_NUMBER(tv) duk_tval_get_number_unpacked((tv))
1457#else
1458/* This seems reasonable overall. */
1459#define DUK_TVAL_GET_NUMBER(tv) (DUK_TVAL_IS_FASTINT((tv)) ? duk_tval_get_number_unpacked_fastint((tv)) : DUK_TVAL_GET_DOUBLE((tv)))
1460#endif
1461#else
1462#define DUK_TVAL_GET_NUMBER(tv) ((tv)->v.d)
1463#define DUK_TVAL_GET_DOUBLE(tv) ((tv)->v.d)
1464#endif /* DUK_USE_FASTINT */
1465#define DUK_TVAL_GET_POINTER(tv) ((tv)->v.voidptr)
1466#define DUK_TVAL_GET_LIGHTFUNC(tv, out_fp, out_flags) \
1467 do { \
1468 (out_flags) = (duk_uint32_t) (tv)->v_extra; \
1469 (out_fp) = (tv)->v.lightfunc; \
1470 } while (0)
1471#define DUK_TVAL_GET_LIGHTFUNC_FUNCPTR(tv) ((tv)->v.lightfunc)
1472#define DUK_TVAL_GET_LIGHTFUNC_FLAGS(tv) ((duk_small_uint_t) ((tv)->v_extra))
1473#define DUK_TVAL_GET_STRING(tv) ((tv)->v.hstring)
1474#define DUK_TVAL_GET_OBJECT(tv) ((tv)->v.hobject)
1475#define DUK_TVAL_GET_BUFFER(tv) ((tv)->v.hbuffer)
1476#define DUK_TVAL_GET_HEAPHDR(tv) ((tv)->v.heaphdr)
1477
1478/* decoding */
1479#define DUK_TVAL_GET_TAG(tv) ((tv)->t)
1480#define DUK_TVAL_IS_UNDEFINED(tv) ((tv)->t == DUK_TAG_UNDEFINED)
1481#define DUK_TVAL_IS_UNUSED(tv) ((tv)->t == DUK_TAG_UNUSED)
1482#define DUK_TVAL_IS_NULL(tv) ((tv)->t == DUK_TAG_NULL)
1483#define DUK_TVAL_IS_BOOLEAN(tv) ((tv)->t == DUK_TAG_BOOLEAN)
1484#define DUK_TVAL_IS_BOOLEAN_TRUE(tv) (((tv)->t == DUK_TAG_BOOLEAN) && ((tv)->v.i != 0))
1485#define DUK_TVAL_IS_BOOLEAN_FALSE(tv) (((tv)->t == DUK_TAG_BOOLEAN) && ((tv)->v.i == 0))
1486#if defined(DUK_USE_FASTINT)
1487#define DUK_TVAL_IS_DOUBLE(tv) ((tv)->t == DUK_TAG_NUMBER)
1488#define DUK_TVAL_IS_FASTINT(tv) ((tv)->t == DUK_TAG_FASTINT)
1489#define DUK_TVAL_IS_NUMBER(tv) ((tv)->t == DUK_TAG_NUMBER || (tv)->t == DUK_TAG_FASTINT)
1490#else
1491#define DUK_TVAL_IS_NUMBER(tv) ((tv)->t == DUK_TAG_NUMBER)
1492#define DUK_TVAL_IS_DOUBLE(tv) DUK_TVAL_IS_NUMBER((tv))
1493#endif /* DUK_USE_FASTINT */
1494#define DUK_TVAL_IS_POINTER(tv) ((tv)->t == DUK_TAG_POINTER)
1495#define DUK_TVAL_IS_LIGHTFUNC(tv) ((tv)->t == DUK_TAG_LIGHTFUNC)
1496#define DUK_TVAL_IS_STRING(tv) ((tv)->t == DUK_TAG_STRING)
1497#define DUK_TVAL_IS_OBJECT(tv) ((tv)->t == DUK_TAG_OBJECT)
1498#define DUK_TVAL_IS_BUFFER(tv) ((tv)->t == DUK_TAG_BUFFER)
1499
1500/* This is performance critical because it's needed for every DECREF.
1501 * Take advantage of the fact that the first heap allocated tag is 8,
1502 * so that bit 3 is set for all heap allocated tags (and never set for
1503 * non-heap-allocated tags).
1504 */
1505#if 0
1506#define DUK_TVAL_IS_HEAP_ALLOCATED(tv) ((tv)->t >= DUK_TAG_STRING)
1507#endif
1508#define DUK_TVAL_IS_HEAP_ALLOCATED(tv) ((tv)->t & 0x08)
1509
1510#if defined(DUK_USE_FASTINT)
1511#if 0
1512DUK_INTERNAL_DECL duk_double_t duk_tval_get_number_unpacked(duk_tval *tv);
1513#endif
1515#endif
1516
1517#endif /* DUK_USE_PACKED_TVAL */
1518
1519/*
1520 * Convenience (independent of representation)
1521 */
1522
1523#define DUK_TVAL_SET_BOOLEAN_TRUE(tv) DUK_TVAL_SET_BOOLEAN((tv), 1)
1524#define DUK_TVAL_SET_BOOLEAN_FALSE(tv) DUK_TVAL_SET_BOOLEAN((tv), 0)
1525
1526#define DUK_TVAL_STRING_IS_SYMBOL(tv) DUK_HSTRING_HAS_SYMBOL(DUK_TVAL_GET_STRING((tv)))
1527
1528/* Lightfunc flags packing and unpacking. */
1529/* Sign extend: 0x0000##00 -> 0x##000000 -> sign extend to 0xssssss##.
1530 * Avoid signed shifts due to portability limitations.
1531 */
1532#define DUK_LFUNC_FLAGS_GET_MAGIC(lf_flags) ((duk_int32_t) (duk_int8_t) (((duk_uint16_t) (lf_flags)) >> 8))
1533#define DUK_LFUNC_FLAGS_GET_LENGTH(lf_flags) (((lf_flags) >> 4) & 0x0fU)
1534#define DUK_LFUNC_FLAGS_GET_NARGS(lf_flags) ((lf_flags) &0x0fU)
1535#define DUK_LFUNC_FLAGS_PACK(magic, length, nargs) ((((duk_small_uint_t) (magic)) & 0xffU) << 8) | ((length) << 4) | (nargs)
1536
1537#define DUK_LFUNC_NARGS_VARARGS 0x0f /* varargs marker */
1538#define DUK_LFUNC_NARGS_MIN 0x00
1539#define DUK_LFUNC_NARGS_MAX 0x0e /* max, excl. varargs marker */
1540#define DUK_LFUNC_LENGTH_MIN 0x00
1541#define DUK_LFUNC_LENGTH_MAX 0x0f
1542#define DUK_LFUNC_MAGIC_MIN (-0x80)
1543#define DUK_LFUNC_MAGIC_MAX 0x7f
1544
1545/* fastint constants etc */
1546#if defined(DUK_USE_FASTINT)
1547#define DUK_FASTINT_MIN (DUK_I64_CONSTANT(-0x800000000000))
1548#define DUK_FASTINT_MAX (DUK_I64_CONSTANT(0x7fffffffffff))
1549#define DUK_FASTINT_BITS 48
1550
1553#endif
1554
1555#if defined(DUK_USE_ASSERTIONS)
1556DUK_INTERNAL_DECL void duk_tval_assert_valid(duk_tval *tv);
1557#define DUK_TVAL_ASSERT_VALID(tv) \
1558 do { \
1559 duk_tval_assert_valid((tv)); \
1560 } while (0)
1561#else
1562#define DUK_TVAL_ASSERT_VALID(tv) \
1563 do { \
1564 } while (0)
1565#endif
1566
1567#endif /* DUK_TVAL_H_INCLUDED */
1568/* #include duk_builtins.h */
1569/*
1570 * Automatically generated by genbuiltins.py, do not edit!
1571 */
1572
1573#if !defined(DUK_BUILTINS_H_INCLUDED)
1574#define DUK_BUILTINS_H_INCLUDED
1575
1576#if defined(DUK_USE_ROM_STRINGS)
1577#error ROM support not enabled, rerun configure.py with --rom-support
1578#else /* DUK_USE_ROM_STRINGS */
1579#define DUK_STRIDX_UC_UNDEFINED 0 /* 'Undefined' */
1580#define DUK_HEAP_STRING_UC_UNDEFINED(heap) DUK_HEAP_GET_STRING((heap),DUK_STRIDX_UC_UNDEFINED)
1581#define DUK_HTHREAD_STRING_UC_UNDEFINED(thr) DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_UC_UNDEFINED)
1582#define DUK_STRIDX_UC_NULL 1 /* 'Null' */
1583#define DUK_HEAP_STRING_UC_NULL(heap) DUK_HEAP_GET_STRING((heap),DUK_STRIDX_UC_NULL)
1584#define DUK_HTHREAD_STRING_UC_NULL(thr) DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_UC_NULL)
1585#define DUK_STRIDX_UC_SYMBOL 2 /* 'Symbol' */
1586#define DUK_HEAP_STRING_UC_SYMBOL(heap) DUK_HEAP_GET_STRING((heap),DUK_STRIDX_UC_SYMBOL)
1587#define DUK_HTHREAD_STRING_UC_SYMBOL(thr) DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_UC_SYMBOL)
1588#define DUK_STRIDX_UC_ARGUMENTS 3 /* 'Arguments' */
1589#define DUK_HEAP_STRING_UC_ARGUMENTS(heap) DUK_HEAP_GET_STRING((heap),DUK_STRIDX_UC_ARGUMENTS)
1590#define DUK_HTHREAD_STRING_UC_ARGUMENTS(thr) DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_UC_ARGUMENTS)
1591#define DUK_STRIDX_UC_OBJECT 4 /* 'Object' */
1592#define DUK_HEAP_STRING_UC_OBJECT(heap) DUK_HEAP_GET_STRING((heap),DUK_STRIDX_UC_OBJECT)
1593#define DUK_HTHREAD_STRING_UC_OBJECT(thr) DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_UC_OBJECT)
1594#define DUK_STRIDX_UC_FUNCTION 5 /* 'Function' */
1595#define DUK_HEAP_STRING_UC_FUNCTION(heap) DUK_HEAP_GET_STRING((heap),DUK_STRIDX_UC_FUNCTION)
1596#define DUK_HTHREAD_STRING_UC_FUNCTION(thr) DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_UC_FUNCTION)
1597#define DUK_STRIDX_UC_ARRAY 6 /* 'Array' */
1598#define DUK_HEAP_STRING_UC_ARRAY(heap) DUK_HEAP_GET_STRING((heap),DUK_STRIDX_UC_ARRAY)
1599#define DUK_HTHREAD_STRING_UC_ARRAY(thr) DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_UC_ARRAY)
1600#define DUK_STRIDX_UC_STRING 7 /* 'String' */
1601#define DUK_HEAP_STRING_UC_STRING(heap) DUK_HEAP_GET_STRING((heap),DUK_STRIDX_UC_STRING)
1602#define DUK_HTHREAD_STRING_UC_STRING(thr) DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_UC_STRING)
1603#define DUK_STRIDX_UC_BOOLEAN 8 /* 'Boolean' */
1604#define DUK_HEAP_STRING_UC_BOOLEAN(heap) DUK_HEAP_GET_STRING((heap),DUK_STRIDX_UC_BOOLEAN)
1605#define DUK_HTHREAD_STRING_UC_BOOLEAN(thr) DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_UC_BOOLEAN)
1606#define DUK_STRIDX_UC_NUMBER 9 /* 'Number' */
1607#define DUK_HEAP_STRING_UC_NUMBER(heap) DUK_HEAP_GET_STRING((heap),DUK_STRIDX_UC_NUMBER)
1608#define DUK_HTHREAD_STRING_UC_NUMBER(thr) DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_UC_NUMBER)
1609#define DUK_STRIDX_UC_DATE 10 /* 'Date' */
1610#define DUK_HEAP_STRING_UC_DATE(heap) DUK_HEAP_GET_STRING((heap),DUK_STRIDX_UC_DATE)
1611#define DUK_HTHREAD_STRING_UC_DATE(thr) DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_UC_DATE)
1612#define DUK_STRIDX_REG_EXP 11 /* 'RegExp' */
1613#define DUK_HEAP_STRING_REG_EXP(heap) DUK_HEAP_GET_STRING((heap),DUK_STRIDX_REG_EXP)
1614#define DUK_HTHREAD_STRING_REG_EXP(thr) DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_REG_EXP)
1615#define DUK_STRIDX_UC_ERROR 12 /* 'Error' */
1616#define DUK_HEAP_STRING_UC_ERROR(heap) DUK_HEAP_GET_STRING((heap),DUK_STRIDX_UC_ERROR)
1617#define DUK_HTHREAD_STRING_UC_ERROR(thr) DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_UC_ERROR)
1618#define DUK_STRIDX_MATH 13 /* 'Math' */
1619#define DUK_HEAP_STRING_MATH(heap) DUK_HEAP_GET_STRING((heap),DUK_STRIDX_MATH)
1620#define DUK_HTHREAD_STRING_MATH(thr) DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_MATH)
1621#define DUK_STRIDX_JSON 14 /* 'JSON' */
1622#define DUK_HEAP_STRING_JSON(heap) DUK_HEAP_GET_STRING((heap),DUK_STRIDX_JSON)
1623#define DUK_HTHREAD_STRING_JSON(thr) DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_JSON)
1624#define DUK_STRIDX_EMPTY_STRING 15 /* '' */
1625#define DUK_HEAP_STRING_EMPTY_STRING(heap) DUK_HEAP_GET_STRING((heap),DUK_STRIDX_EMPTY_STRING)
1626#define DUK_HTHREAD_STRING_EMPTY_STRING(thr) DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_EMPTY_STRING)
1627#define DUK_STRIDX_ARRAY_BUFFER 16 /* 'ArrayBuffer' */
1628#define DUK_HEAP_STRING_ARRAY_BUFFER(heap) DUK_HEAP_GET_STRING((heap),DUK_STRIDX_ARRAY_BUFFER)
1629#define DUK_HTHREAD_STRING_ARRAY_BUFFER(thr) DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_ARRAY_BUFFER)
1630#define DUK_STRIDX_DATA_VIEW 17 /* 'DataView' */
1631#define DUK_HEAP_STRING_DATA_VIEW(heap) DUK_HEAP_GET_STRING((heap),DUK_STRIDX_DATA_VIEW)
1632#define DUK_HTHREAD_STRING_DATA_VIEW(thr) DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_DATA_VIEW)
1633#define DUK_STRIDX_INT8_ARRAY 18 /* 'Int8Array' */
1634#define DUK_HEAP_STRING_INT8_ARRAY(heap) DUK_HEAP_GET_STRING((heap),DUK_STRIDX_INT8_ARRAY)
1635#define DUK_HTHREAD_STRING_INT8_ARRAY(thr) DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_INT8_ARRAY)
1636#define DUK_STRIDX_UINT8_ARRAY 19 /* 'Uint8Array' */
1637#define DUK_HEAP_STRING_UINT8_ARRAY(heap) DUK_HEAP_GET_STRING((heap),DUK_STRIDX_UINT8_ARRAY)
1638#define DUK_HTHREAD_STRING_UINT8_ARRAY(thr) DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_UINT8_ARRAY)
1639#define DUK_STRIDX_UINT8_CLAMPED_ARRAY 20 /* 'Uint8ClampedArray' */
1640#define DUK_HEAP_STRING_UINT8_CLAMPED_ARRAY(heap) DUK_HEAP_GET_STRING((heap),DUK_STRIDX_UINT8_CLAMPED_ARRAY)
1641#define DUK_HTHREAD_STRING_UINT8_CLAMPED_ARRAY(thr) DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_UINT8_CLAMPED_ARRAY)
1642#define DUK_STRIDX_INT16_ARRAY 21 /* 'Int16Array' */
1643#define DUK_HEAP_STRING_INT16_ARRAY(heap) DUK_HEAP_GET_STRING((heap),DUK_STRIDX_INT16_ARRAY)
1644#define DUK_HTHREAD_STRING_INT16_ARRAY(thr) DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_INT16_ARRAY)
1645#define DUK_STRIDX_UINT16_ARRAY 22 /* 'Uint16Array' */
1646#define DUK_HEAP_STRING_UINT16_ARRAY(heap) DUK_HEAP_GET_STRING((heap),DUK_STRIDX_UINT16_ARRAY)
1647#define DUK_HTHREAD_STRING_UINT16_ARRAY(thr) DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_UINT16_ARRAY)
1648#define DUK_STRIDX_INT32_ARRAY 23 /* 'Int32Array' */
1649#define DUK_HEAP_STRING_INT32_ARRAY(heap) DUK_HEAP_GET_STRING((heap),DUK_STRIDX_INT32_ARRAY)
1650#define DUK_HTHREAD_STRING_INT32_ARRAY(thr) DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_INT32_ARRAY)
1651#define DUK_STRIDX_UINT32_ARRAY 24 /* 'Uint32Array' */
1652#define DUK_HEAP_STRING_UINT32_ARRAY(heap) DUK_HEAP_GET_STRING((heap),DUK_STRIDX_UINT32_ARRAY)
1653#define DUK_HTHREAD_STRING_UINT32_ARRAY(thr) DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_UINT32_ARRAY)
1654#define DUK_STRIDX_FLOAT32_ARRAY 25 /* 'Float32Array' */
1655#define DUK_HEAP_STRING_FLOAT32_ARRAY(heap) DUK_HEAP_GET_STRING((heap),DUK_STRIDX_FLOAT32_ARRAY)
1656#define DUK_HTHREAD_STRING_FLOAT32_ARRAY(thr) DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_FLOAT32_ARRAY)
1657#define DUK_STRIDX_FLOAT64_ARRAY 26 /* 'Float64Array' */
1658#define DUK_HEAP_STRING_FLOAT64_ARRAY(heap) DUK_HEAP_GET_STRING((heap),DUK_STRIDX_FLOAT64_ARRAY)
1659#define DUK_HTHREAD_STRING_FLOAT64_ARRAY(thr) DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_FLOAT64_ARRAY)
1660#define DUK_STRIDX_GLOBAL 27 /* 'global' */
1661#define DUK_HEAP_STRING_GLOBAL(heap) DUK_HEAP_GET_STRING((heap),DUK_STRIDX_GLOBAL)
1662#define DUK_HTHREAD_STRING_GLOBAL(thr) DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_GLOBAL)
1663#define DUK_STRIDX_OBJ_ENV 28 /* 'ObjEnv' */
1664#define DUK_HEAP_STRING_OBJ_ENV(heap) DUK_HEAP_GET_STRING((heap),DUK_STRIDX_OBJ_ENV)
1665#define DUK_HTHREAD_STRING_OBJ_ENV(thr) DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_OBJ_ENV)
1666#define DUK_STRIDX_DEC_ENV 29 /* 'DecEnv' */
1667#define DUK_HEAP_STRING_DEC_ENV(heap) DUK_HEAP_GET_STRING((heap),DUK_STRIDX_DEC_ENV)
1668#define DUK_HTHREAD_STRING_DEC_ENV(thr) DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_DEC_ENV)
1669#define DUK_STRIDX_UC_BUFFER 30 /* 'Buffer' */
1670#define DUK_HEAP_STRING_UC_BUFFER(heap) DUK_HEAP_GET_STRING((heap),DUK_STRIDX_UC_BUFFER)
1671#define DUK_HTHREAD_STRING_UC_BUFFER(thr) DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_UC_BUFFER)
1672#define DUK_STRIDX_UC_POINTER 31 /* 'Pointer' */
1673#define DUK_HEAP_STRING_UC_POINTER(heap) DUK_HEAP_GET_STRING((heap),DUK_STRIDX_UC_POINTER)
1674#define DUK_HTHREAD_STRING_UC_POINTER(thr) DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_UC_POINTER)
1675#define DUK_STRIDX_UC_THREAD 32 /* 'Thread' */
1676#define DUK_HEAP_STRING_UC_THREAD(heap) DUK_HEAP_GET_STRING((heap),DUK_STRIDX_UC_THREAD)
1677#define DUK_HTHREAD_STRING_UC_THREAD(thr) DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_UC_THREAD)
1678#define DUK_STRIDX_EVAL 33 /* 'eval' */
1679#define DUK_HEAP_STRING_EVAL(heap) DUK_HEAP_GET_STRING((heap),DUK_STRIDX_EVAL)
1680#define DUK_HTHREAD_STRING_EVAL(thr) DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_EVAL)
1681#define DUK_STRIDX_VALUE 34 /* 'value' */
1682#define DUK_HEAP_STRING_VALUE(heap) DUK_HEAP_GET_STRING((heap),DUK_STRIDX_VALUE)
1683#define DUK_HTHREAD_STRING_VALUE(thr) DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_VALUE)
1684#define DUK_STRIDX_WRITABLE 35 /* 'writable' */
1685#define DUK_HEAP_STRING_WRITABLE(heap) DUK_HEAP_GET_STRING((heap),DUK_STRIDX_WRITABLE)
1686#define DUK_HTHREAD_STRING_WRITABLE(thr) DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_WRITABLE)
1687#define DUK_STRIDX_CONFIGURABLE 36 /* 'configurable' */
1688#define DUK_HEAP_STRING_CONFIGURABLE(heap) DUK_HEAP_GET_STRING((heap),DUK_STRIDX_CONFIGURABLE)
1689#define DUK_HTHREAD_STRING_CONFIGURABLE(thr) DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_CONFIGURABLE)
1690#define DUK_STRIDX_ENUMERABLE 37 /* 'enumerable' */
1691#define DUK_HEAP_STRING_ENUMERABLE(heap) DUK_HEAP_GET_STRING((heap),DUK_STRIDX_ENUMERABLE)
1692#define DUK_HTHREAD_STRING_ENUMERABLE(thr) DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_ENUMERABLE)
1693#define DUK_STRIDX_JOIN 38 /* 'join' */
1694#define DUK_HEAP_STRING_JOIN(heap) DUK_HEAP_GET_STRING((heap),DUK_STRIDX_JOIN)
1695#define DUK_HTHREAD_STRING_JOIN(thr) DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_JOIN)
1696#define DUK_STRIDX_TO_LOCALE_STRING 39 /* 'toLocaleString' */
1697#define DUK_HEAP_STRING_TO_LOCALE_STRING(heap) DUK_HEAP_GET_STRING((heap),DUK_STRIDX_TO_LOCALE_STRING)
1698#define DUK_HTHREAD_STRING_TO_LOCALE_STRING(thr) DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_TO_LOCALE_STRING)
1699#define DUK_STRIDX_VALUE_OF 40 /* 'valueOf' */
1700#define DUK_HEAP_STRING_VALUE_OF(heap) DUK_HEAP_GET_STRING((heap),DUK_STRIDX_VALUE_OF)
1701#define DUK_HTHREAD_STRING_VALUE_OF(thr) DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_VALUE_OF)
1702#define DUK_STRIDX_TO_UTC_STRING 41 /* 'toUTCString' */
1703#define DUK_HEAP_STRING_TO_UTC_STRING(heap) DUK_HEAP_GET_STRING((heap),DUK_STRIDX_TO_UTC_STRING)
1704#define DUK_HTHREAD_STRING_TO_UTC_STRING(thr) DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_TO_UTC_STRING)
1705#define DUK_STRIDX_TO_ISO_STRING 42 /* 'toISOString' */
1706#define DUK_HEAP_STRING_TO_ISO_STRING(heap) DUK_HEAP_GET_STRING((heap),DUK_STRIDX_TO_ISO_STRING)
1707#define DUK_HTHREAD_STRING_TO_ISO_STRING(thr) DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_TO_ISO_STRING)
1708#define DUK_STRIDX_TO_GMT_STRING 43 /* 'toGMTString' */
1709#define DUK_HEAP_STRING_TO_GMT_STRING(heap) DUK_HEAP_GET_STRING((heap),DUK_STRIDX_TO_GMT_STRING)
1710#define DUK_HTHREAD_STRING_TO_GMT_STRING(thr) DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_TO_GMT_STRING)
1711#define DUK_STRIDX_SOURCE 44 /* 'source' */
1712#define DUK_HEAP_STRING_SOURCE(heap) DUK_HEAP_GET_STRING((heap),DUK_STRIDX_SOURCE)
1713#define DUK_HTHREAD_STRING_SOURCE(thr) DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_SOURCE)
1714#define DUK_STRIDX_IGNORE_CASE 45 /* 'ignoreCase' */
1715#define DUK_HEAP_STRING_IGNORE_CASE(heap) DUK_HEAP_GET_STRING((heap),DUK_STRIDX_IGNORE_CASE)
1716#define DUK_HTHREAD_STRING_IGNORE_CASE(thr) DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_IGNORE_CASE)
1717#define DUK_STRIDX_MULTILINE 46 /* 'multiline' */
1718#define DUK_HEAP_STRING_MULTILINE(heap) DUK_HEAP_GET_STRING((heap),DUK_STRIDX_MULTILINE)
1719#define DUK_HTHREAD_STRING_MULTILINE(thr) DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_MULTILINE)
1720#define DUK_STRIDX_LAST_INDEX 47 /* 'lastIndex' */
1721#define DUK_HEAP_STRING_LAST_INDEX(heap) DUK_HEAP_GET_STRING((heap),DUK_STRIDX_LAST_INDEX)
1722#define DUK_HTHREAD_STRING_LAST_INDEX(thr) DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_LAST_INDEX)
1723#define DUK_STRIDX_FLAGS 48 /* 'flags' */
1724#define DUK_HEAP_STRING_FLAGS(heap) DUK_HEAP_GET_STRING((heap),DUK_STRIDX_FLAGS)
1725#define DUK_HTHREAD_STRING_FLAGS(thr) DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_FLAGS)
1726#define DUK_STRIDX_INDEX 49 /* 'index' */
1727#define DUK_HEAP_STRING_INDEX(heap) DUK_HEAP_GET_STRING((heap),DUK_STRIDX_INDEX)
1728#define DUK_HTHREAD_STRING_INDEX(thr) DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_INDEX)
1729#define DUK_STRIDX_PROTOTYPE 50 /* 'prototype' */
1730#define DUK_HEAP_STRING_PROTOTYPE(heap) DUK_HEAP_GET_STRING((heap),DUK_STRIDX_PROTOTYPE)
1731#define DUK_HTHREAD_STRING_PROTOTYPE(thr) DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_PROTOTYPE)
1732#define DUK_STRIDX_CONSTRUCTOR 51 /* 'constructor' */
1733#define DUK_HEAP_STRING_CONSTRUCTOR(heap) DUK_HEAP_GET_STRING((heap),DUK_STRIDX_CONSTRUCTOR)
1734#define DUK_HTHREAD_STRING_CONSTRUCTOR(thr) DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_CONSTRUCTOR)
1735#define DUK_STRIDX_MESSAGE 52 /* 'message' */
1736#define DUK_HEAP_STRING_MESSAGE(heap) DUK_HEAP_GET_STRING((heap),DUK_STRIDX_MESSAGE)
1737#define DUK_HTHREAD_STRING_MESSAGE(thr) DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_MESSAGE)
1738#define DUK_STRIDX_LC_BOOLEAN 53 /* 'boolean' */
1739#define DUK_HEAP_STRING_LC_BOOLEAN(heap) DUK_HEAP_GET_STRING((heap),DUK_STRIDX_LC_BOOLEAN)
1740#define DUK_HTHREAD_STRING_LC_BOOLEAN(thr) DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_LC_BOOLEAN)
1741#define DUK_STRIDX_LC_NUMBER 54 /* 'number' */
1742#define DUK_HEAP_STRING_LC_NUMBER(heap) DUK_HEAP_GET_STRING((heap),DUK_STRIDX_LC_NUMBER)
1743#define DUK_HTHREAD_STRING_LC_NUMBER(thr) DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_LC_NUMBER)
1744#define DUK_STRIDX_LC_STRING 55 /* 'string' */
1745#define DUK_HEAP_STRING_LC_STRING(heap) DUK_HEAP_GET_STRING((heap),DUK_STRIDX_LC_STRING)
1746#define DUK_HTHREAD_STRING_LC_STRING(thr) DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_LC_STRING)
1747#define DUK_STRIDX_LC_SYMBOL 56 /* 'symbol' */
1748#define DUK_HEAP_STRING_LC_SYMBOL(heap) DUK_HEAP_GET_STRING((heap),DUK_STRIDX_LC_SYMBOL)
1749#define DUK_HTHREAD_STRING_LC_SYMBOL(thr) DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_LC_SYMBOL)
1750#define DUK_STRIDX_LC_OBJECT 57 /* 'object' */
1751#define DUK_HEAP_STRING_LC_OBJECT(heap) DUK_HEAP_GET_STRING((heap),DUK_STRIDX_LC_OBJECT)
1752#define DUK_HTHREAD_STRING_LC_OBJECT(thr) DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_LC_OBJECT)
1753#define DUK_STRIDX_LC_UNDEFINED 58 /* 'undefined' */
1754#define DUK_HEAP_STRING_LC_UNDEFINED(heap) DUK_HEAP_GET_STRING((heap),DUK_STRIDX_LC_UNDEFINED)
1755#define DUK_HTHREAD_STRING_LC_UNDEFINED(thr) DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_LC_UNDEFINED)
1756#define DUK_STRIDX_NAN 59 /* 'NaN' */
1757#define DUK_HEAP_STRING_NAN(heap) DUK_HEAP_GET_STRING((heap),DUK_STRIDX_NAN)
1758#define DUK_HTHREAD_STRING_NAN(thr) DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_NAN)
1759#define DUK_STRIDX_INFINITY 60 /* 'Infinity' */
1760#define DUK_HEAP_STRING_INFINITY(heap) DUK_HEAP_GET_STRING((heap),DUK_STRIDX_INFINITY)
1761#define DUK_HTHREAD_STRING_INFINITY(thr) DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_INFINITY)
1762#define DUK_STRIDX_MINUS_INFINITY 61 /* '-Infinity' */
1763#define DUK_HEAP_STRING_MINUS_INFINITY(heap) DUK_HEAP_GET_STRING((heap),DUK_STRIDX_MINUS_INFINITY)
1764#define DUK_HTHREAD_STRING_MINUS_INFINITY(thr) DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_MINUS_INFINITY)
1765#define DUK_STRIDX_MINUS_ZERO 62 /* '-0' */
1766#define DUK_HEAP_STRING_MINUS_ZERO(heap) DUK_HEAP_GET_STRING((heap),DUK_STRIDX_MINUS_ZERO)
1767#define DUK_HTHREAD_STRING_MINUS_ZERO(thr) DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_MINUS_ZERO)
1768#define DUK_STRIDX_COMMA 63 /* ',' */
1769#define DUK_HEAP_STRING_COMMA(heap) DUK_HEAP_GET_STRING((heap),DUK_STRIDX_COMMA)
1770#define DUK_HTHREAD_STRING_COMMA(thr) DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_COMMA)
1771#define DUK_STRIDX_NEWLINE_4SPACE 64 /* '\n ' */
1772#define DUK_HEAP_STRING_NEWLINE_4SPACE(heap) DUK_HEAP_GET_STRING((heap),DUK_STRIDX_NEWLINE_4SPACE)
1773#define DUK_HTHREAD_STRING_NEWLINE_4SPACE(thr) DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_NEWLINE_4SPACE)
1774#define DUK_STRIDX_BRACKETED_ELLIPSIS 65 /* '[...]' */
1775#define DUK_HEAP_STRING_BRACKETED_ELLIPSIS(heap) DUK_HEAP_GET_STRING((heap),DUK_STRIDX_BRACKETED_ELLIPSIS)
1776#define DUK_HTHREAD_STRING_BRACKETED_ELLIPSIS(thr) DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_BRACKETED_ELLIPSIS)
1777#define DUK_STRIDX_INVALID_DATE 66 /* 'Invalid Date' */
1778#define DUK_HEAP_STRING_INVALID_DATE(heap) DUK_HEAP_GET_STRING((heap),DUK_STRIDX_INVALID_DATE)
1779#define DUK_HTHREAD_STRING_INVALID_DATE(thr) DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_INVALID_DATE)
1780#define DUK_STRIDX_LC_ARGUMENTS 67 /* 'arguments' */
1781#define DUK_HEAP_STRING_LC_ARGUMENTS(heap) DUK_HEAP_GET_STRING((heap),DUK_STRIDX_LC_ARGUMENTS)
1782#define DUK_HTHREAD_STRING_LC_ARGUMENTS(thr) DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_LC_ARGUMENTS)
1783#define DUK_STRIDX_CALLEE 68 /* 'callee' */
1784#define DUK_HEAP_STRING_CALLEE(heap) DUK_HEAP_GET_STRING((heap),DUK_STRIDX_CALLEE)
1785#define DUK_HTHREAD_STRING_CALLEE(thr) DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_CALLEE)
1786#define DUK_STRIDX_CALLER 69 /* 'caller' */
1787#define DUK_HEAP_STRING_CALLER(heap) DUK_HEAP_GET_STRING((heap),DUK_STRIDX_CALLER)
1788#define DUK_HTHREAD_STRING_CALLER(thr) DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_CALLER)
1789#define DUK_STRIDX_APPLY 70 /* 'apply' */
1790#define DUK_HEAP_STRING_APPLY(heap) DUK_HEAP_GET_STRING((heap),DUK_STRIDX_APPLY)
1791#define DUK_HTHREAD_STRING_APPLY(thr) DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_APPLY)
1792#define DUK_STRIDX_CONSTRUCT 71 /* 'construct' */
1793#define DUK_HEAP_STRING_CONSTRUCT(heap) DUK_HEAP_GET_STRING((heap),DUK_STRIDX_CONSTRUCT)
1794#define DUK_HTHREAD_STRING_CONSTRUCT(thr) DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_CONSTRUCT)
1795#define DUK_STRIDX_DELETE_PROPERTY 72 /* 'deleteProperty' */
1796#define DUK_HEAP_STRING_DELETE_PROPERTY(heap) DUK_HEAP_GET_STRING((heap),DUK_STRIDX_DELETE_PROPERTY)
1797#define DUK_HTHREAD_STRING_DELETE_PROPERTY(thr) DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_DELETE_PROPERTY)
1798#define DUK_STRIDX_GET 73 /* 'get' */
1799#define DUK_HEAP_STRING_GET(heap) DUK_HEAP_GET_STRING((heap),DUK_STRIDX_GET)
1800#define DUK_HTHREAD_STRING_GET(thr) DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_GET)
1801#define DUK_STRIDX_HAS 74 /* 'has' */
1802#define DUK_HEAP_STRING_HAS(heap) DUK_HEAP_GET_STRING((heap),DUK_STRIDX_HAS)
1803#define DUK_HTHREAD_STRING_HAS(thr) DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_HAS)
1804#define DUK_STRIDX_OWN_KEYS 75 /* 'ownKeys' */
1805#define DUK_HEAP_STRING_OWN_KEYS(heap) DUK_HEAP_GET_STRING((heap),DUK_STRIDX_OWN_KEYS)
1806#define DUK_HTHREAD_STRING_OWN_KEYS(thr) DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_OWN_KEYS)
1807#define DUK_STRIDX_WELLKNOWN_SYMBOL_TO_PRIMITIVE 76 /* '\x81Symbol.toPrimitive\xff' */
1808#define DUK_HEAP_STRING_WELLKNOWN_SYMBOL_TO_PRIMITIVE(heap) DUK_HEAP_GET_STRING((heap),DUK_STRIDX_WELLKNOWN_SYMBOL_TO_PRIMITIVE)
1809#define DUK_HTHREAD_STRING_WELLKNOWN_SYMBOL_TO_PRIMITIVE(thr) DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_WELLKNOWN_SYMBOL_TO_PRIMITIVE)
1810#define DUK_STRIDX_WELLKNOWN_SYMBOL_HAS_INSTANCE 77 /* '\x81Symbol.hasInstance\xff' */
1811#define DUK_HEAP_STRING_WELLKNOWN_SYMBOL_HAS_INSTANCE(heap) DUK_HEAP_GET_STRING((heap),DUK_STRIDX_WELLKNOWN_SYMBOL_HAS_INSTANCE)
1812#define DUK_HTHREAD_STRING_WELLKNOWN_SYMBOL_HAS_INSTANCE(thr) DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_WELLKNOWN_SYMBOL_HAS_INSTANCE)
1813#define DUK_STRIDX_WELLKNOWN_SYMBOL_TO_STRING_TAG 78 /* '\x81Symbol.toStringTag\xff' */
1814#define DUK_HEAP_STRING_WELLKNOWN_SYMBOL_TO_STRING_TAG(heap) DUK_HEAP_GET_STRING((heap),DUK_STRIDX_WELLKNOWN_SYMBOL_TO_STRING_TAG)
1815#define DUK_HTHREAD_STRING_WELLKNOWN_SYMBOL_TO_STRING_TAG(thr) DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_WELLKNOWN_SYMBOL_TO_STRING_TAG)
1816#define DUK_STRIDX_WELLKNOWN_SYMBOL_IS_CONCAT_SPREADABLE 79 /* '\x81Symbol.isConcatSpreadable\xff' */
1817#define DUK_HEAP_STRING_WELLKNOWN_SYMBOL_IS_CONCAT_SPREADABLE(heap) DUK_HEAP_GET_STRING((heap),DUK_STRIDX_WELLKNOWN_SYMBOL_IS_CONCAT_SPREADABLE)
1818#define DUK_HTHREAD_STRING_WELLKNOWN_SYMBOL_IS_CONCAT_SPREADABLE(thr) DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_WELLKNOWN_SYMBOL_IS_CONCAT_SPREADABLE)
1819#define DUK_STRIDX_SET_PROTOTYPE_OF 80 /* 'setPrototypeOf' */
1820#define DUK_HEAP_STRING_SET_PROTOTYPE_OF(heap) DUK_HEAP_GET_STRING((heap),DUK_STRIDX_SET_PROTOTYPE_OF)
1821#define DUK_HTHREAD_STRING_SET_PROTOTYPE_OF(thr) DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_SET_PROTOTYPE_OF)
1822#define DUK_STRIDX___PROTO__ 81 /* '__proto__' */
1823#define DUK_HEAP_STRING___PROTO__(heap) DUK_HEAP_GET_STRING((heap),DUK_STRIDX___PROTO__)
1824#define DUK_HTHREAD_STRING___PROTO__(thr) DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX___PROTO__)
1825#define DUK_STRIDX_TO_STRING 82 /* 'toString' */
1826#define DUK_HEAP_STRING_TO_STRING(heap) DUK_HEAP_GET_STRING((heap),DUK_STRIDX_TO_STRING)
1827#define DUK_HTHREAD_STRING_TO_STRING(thr) DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_TO_STRING)
1828#define DUK_STRIDX_TO_JSON 83 /* 'toJSON' */
1829#define DUK_HEAP_STRING_TO_JSON(heap) DUK_HEAP_GET_STRING((heap),DUK_STRIDX_TO_JSON)
1830#define DUK_HTHREAD_STRING_TO_JSON(thr) DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_TO_JSON)
1831#define DUK_STRIDX_TYPE 84 /* 'type' */
1832#define DUK_HEAP_STRING_TYPE(heap) DUK_HEAP_GET_STRING((heap),DUK_STRIDX_TYPE)
1833#define DUK_HTHREAD_STRING_TYPE(thr) DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_TYPE)
1834#define DUK_STRIDX_DATA 85 /* 'data' */
1835#define DUK_HEAP_STRING_DATA(heap) DUK_HEAP_GET_STRING((heap),DUK_STRIDX_DATA)
1836#define DUK_HTHREAD_STRING_DATA(thr) DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_DATA)
1837#define DUK_STRIDX_LC_BUFFER 86 /* 'buffer' */
1838#define DUK_HEAP_STRING_LC_BUFFER(heap) DUK_HEAP_GET_STRING((heap),DUK_STRIDX_LC_BUFFER)
1839#define DUK_HTHREAD_STRING_LC_BUFFER(thr) DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_LC_BUFFER)
1840#define DUK_STRIDX_LENGTH 87 /* 'length' */
1841#define DUK_HEAP_STRING_LENGTH(heap) DUK_HEAP_GET_STRING((heap),DUK_STRIDX_LENGTH)
1842#define DUK_HTHREAD_STRING_LENGTH(thr) DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_LENGTH)
1843#define DUK_STRIDX_SET 88 /* 'set' */
1844#define DUK_HEAP_STRING_SET(heap) DUK_HEAP_GET_STRING((heap),DUK_STRIDX_SET)
1845#define DUK_HTHREAD_STRING_SET(thr) DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_SET)
1846#define DUK_STRIDX_STACK 89 /* 'stack' */
1847#define DUK_HEAP_STRING_STACK(heap) DUK_HEAP_GET_STRING((heap),DUK_STRIDX_STACK)
1848#define DUK_HTHREAD_STRING_STACK(thr) DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_STACK)
1849#define DUK_STRIDX_PC 90 /* 'pc' */
1850#define DUK_HEAP_STRING_PC(heap) DUK_HEAP_GET_STRING((heap),DUK_STRIDX_PC)
1851#define DUK_HTHREAD_STRING_PC(thr) DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_PC)
1852#define DUK_STRIDX_LINE_NUMBER 91 /* 'lineNumber' */
1853#define DUK_HEAP_STRING_LINE_NUMBER(heap) DUK_HEAP_GET_STRING((heap),DUK_STRIDX_LINE_NUMBER)
1854#define DUK_HTHREAD_STRING_LINE_NUMBER(thr) DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_LINE_NUMBER)
1855#define DUK_STRIDX_INT_TRACEDATA 92 /* '\x82Tracedata' */
1856#define DUK_HEAP_STRING_INT_TRACEDATA(heap) DUK_HEAP_GET_STRING((heap),DUK_STRIDX_INT_TRACEDATA)
1857#define DUK_HTHREAD_STRING_INT_TRACEDATA(thr) DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_INT_TRACEDATA)
1858#define DUK_STRIDX_NAME 93 /* 'name' */
1859#define DUK_HEAP_STRING_NAME(heap) DUK_HEAP_GET_STRING((heap),DUK_STRIDX_NAME)
1860#define DUK_HTHREAD_STRING_NAME(thr) DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_NAME)
1861#define DUK_STRIDX_FILE_NAME 94 /* 'fileName' */
1862#define DUK_HEAP_STRING_FILE_NAME(heap) DUK_HEAP_GET_STRING((heap),DUK_STRIDX_FILE_NAME)
1863#define DUK_HTHREAD_STRING_FILE_NAME(thr) DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_FILE_NAME)
1864#define DUK_STRIDX_LC_POINTER 95 /* 'pointer' */
1865#define DUK_HEAP_STRING_LC_POINTER(heap) DUK_HEAP_GET_STRING((heap),DUK_STRIDX_LC_POINTER)
1866#define DUK_HTHREAD_STRING_LC_POINTER(thr) DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_LC_POINTER)
1867#define DUK_STRIDX_INT_TARGET 96 /* '\x82Target' */
1868#define DUK_HEAP_STRING_INT_TARGET(heap) DUK_HEAP_GET_STRING((heap),DUK_STRIDX_INT_TARGET)
1869#define DUK_HTHREAD_STRING_INT_TARGET(thr) DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_INT_TARGET)
1870#define DUK_STRIDX_INT_NEXT 97 /* '\x82Next' */
1871#define DUK_HEAP_STRING_INT_NEXT(heap) DUK_HEAP_GET_STRING((heap),DUK_STRIDX_INT_NEXT)
1872#define DUK_HTHREAD_STRING_INT_NEXT(thr) DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_INT_NEXT)
1873#define DUK_STRIDX_INT_BYTECODE 98 /* '\x82Bytecode' */
1874#define DUK_HEAP_STRING_INT_BYTECODE(heap) DUK_HEAP_GET_STRING((heap),DUK_STRIDX_INT_BYTECODE)
1875#define DUK_HTHREAD_STRING_INT_BYTECODE(thr) DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_INT_BYTECODE)
1876#define DUK_STRIDX_INT_FORMALS 99 /* '\x82Formals' */
1877#define DUK_HEAP_STRING_INT_FORMALS(heap) DUK_HEAP_GET_STRING((heap),DUK_STRIDX_INT_FORMALS)
1878#define DUK_HTHREAD_STRING_INT_FORMALS(thr) DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_INT_FORMALS)
1879#define DUK_STRIDX_INT_VARMAP 100 /* '\x82Varmap' */
1880#define DUK_HEAP_STRING_INT_VARMAP(heap) DUK_HEAP_GET_STRING((heap),DUK_STRIDX_INT_VARMAP)
1881#define DUK_HTHREAD_STRING_INT_VARMAP(thr) DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_INT_VARMAP)
1882#define DUK_STRIDX_INT_SOURCE 101 /* '\x82Source' */
1883#define DUK_HEAP_STRING_INT_SOURCE(heap) DUK_HEAP_GET_STRING((heap),DUK_STRIDX_INT_SOURCE)
1884#define DUK_HTHREAD_STRING_INT_SOURCE(thr) DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_INT_SOURCE)
1885#define DUK_STRIDX_INT_PC2LINE 102 /* '\x82Pc2line' */
1886#define DUK_HEAP_STRING_INT_PC2LINE(heap) DUK_HEAP_GET_STRING((heap),DUK_STRIDX_INT_PC2LINE)
1887#define DUK_HTHREAD_STRING_INT_PC2LINE(thr) DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_INT_PC2LINE)
1888#define DUK_STRIDX_INT_MAP 103 /* '\x82Map' */
1889#define DUK_HEAP_STRING_INT_MAP(heap) DUK_HEAP_GET_STRING((heap),DUK_STRIDX_INT_MAP)
1890#define DUK_HTHREAD_STRING_INT_MAP(thr) DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_INT_MAP)
1891#define DUK_STRIDX_INT_VARENV 104 /* '\x82Varenv' */
1892#define DUK_HEAP_STRING_INT_VARENV(heap) DUK_HEAP_GET_STRING((heap),DUK_STRIDX_INT_VARENV)
1893#define DUK_HTHREAD_STRING_INT_VARENV(thr) DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_INT_VARENV)
1894#define DUK_STRIDX_INT_FINALIZER 105 /* '\x82Finalizer' */
1895#define DUK_HEAP_STRING_INT_FINALIZER(heap) DUK_HEAP_GET_STRING((heap),DUK_STRIDX_INT_FINALIZER)
1896#define DUK_HTHREAD_STRING_INT_FINALIZER(thr) DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_INT_FINALIZER)
1897#define DUK_STRIDX_INT_VALUE 106 /* '\x82Value' */
1898#define DUK_HEAP_STRING_INT_VALUE(heap) DUK_HEAP_GET_STRING((heap),DUK_STRIDX_INT_VALUE)
1899#define DUK_HTHREAD_STRING_INT_VALUE(thr) DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_INT_VALUE)
1900#define DUK_STRIDX_COMPILE 107 /* 'compile' */
1901#define DUK_HEAP_STRING_COMPILE(heap) DUK_HEAP_GET_STRING((heap),DUK_STRIDX_COMPILE)
1902#define DUK_HTHREAD_STRING_COMPILE(thr) DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_COMPILE)
1903#define DUK_STRIDX_INPUT 108 /* 'input' */
1904#define DUK_HEAP_STRING_INPUT(heap) DUK_HEAP_GET_STRING((heap),DUK_STRIDX_INPUT)
1905#define DUK_HTHREAD_STRING_INPUT(thr) DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_INPUT)
1906#define DUK_STRIDX_ERR_CREATE 109 /* 'errCreate' */
1907#define DUK_HEAP_STRING_ERR_CREATE(heap) DUK_HEAP_GET_STRING((heap),DUK_STRIDX_ERR_CREATE)
1908#define DUK_HTHREAD_STRING_ERR_CREATE(thr) DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_ERR_CREATE)
1909#define DUK_STRIDX_ERR_THROW 110 /* 'errThrow' */
1910#define DUK_HEAP_STRING_ERR_THROW(heap) DUK_HEAP_GET_STRING((heap),DUK_STRIDX_ERR_THROW)
1911#define DUK_HTHREAD_STRING_ERR_THROW(thr) DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_ERR_THROW)
1912#define DUK_STRIDX_ENV 111 /* 'env' */
1913#define DUK_HEAP_STRING_ENV(heap) DUK_HEAP_GET_STRING((heap),DUK_STRIDX_ENV)
1914#define DUK_HTHREAD_STRING_ENV(thr) DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_ENV)
1915#define DUK_STRIDX_HEX 112 /* 'hex' */
1916#define DUK_HEAP_STRING_HEX(heap) DUK_HEAP_GET_STRING((heap),DUK_STRIDX_HEX)
1917#define DUK_HTHREAD_STRING_HEX(thr) DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_HEX)
1918#define DUK_STRIDX_BASE64 113 /* 'base64' */
1919#define DUK_HEAP_STRING_BASE64(heap) DUK_HEAP_GET_STRING((heap),DUK_STRIDX_BASE64)
1920#define DUK_HTHREAD_STRING_BASE64(thr) DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_BASE64)
1921#define DUK_STRIDX_JX 114 /* 'jx' */
1922#define DUK_HEAP_STRING_JX(heap) DUK_HEAP_GET_STRING((heap),DUK_STRIDX_JX)
1923#define DUK_HTHREAD_STRING_JX(thr) DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_JX)
1924#define DUK_STRIDX_JC 115 /* 'jc' */
1925#define DUK_HEAP_STRING_JC(heap) DUK_HEAP_GET_STRING((heap),DUK_STRIDX_JC)
1926#define DUK_HTHREAD_STRING_JC(thr) DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_JC)
1927#define DUK_STRIDX_JSON_EXT_UNDEFINED 116 /* '{"_undef":true}' */
1928#define DUK_HEAP_STRING_JSON_EXT_UNDEFINED(heap) DUK_HEAP_GET_STRING((heap),DUK_STRIDX_JSON_EXT_UNDEFINED)
1929#define DUK_HTHREAD_STRING_JSON_EXT_UNDEFINED(thr) DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_JSON_EXT_UNDEFINED)
1930#define DUK_STRIDX_JSON_EXT_NAN 117 /* '{"_nan":true}' */
1931#define DUK_HEAP_STRING_JSON_EXT_NAN(heap) DUK_HEAP_GET_STRING((heap),DUK_STRIDX_JSON_EXT_NAN)
1932#define DUK_HTHREAD_STRING_JSON_EXT_NAN(thr) DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_JSON_EXT_NAN)
1933#define DUK_STRIDX_JSON_EXT_POSINF 118 /* '{"_inf":true}' */
1934#define DUK_HEAP_STRING_JSON_EXT_POSINF(heap) DUK_HEAP_GET_STRING((heap),DUK_STRIDX_JSON_EXT_POSINF)
1935#define DUK_HTHREAD_STRING_JSON_EXT_POSINF(thr) DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_JSON_EXT_POSINF)
1936#define DUK_STRIDX_JSON_EXT_NEGINF 119 /* '{"_ninf":true}' */
1937#define DUK_HEAP_STRING_JSON_EXT_NEGINF(heap) DUK_HEAP_GET_STRING((heap),DUK_STRIDX_JSON_EXT_NEGINF)
1938#define DUK_HTHREAD_STRING_JSON_EXT_NEGINF(thr) DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_JSON_EXT_NEGINF)
1939#define DUK_STRIDX_JSON_EXT_FUNCTION1 120 /* '{"_func":true}' */
1940#define DUK_HEAP_STRING_JSON_EXT_FUNCTION1(heap) DUK_HEAP_GET_STRING((heap),DUK_STRIDX_JSON_EXT_FUNCTION1)
1941#define DUK_HTHREAD_STRING_JSON_EXT_FUNCTION1(thr) DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_JSON_EXT_FUNCTION1)
1942#define DUK_STRIDX_JSON_EXT_FUNCTION2 121 /* '{_func:true}' */
1943#define DUK_HEAP_STRING_JSON_EXT_FUNCTION2(heap) DUK_HEAP_GET_STRING((heap),DUK_STRIDX_JSON_EXT_FUNCTION2)
1944#define DUK_HTHREAD_STRING_JSON_EXT_FUNCTION2(thr) DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_JSON_EXT_FUNCTION2)
1945#define DUK_STRIDX_BREAK 122 /* 'break' */
1946#define DUK_HEAP_STRING_BREAK(heap) DUK_HEAP_GET_STRING((heap),DUK_STRIDX_BREAK)
1947#define DUK_HTHREAD_STRING_BREAK(thr) DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_BREAK)
1948#define DUK_STRIDX_CASE 123 /* 'case' */
1949#define DUK_HEAP_STRING_CASE(heap) DUK_HEAP_GET_STRING((heap),DUK_STRIDX_CASE)
1950#define DUK_HTHREAD_STRING_CASE(thr) DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_CASE)
1951#define DUK_STRIDX_CATCH 124 /* 'catch' */
1952#define DUK_HEAP_STRING_CATCH(heap) DUK_HEAP_GET_STRING((heap),DUK_STRIDX_CATCH)
1953#define DUK_HTHREAD_STRING_CATCH(thr) DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_CATCH)
1954#define DUK_STRIDX_CONTINUE 125 /* 'continue' */
1955#define DUK_HEAP_STRING_CONTINUE(heap) DUK_HEAP_GET_STRING((heap),DUK_STRIDX_CONTINUE)
1956#define DUK_HTHREAD_STRING_CONTINUE(thr) DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_CONTINUE)
1957#define DUK_STRIDX_DEBUGGER 126 /* 'debugger' */
1958#define DUK_HEAP_STRING_DEBUGGER(heap) DUK_HEAP_GET_STRING((heap),DUK_STRIDX_DEBUGGER)
1959#define DUK_HTHREAD_STRING_DEBUGGER(thr) DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_DEBUGGER)
1960#define DUK_STRIDX_DEFAULT 127 /* 'default' */
1961#define DUK_HEAP_STRING_DEFAULT(heap) DUK_HEAP_GET_STRING((heap),DUK_STRIDX_DEFAULT)
1962#define DUK_HTHREAD_STRING_DEFAULT(thr) DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_DEFAULT)
1963#define DUK_STRIDX_DELETE 128 /* 'delete' */
1964#define DUK_HEAP_STRING_DELETE(heap) DUK_HEAP_GET_STRING((heap),DUK_STRIDX_DELETE)
1965#define DUK_HTHREAD_STRING_DELETE(thr) DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_DELETE)
1966#define DUK_STRIDX_DO 129 /* 'do' */
1967#define DUK_HEAP_STRING_DO(heap) DUK_HEAP_GET_STRING((heap),DUK_STRIDX_DO)
1968#define DUK_HTHREAD_STRING_DO(thr) DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_DO)
1969#define DUK_STRIDX_ELSE 130 /* 'else' */
1970#define DUK_HEAP_STRING_ELSE(heap) DUK_HEAP_GET_STRING((heap),DUK_STRIDX_ELSE)
1971#define DUK_HTHREAD_STRING_ELSE(thr) DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_ELSE)
1972#define DUK_STRIDX_FINALLY 131 /* 'finally' */
1973#define DUK_HEAP_STRING_FINALLY(heap) DUK_HEAP_GET_STRING((heap),DUK_STRIDX_FINALLY)
1974#define DUK_HTHREAD_STRING_FINALLY(thr) DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_FINALLY)
1975#define DUK_STRIDX_FOR 132 /* 'for' */
1976#define DUK_HEAP_STRING_FOR(heap) DUK_HEAP_GET_STRING((heap),DUK_STRIDX_FOR)
1977#define DUK_HTHREAD_STRING_FOR(thr) DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_FOR)
1978#define DUK_STRIDX_LC_FUNCTION 133 /* 'function' */
1979#define DUK_HEAP_STRING_LC_FUNCTION(heap) DUK_HEAP_GET_STRING((heap),DUK_STRIDX_LC_FUNCTION)
1980#define DUK_HTHREAD_STRING_LC_FUNCTION(thr) DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_LC_FUNCTION)
1981#define DUK_STRIDX_IF 134 /* 'if' */
1982#define DUK_HEAP_STRING_IF(heap) DUK_HEAP_GET_STRING((heap),DUK_STRIDX_IF)
1983#define DUK_HTHREAD_STRING_IF(thr) DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_IF)
1984#define DUK_STRIDX_IN 135 /* 'in' */
1985#define DUK_HEAP_STRING_IN(heap) DUK_HEAP_GET_STRING((heap),DUK_STRIDX_IN)
1986#define DUK_HTHREAD_STRING_IN(thr) DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_IN)
1987#define DUK_STRIDX_INSTANCEOF 136 /* 'instanceof' */
1988#define DUK_HEAP_STRING_INSTANCEOF(heap) DUK_HEAP_GET_STRING((heap),DUK_STRIDX_INSTANCEOF)
1989#define DUK_HTHREAD_STRING_INSTANCEOF(thr) DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_INSTANCEOF)
1990#define DUK_STRIDX_NEW 137 /* 'new' */
1991#define DUK_HEAP_STRING_NEW(heap) DUK_HEAP_GET_STRING((heap),DUK_STRIDX_NEW)
1992#define DUK_HTHREAD_STRING_NEW(thr) DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_NEW)
1993#define DUK_STRIDX_RETURN 138 /* 'return' */
1994#define DUK_HEAP_STRING_RETURN(heap) DUK_HEAP_GET_STRING((heap),DUK_STRIDX_RETURN)
1995#define DUK_HTHREAD_STRING_RETURN(thr) DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_RETURN)
1996#define DUK_STRIDX_SWITCH 139 /* 'switch' */
1997#define DUK_HEAP_STRING_SWITCH(heap) DUK_HEAP_GET_STRING((heap),DUK_STRIDX_SWITCH)
1998#define DUK_HTHREAD_STRING_SWITCH(thr) DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_SWITCH)
1999#define DUK_STRIDX_THIS 140 /* 'this' */
2000#define DUK_HEAP_STRING_THIS(heap) DUK_HEAP_GET_STRING((heap),DUK_STRIDX_THIS)
2001#define DUK_HTHREAD_STRING_THIS(thr) DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_THIS)
2002#define DUK_STRIDX_THROW 141 /* 'throw' */
2003#define DUK_HEAP_STRING_THROW(heap) DUK_HEAP_GET_STRING((heap),DUK_STRIDX_THROW)
2004#define DUK_HTHREAD_STRING_THROW(thr) DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_THROW)
2005#define DUK_STRIDX_TRY 142 /* 'try' */
2006#define DUK_HEAP_STRING_TRY(heap) DUK_HEAP_GET_STRING((heap),DUK_STRIDX_TRY)
2007#define DUK_HTHREAD_STRING_TRY(thr) DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_TRY)
2008#define DUK_STRIDX_TYPEOF 143 /* 'typeof' */
2009#define DUK_HEAP_STRING_TYPEOF(heap) DUK_HEAP_GET_STRING((heap),DUK_STRIDX_TYPEOF)
2010#define DUK_HTHREAD_STRING_TYPEOF(thr) DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_TYPEOF)
2011#define DUK_STRIDX_VAR 144 /* 'var' */
2012#define DUK_HEAP_STRING_VAR(heap) DUK_HEAP_GET_STRING((heap),DUK_STRIDX_VAR)
2013#define DUK_HTHREAD_STRING_VAR(thr) DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_VAR)
2014#define DUK_STRIDX_CONST 145 /* 'const' */
2015#define DUK_HEAP_STRING_CONST(heap) DUK_HEAP_GET_STRING((heap),DUK_STRIDX_CONST)
2016#define DUK_HTHREAD_STRING_CONST(thr) DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_CONST)
2017#define DUK_STRIDX_VOID 146 /* 'void' */
2018#define DUK_HEAP_STRING_VOID(heap) DUK_HEAP_GET_STRING((heap),DUK_STRIDX_VOID)
2019#define DUK_HTHREAD_STRING_VOID(thr) DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_VOID)
2020#define DUK_STRIDX_WHILE 147 /* 'while' */
2021#define DUK_HEAP_STRING_WHILE(heap) DUK_HEAP_GET_STRING((heap),DUK_STRIDX_WHILE)
2022#define DUK_HTHREAD_STRING_WHILE(thr) DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_WHILE)
2023#define DUK_STRIDX_WITH 148 /* 'with' */
2024#define DUK_HEAP_STRING_WITH(heap) DUK_HEAP_GET_STRING((heap),DUK_STRIDX_WITH)
2025#define DUK_HTHREAD_STRING_WITH(thr) DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_WITH)
2026#define DUK_STRIDX_CLASS 149 /* 'class' */
2027#define DUK_HEAP_STRING_CLASS(heap) DUK_HEAP_GET_STRING((heap),DUK_STRIDX_CLASS)
2028#define DUK_HTHREAD_STRING_CLASS(thr) DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_CLASS)
2029#define DUK_STRIDX_ENUM 150 /* 'enum' */
2030#define DUK_HEAP_STRING_ENUM(heap) DUK_HEAP_GET_STRING((heap),DUK_STRIDX_ENUM)
2031#define DUK_HTHREAD_STRING_ENUM(thr) DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_ENUM)
2032#define DUK_STRIDX_EXPORT 151 /* 'export' */
2033#define DUK_HEAP_STRING_EXPORT(heap) DUK_HEAP_GET_STRING((heap),DUK_STRIDX_EXPORT)
2034#define DUK_HTHREAD_STRING_EXPORT(thr) DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_EXPORT)
2035#define DUK_STRIDX_EXTENDS 152 /* 'extends' */
2036#define DUK_HEAP_STRING_EXTENDS(heap) DUK_HEAP_GET_STRING((heap),DUK_STRIDX_EXTENDS)
2037#define DUK_HTHREAD_STRING_EXTENDS(thr) DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_EXTENDS)
2038#define DUK_STRIDX_IMPORT 153 /* 'import' */
2039#define DUK_HEAP_STRING_IMPORT(heap) DUK_HEAP_GET_STRING((heap),DUK_STRIDX_IMPORT)
2040#define DUK_HTHREAD_STRING_IMPORT(thr) DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_IMPORT)
2041#define DUK_STRIDX_SUPER 154 /* 'super' */
2042#define DUK_HEAP_STRING_SUPER(heap) DUK_HEAP_GET_STRING((heap),DUK_STRIDX_SUPER)
2043#define DUK_HTHREAD_STRING_SUPER(thr) DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_SUPER)
2044#define DUK_STRIDX_LC_NULL 155 /* 'null' */
2045#define DUK_HEAP_STRING_LC_NULL(heap) DUK_HEAP_GET_STRING((heap),DUK_STRIDX_LC_NULL)
2046#define DUK_HTHREAD_STRING_LC_NULL(thr) DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_LC_NULL)
2047#define DUK_STRIDX_TRUE 156 /* 'true' */
2048#define DUK_HEAP_STRING_TRUE(heap) DUK_HEAP_GET_STRING((heap),DUK_STRIDX_TRUE)
2049#define DUK_HTHREAD_STRING_TRUE(thr) DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_TRUE)
2050#define DUK_STRIDX_FALSE 157 /* 'false' */
2051#define DUK_HEAP_STRING_FALSE(heap) DUK_HEAP_GET_STRING((heap),DUK_STRIDX_FALSE)
2052#define DUK_HTHREAD_STRING_FALSE(thr) DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_FALSE)
2053#define DUK_STRIDX_IMPLEMENTS 158 /* 'implements' */
2054#define DUK_HEAP_STRING_IMPLEMENTS(heap) DUK_HEAP_GET_STRING((heap),DUK_STRIDX_IMPLEMENTS)
2055#define DUK_HTHREAD_STRING_IMPLEMENTS(thr) DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_IMPLEMENTS)
2056#define DUK_STRIDX_INTERFACE 159 /* 'interface' */
2057#define DUK_HEAP_STRING_INTERFACE(heap) DUK_HEAP_GET_STRING((heap),DUK_STRIDX_INTERFACE)
2058#define DUK_HTHREAD_STRING_INTERFACE(thr) DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_INTERFACE)
2059#define DUK_STRIDX_LET 160 /* 'let' */
2060#define DUK_HEAP_STRING_LET(heap) DUK_HEAP_GET_STRING((heap),DUK_STRIDX_LET)
2061#define DUK_HTHREAD_STRING_LET(thr) DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_LET)
2062#define DUK_STRIDX_PACKAGE 161 /* 'package' */
2063#define DUK_HEAP_STRING_PACKAGE(heap) DUK_HEAP_GET_STRING((heap),DUK_STRIDX_PACKAGE)
2064#define DUK_HTHREAD_STRING_PACKAGE(thr) DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_PACKAGE)
2065#define DUK_STRIDX_PRIVATE 162 /* 'private' */
2066#define DUK_HEAP_STRING_PRIVATE(heap) DUK_HEAP_GET_STRING((heap),DUK_STRIDX_PRIVATE)
2067#define DUK_HTHREAD_STRING_PRIVATE(thr) DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_PRIVATE)
2068#define DUK_STRIDX_PROTECTED 163 /* 'protected' */
2069#define DUK_HEAP_STRING_PROTECTED(heap) DUK_HEAP_GET_STRING((heap),DUK_STRIDX_PROTECTED)
2070#define DUK_HTHREAD_STRING_PROTECTED(thr) DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_PROTECTED)
2071#define DUK_STRIDX_PUBLIC 164 /* 'public' */
2072#define DUK_HEAP_STRING_PUBLIC(heap) DUK_HEAP_GET_STRING((heap),DUK_STRIDX_PUBLIC)
2073#define DUK_HTHREAD_STRING_PUBLIC(thr) DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_PUBLIC)
2074#define DUK_STRIDX_STATIC 165 /* 'static' */
2075#define DUK_HEAP_STRING_STATIC(heap) DUK_HEAP_GET_STRING((heap),DUK_STRIDX_STATIC)
2076#define DUK_HTHREAD_STRING_STATIC(thr) DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_STATIC)
2077#define DUK_STRIDX_YIELD 166 /* 'yield' */
2078#define DUK_HEAP_STRING_YIELD(heap) DUK_HEAP_GET_STRING((heap),DUK_STRIDX_YIELD)
2079#define DUK_HTHREAD_STRING_YIELD(thr) DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_YIELD)
2080
2081#define DUK_HEAP_NUM_STRINGS 167
2082#define DUK_STRIDX_START_RESERVED 122
2083#define DUK_STRIDX_START_STRICT_RESERVED 158
2084#define DUK_STRIDX_END_RESERVED 167 /* exclusive endpoint */
2085
2086/* To convert a heap stridx to a token number, subtract
2087 * DUK_STRIDX_START_RESERVED and add DUK_TOK_START_RESERVED.
2088 */
2089#if !defined(DUK_SINGLE_FILE)
2090DUK_INTERNAL_DECL const duk_uint8_t duk_strings_data[972];
2091#endif /* !DUK_SINGLE_FILE */
2092#define DUK_STRDATA_MAX_STRLEN 27
2093#define DUK_STRDATA_DATA_LENGTH 972
2094#endif /* DUK_USE_ROM_STRINGS */
2095
2096#if defined(DUK_USE_ROM_OBJECTS)
2097#error RAM support not enabled, rerun configure.py with --ram-support
2098#else /* DUK_USE_ROM_OBJECTS */
2283#if !defined(DUK_SINGLE_FILE)
2285#endif /* !DUK_SINGLE_FILE */
2286#define DUK_BIDX_GLOBAL 0
2287#define DUK_BIDX_GLOBAL_ENV 1
2288#define DUK_BIDX_OBJECT_CONSTRUCTOR 2
2289#define DUK_BIDX_OBJECT_PROTOTYPE 3
2290#define DUK_BIDX_FUNCTION_CONSTRUCTOR 4
2291#define DUK_BIDX_FUNCTION_PROTOTYPE 5
2292#define DUK_BIDX_NATIVE_FUNCTION_PROTOTYPE 6
2293#define DUK_BIDX_ARRAY_CONSTRUCTOR 7
2294#define DUK_BIDX_ARRAY_PROTOTYPE 8
2295#define DUK_BIDX_STRING_CONSTRUCTOR 9
2296#define DUK_BIDX_STRING_PROTOTYPE 10
2297#define DUK_BIDX_BOOLEAN_CONSTRUCTOR 11
2298#define DUK_BIDX_BOOLEAN_PROTOTYPE 12
2299#define DUK_BIDX_NUMBER_CONSTRUCTOR 13
2300#define DUK_BIDX_NUMBER_PROTOTYPE 14
2301#define DUK_BIDX_DATE_CONSTRUCTOR 15
2302#define DUK_BIDX_DATE_PROTOTYPE 16
2303#define DUK_BIDX_REGEXP_CONSTRUCTOR 17
2304#define DUK_BIDX_REGEXP_PROTOTYPE 18
2305#define DUK_BIDX_ERROR_CONSTRUCTOR 19
2306#define DUK_BIDX_ERROR_PROTOTYPE 20
2307#define DUK_BIDX_EVAL_ERROR_CONSTRUCTOR 21
2308#define DUK_BIDX_EVAL_ERROR_PROTOTYPE 22
2309#define DUK_BIDX_RANGE_ERROR_CONSTRUCTOR 23
2310#define DUK_BIDX_RANGE_ERROR_PROTOTYPE 24
2311#define DUK_BIDX_REFERENCE_ERROR_CONSTRUCTOR 25
2312#define DUK_BIDX_REFERENCE_ERROR_PROTOTYPE 26
2313#define DUK_BIDX_SYNTAX_ERROR_CONSTRUCTOR 27
2314#define DUK_BIDX_SYNTAX_ERROR_PROTOTYPE 28
2315#define DUK_BIDX_TYPE_ERROR_CONSTRUCTOR 29
2316#define DUK_BIDX_TYPE_ERROR_PROTOTYPE 30
2317#define DUK_BIDX_URI_ERROR_CONSTRUCTOR 31
2318#define DUK_BIDX_URI_ERROR_PROTOTYPE 32
2319#define DUK_BIDX_TYPE_ERROR_THROWER 33
2320#define DUK_BIDX_DUKTAPE 34
2321#define DUK_BIDX_THREAD_PROTOTYPE 35
2322#define DUK_BIDX_POINTER_PROTOTYPE 36
2323#define DUK_BIDX_DOUBLE_ERROR 37
2324#define DUK_BIDX_SYMBOL_PROTOTYPE 38
2325#define DUK_BIDX_ARRAYBUFFER_PROTOTYPE 39
2326#define DUK_BIDX_DATAVIEW_PROTOTYPE 40
2327#define DUK_BIDX_INT8ARRAY_PROTOTYPE 41
2328#define DUK_BIDX_UINT8ARRAY_PROTOTYPE 42
2329#define DUK_BIDX_UINT8CLAMPEDARRAY_PROTOTYPE 43
2330#define DUK_BIDX_INT16ARRAY_PROTOTYPE 44
2331#define DUK_BIDX_UINT16ARRAY_PROTOTYPE 45
2332#define DUK_BIDX_INT32ARRAY_PROTOTYPE 46
2333#define DUK_BIDX_UINT32ARRAY_PROTOTYPE 47
2334#define DUK_BIDX_FLOAT32ARRAY_PROTOTYPE 48
2335#define DUK_BIDX_FLOAT64ARRAY_PROTOTYPE 49
2336#define DUK_BIDX_NODEJS_BUFFER_PROTOTYPE 50
2337#define DUK_NUM_BUILTINS 51
2338#define DUK_NUM_BIDX_BUILTINS 51
2339#define DUK_NUM_ALL_BUILTINS 80
2340#if defined(DUK_USE_DOUBLE_LE)
2341#if !defined(DUK_SINGLE_FILE)
2342DUK_INTERNAL_DECL const duk_uint8_t duk_builtins_data[4281];
2343#endif /* !DUK_SINGLE_FILE */
2344#define DUK_BUILTINS_DATA_LENGTH 4281
2345#elif defined(DUK_USE_DOUBLE_BE)
2346#if !defined(DUK_SINGLE_FILE)
2347DUK_INTERNAL_DECL const duk_uint8_t duk_builtins_data[4281];
2348#endif /* !DUK_SINGLE_FILE */
2349#define DUK_BUILTINS_DATA_LENGTH 4281
2350#elif defined(DUK_USE_DOUBLE_ME)
2351#if !defined(DUK_SINGLE_FILE)
2352DUK_INTERNAL_DECL const duk_uint8_t duk_builtins_data[4281];
2353#endif /* !DUK_SINGLE_FILE */
2354#define DUK_BUILTINS_DATA_LENGTH 4281
2355#else
2356#error invalid endianness defines
2357#endif
2358#endif /* DUK_USE_ROM_OBJECTS */
2359#endif /* DUK_BUILTINS_H_INCLUDED */
2360
2361/* #include duk_util.h */
2362/*
2363 * Utilities
2364 */
2365
2366#if !defined(DUK_UTIL_H_INCLUDED)
2367#define DUK_UTIL_H_INCLUDED
2368
2369/*
2370 * Some useful constants
2371 */
2372
2373#define DUK_DOUBLE_2TO32 4294967296.0
2374#define DUK_DOUBLE_2TO31 2147483648.0
2375#define DUK_DOUBLE_LOG2E 1.4426950408889634
2376#define DUK_DOUBLE_LOG10E 0.4342944819032518
2377
2378/*
2379 * Endian conversion
2380 */
2381
2382#if defined(DUK_USE_INTEGER_LE)
2383#define DUK_HTON32(x) DUK_BSWAP32((x))
2384#define DUK_NTOH32(x) DUK_BSWAP32((x))
2385#define DUK_HTON16(x) DUK_BSWAP16((x))
2386#define DUK_NTOH16(x) DUK_BSWAP16((x))
2387#elif defined(DUK_USE_INTEGER_BE)
2388#define DUK_HTON32(x) (x)
2389#define DUK_NTOH32(x) (x)
2390#define DUK_HTON16(x) (x)
2391#define DUK_NTOH16(x) (x)
2392#else
2393#error internal error, endianness defines broken
2394#endif
2395
2396/*
2397 * Bitstream decoder
2398 */
2399
2401 const duk_uint8_t *data;
2404 duk_uint32_t currval;
2406};
2407
2408#define DUK_BD_BITPACKED_STRING_MAXLEN 256
2409
2410/*
2411 * Bitstream encoder
2412 */
2413
2415 duk_uint8_t *data;
2418 duk_uint32_t currval;
2421};
2422
2423/*
2424 * Raw write/read macros for big endian, unaligned basic values.
2425 * Caller ensures there's enough space. The INC macro variants
2426 * update the pointer argument automatically.
2427 */
2428
2429#define DUK_RAW_WRITE_U8(ptr, val) \
2430 do { \
2431 *(ptr) = (duk_uint8_t) (val); \
2432 } while (0)
2433#define DUK_RAW_WRITE_U16_BE(ptr, val) duk_raw_write_u16_be((ptr), (duk_uint16_t) (val))
2434#define DUK_RAW_WRITE_U32_BE(ptr, val) duk_raw_write_u32_be((ptr), (duk_uint32_t) (val))
2435#define DUK_RAW_WRITE_FLOAT_BE(ptr, val) duk_raw_write_float_be((ptr), (duk_float_t) (val))
2436#define DUK_RAW_WRITE_DOUBLE_BE(ptr, val) duk_raw_write_double_be((ptr), (duk_double_t) (val))
2437#define DUK_RAW_WRITE_XUTF8(ptr, val) duk_raw_write_xutf8((ptr), (duk_ucodepoint_t) (val))
2438
2439#define DUK_RAW_WRITEINC_U8(ptr, val) \
2440 do { \
2441 *(ptr)++ = (duk_uint8_t) (val); \
2442 } while (0)
2443#define DUK_RAW_WRITEINC_U16_BE(ptr, val) duk_raw_writeinc_u16_be(&(ptr), (duk_uint16_t) (val))
2444#define DUK_RAW_WRITEINC_U32_BE(ptr, val) duk_raw_writeinc_u32_be(&(ptr), (duk_uint32_t) (val))
2445#define DUK_RAW_WRITEINC_FLOAT_BE(ptr, val) duk_raw_writeinc_float_be(&(ptr), (duk_float_t) (val))
2446#define DUK_RAW_WRITEINC_DOUBLE_BE(ptr, val) duk_raw_writeinc_double_be(&(ptr), (duk_double_t) (val))
2447#define DUK_RAW_WRITEINC_XUTF8(ptr, val) duk_raw_writeinc_xutf8(&(ptr), (duk_ucodepoint_t) (val))
2448#define DUK_RAW_WRITEINC_CESU8(ptr, val) duk_raw_writeinc_cesu8(&(ptr), (duk_ucodepoint_t) (val))
2449
2450#define DUK_RAW_READ_U8(ptr) ((duk_uint8_t) (*(ptr)))
2451#define DUK_RAW_READ_U16_BE(ptr) duk_raw_read_u16_be((ptr));
2452#define DUK_RAW_READ_U32_BE(ptr) duk_raw_read_u32_be((ptr));
2453#define DUK_RAW_READ_DOUBLE_BE(ptr) duk_raw_read_double_be((ptr));
2454
2455#define DUK_RAW_READINC_U8(ptr) ((duk_uint8_t) (*(ptr)++))
2456#define DUK_RAW_READINC_U16_BE(ptr) duk_raw_readinc_u16_be(&(ptr));
2457#define DUK_RAW_READINC_U32_BE(ptr) duk_raw_readinc_u32_be(&(ptr));
2458#define DUK_RAW_READINC_DOUBLE_BE(ptr) duk_raw_readinc_double_be(&(ptr));
2459
2460/*
2461 * Double and float byte order operations.
2462 */
2463
2470
2471/*
2472 * Buffer writer (dynamic buffer only)
2473 *
2474 * Helper for writing to a dynamic buffer with a concept of a "slack" area
2475 * to reduce resizes. You can ensure there is enough space beforehand and
2476 * then write for a while without further checks, relying on a stable data
2477 * pointer. Slack handling is automatic so call sites only indicate how
2478 * much data they need right now.
2479 *
2480 * There are several ways to write using bufwriter. The best approach
2481 * depends mainly on how much performance matters over code footprint.
2482 * The key issues are (1) ensuring there is space and (2) keeping the
2483 * pointers consistent. Fast code should ensure space for multiple writes
2484 * with one ensure call. Fastest inner loop code can temporarily borrow
2485 * the 'p' pointer but must write it back eventually.
2486 *
2487 * Be careful to ensure all macro arguments (other than static pointers like
2488 * 'thr' and 'bw_ctx') are evaluated exactly once, using temporaries if
2489 * necessary (if that's not possible, there should be a note near the macro).
2490 * Buffer write arguments often contain arithmetic etc so this is
2491 * particularly important here.
2492 */
2493
2494/* XXX: Migrate bufwriter and other read/write helpers to its own header? */
2495
2497 duk_uint8_t *p;
2498 duk_uint8_t *p_base;
2499 duk_uint8_t *p_limit;
2501};
2502
2503#if defined(DUK_USE_PREFER_SIZE)
2504#define DUK_BW_SLACK_ADD 64
2505#define DUK_BW_SLACK_SHIFT 4 /* 2^4 -> 1/16 = 6.25% slack */
2506#else
2507#define DUK_BW_SLACK_ADD 64
2508#define DUK_BW_SLACK_SHIFT 2 /* 2^2 -> 1/4 = 25% slack */
2509#endif
2510
2511/* Initialization and finalization (compaction), converting to other types. */
2512
2513#define DUK_BW_INIT_PUSHBUF(thr, bw_ctx, sz) \
2514 do { \
2515 duk_bw_init_pushbuf((thr), (bw_ctx), (sz)); \
2516 } while (0)
2517#define DUK_BW_INIT_WITHBUF(thr, bw_ctx, buf) \
2518 do { \
2519 duk_bw_init((thr), (bw_ctx), (buf)); \
2520 } while (0)
2521#define DUK_BW_COMPACT(thr, bw_ctx) \
2522 do { \
2523 /* Make underlying buffer compact to match DUK_BW_GET_SIZE(). */ \
2524 duk_bw_compact((thr), (bw_ctx)); \
2525 } while (0)
2526#define DUK_BW_PUSH_AS_STRING(thr, bw_ctx) \
2527 do { \
2528 duk_push_lstring((thr), (const char *) (bw_ctx)->p_base, (duk_size_t) ((bw_ctx)->p - (bw_ctx)->p_base)); \
2529 } while (0)
2530
2531/* Pointers may be NULL for a while when 'buf' size is zero and before any
2532 * ENSURE calls have been made. Once an ENSURE has been made, the pointers
2533 * are required to be non-NULL so that it's always valid to use memcpy() and
2534 * memmove(), even for zero size.
2535 */
2536#if defined(DUK_USE_ASSERTIONS)
2537DUK_INTERNAL_DECL void duk_bw_assert_valid(duk_hthread *thr, duk_bufwriter_ctx *bw_ctx);
2538#define DUK_BW_ASSERT_VALID_EXPR(thr, bw_ctx) (duk_bw_assert_valid((thr), (bw_ctx)))
2539#define DUK_BW_ASSERT_VALID(thr, bw_ctx) \
2540 do { \
2541 duk_bw_assert_valid((thr), (bw_ctx)); \
2542 } while (0)
2543#else
2544#define DUK_BW_ASSERT_VALID_EXPR(thr, bw_ctx) DUK_ASSERT_EXPR(1)
2545#define DUK_BW_ASSERT_VALID(thr, bw_ctx) \
2546 do { \
2547 } while (0)
2548#endif
2549
2550/* Working with the pointer and current size. */
2551
2552#define DUK_BW_GET_PTR(thr, bw_ctx) ((bw_ctx)->p)
2553#define DUK_BW_SET_PTR(thr, bw_ctx, ptr) \
2554 do { \
2555 (bw_ctx)->p = (ptr); \
2556 } while (0)
2557#define DUK_BW_ADD_PTR(thr, bw_ctx, delta) \
2558 do { \
2559 (bw_ctx)->p += (delta); \
2560 } while (0)
2561#define DUK_BW_GET_BASEPTR(thr, bw_ctx) ((bw_ctx)->p_base)
2562#define DUK_BW_GET_LIMITPTR(thr, bw_ctx) ((bw_ctx)->p_limit)
2563#define DUK_BW_GET_SIZE(thr, bw_ctx) ((duk_size_t) ((bw_ctx)->p - (bw_ctx)->p_base))
2564#define DUK_BW_SET_SIZE(thr, bw_ctx, sz) \
2565 do { \
2566 DUK_ASSERT((duk_size_t) (sz) <= (duk_size_t) ((bw_ctx)->p - (bw_ctx)->p_base)); \
2567 (bw_ctx)->p = (bw_ctx)->p_base + (sz); \
2568 } while (0)
2569#define DUK_BW_RESET_SIZE(thr, bw_ctx) \
2570 do { \
2571 /* Reset to zero size, keep current limit. */ \
2572 (bw_ctx)->p = (bw_ctx)->p_base; \
2573 } while (0)
2574#define DUK_BW_GET_BUFFER(thr, bw_ctx) ((bw_ctx)->buf)
2575
2576/* Ensuring (reserving) space. */
2577
2578#define DUK_BW_ENSURE(thr, bw_ctx, sz) \
2579 do { \
2580 duk_size_t duk__sz, duk__space; \
2581 DUK_BW_ASSERT_VALID((thr), (bw_ctx)); \
2582 duk__sz = (sz); \
2583 duk__space = (duk_size_t) ((bw_ctx)->p_limit - (bw_ctx)->p); \
2584 if (duk__space < duk__sz) { \
2585 (void) duk_bw_resize((thr), (bw_ctx), duk__sz); \
2586 } \
2587 } while (0)
2588/* NOTE: Multiple evaluation of 'ptr' in this macro. */
2589/* XXX: Rework to use an always-inline function? */
2590#define DUK_BW_ENSURE_RAW(thr, bw_ctx, sz, ptr) \
2591 (((duk_size_t) ((bw_ctx)->p_limit - (ptr)) >= (sz)) ? (ptr) : ((bw_ctx)->p = (ptr), duk_bw_resize((thr), (bw_ctx), (sz))))
2592#define DUK_BW_ENSURE_GETPTR(thr, bw_ctx, sz) DUK_BW_ENSURE_RAW((thr), (bw_ctx), (sz), (bw_ctx)->p)
2593#define DUK_BW_ASSERT_SPACE_EXPR(thr, bw_ctx, sz) \
2594 (DUK_BW_ASSERT_VALID_EXPR((thr), (bw_ctx)), \
2595 DUK_ASSERT_EXPR((duk_size_t) ((bw_ctx)->p_limit - (bw_ctx)->p) >= (duk_size_t) (sz)))
2596#define DUK_BW_ASSERT_SPACE(thr, bw_ctx, sz) \
2597 do { \
2598 DUK_BW_ASSERT_SPACE_EXPR((thr), (bw_ctx), (sz)); \
2599 } while (0)
2600
2601/* Miscellaneous. */
2602
2603#define DUK_BW_SETPTR_AND_COMPACT(thr, bw_ctx, ptr) \
2604 do { \
2605 (bw_ctx)->p = (ptr); \
2606 duk_bw_compact((thr), (bw_ctx)); \
2607 } while (0)
2608
2609/* Fast write calls which assume you control the slack beforehand.
2610 * Multibyte write variants exist and use a temporary write pointer
2611 * because byte writes alias with anything: with a stored pointer
2612 * explicit pointer load/stores get generated (e.g. gcc -Os).
2613 */
2614
2615#define DUK_BW_WRITE_RAW_U8(thr, bw_ctx, val) \
2616 do { \
2617 DUK_BW_ASSERT_SPACE((thr), (bw_ctx), 1); \
2618 *(bw_ctx)->p++ = (duk_uint8_t) (val); \
2619 } while (0)
2620#define DUK_BW_WRITE_RAW_U8_2(thr, bw_ctx, val1, val2) \
2621 do { \
2622 duk_uint8_t *duk__p; \
2623 DUK_BW_ASSERT_SPACE((thr), (bw_ctx), 2); \
2624 duk__p = (bw_ctx)->p; \
2625 *duk__p++ = (duk_uint8_t) (val1); \
2626 *duk__p++ = (duk_uint8_t) (val2); \
2627 (bw_ctx)->p = duk__p; \
2628 } while (0)
2629#define DUK_BW_WRITE_RAW_U8_3(thr, bw_ctx, val1, val2, val3) \
2630 do { \
2631 duk_uint8_t *duk__p; \
2632 DUK_BW_ASSERT_SPACE((thr), (bw_ctx), 3); \
2633 duk__p = (bw_ctx)->p; \
2634 *duk__p++ = (duk_uint8_t) (val1); \
2635 *duk__p++ = (duk_uint8_t) (val2); \
2636 *duk__p++ = (duk_uint8_t) (val3); \
2637 (bw_ctx)->p = duk__p; \
2638 } while (0)
2639#define DUK_BW_WRITE_RAW_U8_4(thr, bw_ctx, val1, val2, val3, val4) \
2640 do { \
2641 duk_uint8_t *duk__p; \
2642 DUK_BW_ASSERT_SPACE((thr), (bw_ctx), 4); \
2643 duk__p = (bw_ctx)->p; \
2644 *duk__p++ = (duk_uint8_t) (val1); \
2645 *duk__p++ = (duk_uint8_t) (val2); \
2646 *duk__p++ = (duk_uint8_t) (val3); \
2647 *duk__p++ = (duk_uint8_t) (val4); \
2648 (bw_ctx)->p = duk__p; \
2649 } while (0)
2650#define DUK_BW_WRITE_RAW_U8_5(thr, bw_ctx, val1, val2, val3, val4, val5) \
2651 do { \
2652 duk_uint8_t *duk__p; \
2653 DUK_BW_ASSERT_SPACE((thr), (bw_ctx), 5); \
2654 duk__p = (bw_ctx)->p; \
2655 *duk__p++ = (duk_uint8_t) (val1); \
2656 *duk__p++ = (duk_uint8_t) (val2); \
2657 *duk__p++ = (duk_uint8_t) (val3); \
2658 *duk__p++ = (duk_uint8_t) (val4); \
2659 *duk__p++ = (duk_uint8_t) (val5); \
2660 (bw_ctx)->p = duk__p; \
2661 } while (0)
2662#define DUK_BW_WRITE_RAW_U8_6(thr, bw_ctx, val1, val2, val3, val4, val5, val6) \
2663 do { \
2664 duk_uint8_t *duk__p; \
2665 DUK_BW_ASSERT_SPACE((thr), (bw_ctx), 6); \
2666 duk__p = (bw_ctx)->p; \
2667 *duk__p++ = (duk_uint8_t) (val1); \
2668 *duk__p++ = (duk_uint8_t) (val2); \
2669 *duk__p++ = (duk_uint8_t) (val3); \
2670 *duk__p++ = (duk_uint8_t) (val4); \
2671 *duk__p++ = (duk_uint8_t) (val5); \
2672 *duk__p++ = (duk_uint8_t) (val6); \
2673 (bw_ctx)->p = duk__p; \
2674 } while (0)
2675#define DUK_BW_WRITE_RAW_XUTF8(thr, bw_ctx, cp) \
2676 do { \
2677 duk_ucodepoint_t duk__cp; \
2678 duk_small_int_t duk__enc_len; \
2679 duk__cp = (duk_ucodepoint_t) (cp); \
2680 DUK_BW_ASSERT_SPACE((thr), (bw_ctx), duk_unicode_get_xutf8_length(duk__cp)); \
2681 duk__enc_len = duk_unicode_encode_xutf8(duk__cp, (bw_ctx)->p); \
2682 (bw_ctx)->p += duk__enc_len; \
2683 } while (0)
2684#define DUK_BW_WRITE_RAW_CESU8(thr, bw_ctx, cp) \
2685 do { \
2686 duk_ucodepoint_t duk__cp; \
2687 duk_small_int_t duk__enc_len; \
2688 duk__cp = (duk_ucodepoint_t) (cp); \
2689 DUK_BW_ASSERT_SPACE((thr), (bw_ctx), duk_unicode_get_cesu8_length(duk__cp)); \
2690 duk__enc_len = duk_unicode_encode_cesu8(duk__cp, (bw_ctx)->p); \
2691 (bw_ctx)->p += duk__enc_len; \
2692 } while (0)
2693/* XXX: add temporary duk__p pointer here too; sharing */
2694/* XXX: avoid unsafe variants */
2695#define DUK_BW_WRITE_RAW_BYTES(thr, bw_ctx, valptr, valsz) \
2696 do { \
2697 const void *duk__valptr; \
2698 duk_size_t duk__valsz; \
2699 duk__valptr = (const void *) (valptr); \
2700 duk__valsz = (duk_size_t) (valsz); \
2701 duk_memcpy_unsafe((void *) ((bw_ctx)->p), duk__valptr, duk__valsz); \
2702 (bw_ctx)->p += duk__valsz; \
2703 } while (0)
2704#define DUK_BW_WRITE_RAW_CSTRING(thr, bw_ctx, val) \
2705 do { \
2706 const duk_uint8_t *duk__val; \
2707 duk_size_t duk__val_len; \
2708 duk__val = (const duk_uint8_t *) (val); \
2709 duk__val_len = DUK_STRLEN((const char *) duk__val); \
2710 duk_memcpy_unsafe((void *) ((bw_ctx)->p), (const void *) duk__val, duk__val_len); \
2711 (bw_ctx)->p += duk__val_len; \
2712 } while (0)
2713#define DUK_BW_WRITE_RAW_HSTRING(thr, bw_ctx, val) \
2714 do { \
2715 duk_size_t duk__val_len; \
2716 duk__val_len = DUK_HSTRING_GET_BYTELEN((val)); \
2717 duk_memcpy_unsafe((void *) ((bw_ctx)->p), (const void *) DUK_HSTRING_GET_DATA((val)), duk__val_len); \
2718 (bw_ctx)->p += duk__val_len; \
2719 } while (0)
2720#define DUK_BW_WRITE_RAW_HBUFFER(thr, bw_ctx, val) \
2721 do { \
2722 duk_size_t duk__val_len; \
2723 duk__val_len = DUK_HBUFFER_GET_SIZE((val)); \
2724 duk_memcpy_unsafe((void *) ((bw_ctx)->p), \
2725 (const void *) DUK_HBUFFER_GET_DATA_PTR((thr)->heap, (val)), \
2726 duk__val_len); \
2727 (bw_ctx)->p += duk__val_len; \
2728 } while (0)
2729#define DUK_BW_WRITE_RAW_HBUFFER_FIXED(thr, bw_ctx, val) \
2730 do { \
2731 duk_size_t duk__val_len; \
2732 duk__val_len = DUK_HBUFFER_FIXED_GET_SIZE((val)); \
2733 duk_memcpy_unsafe((void *) ((bw_ctx)->p), \
2734 (const void *) DUK_HBUFFER_FIXED_GET_DATA_PTR((thr)->heap, (val)), \
2735 duk__val_len); \
2736 (bw_ctx)->p += duk__val_len; \
2737 } while (0)
2738#define DUK_BW_WRITE_RAW_HBUFFER_DYNAMIC(thr, bw_ctx, val) \
2739 do { \
2740 duk_size_t duk__val_len; \
2741 duk__val_len = DUK_HBUFFER_DYNAMIC_GET_SIZE((val)); \
2742 duk_memcpy_unsafe((void *) ((bw_ctx)->p), \
2743 (const void *) DUK_HBUFFER_DYNAMIC_GET_DATA_PTR((thr)->heap, (val)), \
2744 duk__val_len); \
2745 (bw_ctx)->p += duk__val_len; \
2746 } while (0)
2747
2748/* Append bytes from a slice already in the buffer. */
2749#define DUK_BW_WRITE_RAW_SLICE(thr, bw, dst_off, dst_len) duk_bw_write_raw_slice((thr), (bw), (dst_off), (dst_len))
2750
2751/* Insert bytes in the middle of the buffer from an external buffer. */
2752#define DUK_BW_INSERT_RAW_BYTES(thr, bw, dst_off, buf, len) duk_bw_insert_raw_bytes((thr), (bw), (dst_off), (buf), (len))
2753
2754/* Insert bytes in the middle of the buffer from a slice already
2755 * in the buffer. Source offset is interpreted "before" the operation.
2756 */
2757#define DUK_BW_INSERT_RAW_SLICE(thr, bw, dst_off, src_off, len) duk_bw_insert_raw_slice((thr), (bw), (dst_off), (src_off), (len))
2758
2759/* Insert a reserved area somewhere in the buffer; caller fills it.
2760 * Evaluates to a (duk_uint_t *) pointing to the start of the reserved
2761 * area for convenience.
2762 */
2763#define DUK_BW_INSERT_RAW_AREA(thr, bw, off, len) duk_bw_insert_raw_area((thr), (bw), (off), (len))
2764
2765/* Remove a slice from inside buffer. */
2766#define DUK_BW_REMOVE_RAW_SLICE(thr, bw, off, len) duk_bw_remove_raw_slice((thr), (bw), (off), (len))
2767
2768/* Safe write calls which will ensure space first. */
2769
2770#define DUK_BW_WRITE_ENSURE_U8(thr, bw_ctx, val) \
2771 do { \
2772 DUK_BW_ENSURE((thr), (bw_ctx), 1); \
2773 DUK_BW_WRITE_RAW_U8((thr), (bw_ctx), (val)); \
2774 } while (0)
2775#define DUK_BW_WRITE_ENSURE_U8_2(thr, bw_ctx, val1, val2) \
2776 do { \
2777 DUK_BW_ENSURE((thr), (bw_ctx), 2); \
2778 DUK_BW_WRITE_RAW_U8_2((thr), (bw_ctx), (val1), (val2)); \
2779 } while (0)
2780#define DUK_BW_WRITE_ENSURE_U8_3(thr, bw_ctx, val1, val2, val3) \
2781 do { \
2782 DUK_BW_ENSURE((thr), (bw_ctx), 3); \
2783 DUK_BW_WRITE_RAW_U8_3((thr), (bw_ctx), (val1), (val2), (val3)); \
2784 } while (0)
2785#define DUK_BW_WRITE_ENSURE_U8_4(thr, bw_ctx, val1, val2, val3, val4) \
2786 do { \
2787 DUK_BW_ENSURE((thr), (bw_ctx), 4); \
2788 DUK_BW_WRITE_RAW_U8_4((thr), (bw_ctx), (val1), (val2), (val3), (val4)); \
2789 } while (0)
2790#define DUK_BW_WRITE_ENSURE_U8_5(thr, bw_ctx, val1, val2, val3, val4, val5) \
2791 do { \
2792 DUK_BW_ENSURE((thr), (bw_ctx), 5); \
2793 DUK_BW_WRITE_RAW_U8_5((thr), (bw_ctx), (val1), (val2), (val3), (val4), (val5)); \
2794 } while (0)
2795#define DUK_BW_WRITE_ENSURE_U8_6(thr, bw_ctx, val1, val2, val3, val4, val5, val6) \
2796 do { \
2797 DUK_BW_ENSURE((thr), (bw_ctx), 6); \
2798 DUK_BW_WRITE_RAW_U8_6((thr), (bw_ctx), (val1), (val2), (val3), (val4), (val5), (val6)); \
2799 } while (0)
2800#define DUK_BW_WRITE_ENSURE_XUTF8(thr, bw_ctx, cp) \
2801 do { \
2802 DUK_BW_ENSURE((thr), (bw_ctx), DUK_UNICODE_MAX_XUTF8_LENGTH); \
2803 DUK_BW_WRITE_RAW_XUTF8((thr), (bw_ctx), (cp)); \
2804 } while (0)
2805#define DUK_BW_WRITE_ENSURE_CESU8(thr, bw_ctx, cp) \
2806 do { \
2807 DUK_BW_ENSURE((thr), (bw_ctx), DUK_UNICODE_MAX_CESU8_LENGTH); \
2808 DUK_BW_WRITE_RAW_CESU8((thr), (bw_ctx), (cp)); \
2809 } while (0)
2810/* XXX: add temporary duk__p pointer here too; sharing */
2811/* XXX: avoid unsafe */
2812#define DUK_BW_WRITE_ENSURE_BYTES(thr, bw_ctx, valptr, valsz) \
2813 do { \
2814 const void *duk__valptr; \
2815 duk_size_t duk__valsz; \
2816 duk__valptr = (const void *) (valptr); \
2817 duk__valsz = (duk_size_t) (valsz); \
2818 DUK_BW_ENSURE((thr), (bw_ctx), duk__valsz); \
2819 duk_memcpy_unsafe((void *) ((bw_ctx)->p), duk__valptr, duk__valsz); \
2820 (bw_ctx)->p += duk__valsz; \
2821 } while (0)
2822#define DUK_BW_WRITE_ENSURE_CSTRING(thr, bw_ctx, val) \
2823 do { \
2824 const duk_uint8_t *duk__val; \
2825 duk_size_t duk__val_len; \
2826 duk__val = (const duk_uint8_t *) (val); \
2827 duk__val_len = DUK_STRLEN((const char *) duk__val); \
2828 DUK_BW_ENSURE((thr), (bw_ctx), duk__val_len); \
2829 duk_memcpy_unsafe((void *) ((bw_ctx)->p), (const void *) duk__val, duk__val_len); \
2830 (bw_ctx)->p += duk__val_len; \
2831 } while (0)
2832#define DUK_BW_WRITE_ENSURE_HSTRING(thr, bw_ctx, val) \
2833 do { \
2834 duk_size_t duk__val_len; \
2835 duk__val_len = DUK_HSTRING_GET_BYTELEN((val)); \
2836 DUK_BW_ENSURE((thr), (bw_ctx), duk__val_len); \
2837 duk_memcpy_unsafe((void *) ((bw_ctx)->p), (const void *) DUK_HSTRING_GET_DATA((val)), duk__val_len); \
2838 (bw_ctx)->p += duk__val_len; \
2839 } while (0)
2840#define DUK_BW_WRITE_ENSURE_HBUFFER(thr, bw_ctx, val) \
2841 do { \
2842 duk_size_t duk__val_len; \
2843 duk__val_len = DUK_HBUFFER_GET_SIZE((val)); \
2844 DUK_BW_ENSURE((thr), (bw_ctx), duk__val_len); \
2845 duk_memcpy_unsafe((void *) ((bw_ctx)->p), \
2846 (const void *) DUK_HBUFFER_GET_DATA_PTR((thr)->heap, (val)), \
2847 duk__val_len); \
2848 (bw_ctx)->p += duk__val_len; \
2849 } while (0)
2850#define DUK_BW_WRITE_ENSURE_HBUFFER_FIXED(thr, bw_ctx, val) \
2851 do { \
2852 duk_size_t duk__val_len; \
2853 duk__val_len = DUK_HBUFFER_FIXED_GET_SIZE((val)); \
2854 DUK_BW_ENSURE((thr), (bw_ctx), duk__val_len); \
2855 duk_memcpy_unsafe((void *) ((bw_ctx)->p), \
2856 (const void *) DUK_HBUFFER_FIXED_GET_DATA_PTR((thr)->heap, (val)), \
2857 duk__val_len); \
2858 (bw_ctx)->p += duk__val_len; \
2859 } while (0)
2860#define DUK_BW_WRITE_ENSURE_HBUFFER_DYNAMIC(thr, bw_ctx, val) \
2861 do { \
2862 duk_size_t duk__val_len; \
2863 duk__val_len = DUK_HBUFFER_DYNAMIC_GET_SIZE((val)); \
2864 DUK_BW_ENSURE((thr), (bw_ctx), duk__val_len); \
2865 duk_memcpy_unsafe((void *) ((bw_ctx)->p), \
2866 (const void *) DUK_HBUFFER_DYNAMIC_GET_DATA_PTR((thr)->heap, (val)), \
2867 duk__val_len); \
2868 (bw_ctx)->p += duk__val_len; \
2869 } while (0)
2870
2871#define DUK_BW_WRITE_ENSURE_SLICE(thr, bw, dst_off, dst_len) duk_bw_write_ensure_slice((thr), (bw), (dst_off), (dst_len))
2872#define DUK_BW_INSERT_ENSURE_BYTES(thr, bw, dst_off, buf, len) duk_bw_insert_ensure_bytes((thr), (bw), (dst_off), (buf), (len))
2873#define DUK_BW_INSERT_ENSURE_SLICE(thr, bw, dst_off, src_off, len) \
2874 duk_bw_insert_ensure_slice((thr), (bw), (dst_off), (src_off), (len))
2875#define DUK_BW_INSERT_ENSURE_AREA(thr, bw, off, len) \
2876 /* Evaluates to (duk_uint8_t *) pointing to start of area. */ \
2877 duk_bw_insert_ensure_area((thr), (bw), (off), (len))
2878#define DUK_BW_REMOVE_ENSURE_SLICE(thr, bw, off, len) \
2879 /* No difference between raw/ensure because the buffer shrinks. */ \
2880 DUK_BW_REMOVE_RAW_SLICE((thr), (bw), (off), (len))
2881
2882/*
2883 * Externs and prototypes
2884 */
2885
2886#if !defined(DUK_SINGLE_FILE)
2887DUK_INTERNAL_DECL const duk_uint8_t duk_lc_digits[36];
2888DUK_INTERNAL_DECL const duk_uint8_t duk_uc_nybbles[16];
2889DUK_INTERNAL_DECL const duk_int8_t duk_hex_dectab[256];
2890#if defined(DUK_USE_HEX_FASTPATH)
2891DUK_INTERNAL_DECL const duk_int16_t duk_hex_dectab_shift4[256];
2892DUK_INTERNAL_DECL const duk_uint16_t duk_hex_enctab[256];
2893#endif
2894#endif /* !DUK_SINGLE_FILE */
2895
2896/* Note: assumes that duk_util_probe_steps size is 32 */
2897#if defined(DUK_USE_HOBJECT_HASH_PART)
2898#if !defined(DUK_SINGLE_FILE)
2899DUK_INTERNAL_DECL duk_uint8_t duk_util_probe_steps[32];
2900#endif /* !DUK_SINGLE_FILE */
2901#endif
2902
2903#if defined(DUK_USE_STRHASH_DENSE)
2904DUK_INTERNAL_DECL duk_uint32_t duk_util_hashbytes(const duk_uint8_t *data, duk_size_t len, duk_uint32_t seed);
2905#endif
2906
2909DUK_INTERNAL_DECL duk_uint32_t duk_bd_decode_flagged(duk_bitdecoder_ctx *ctx, duk_small_int_t bits, duk_uint32_t def_value);
2910DUK_INTERNAL_DECL duk_int32_t duk_bd_decode_flagged_signed(duk_bitdecoder_ctx *ctx, duk_small_int_t bits, duk_int32_t def_value);
2913
2914DUK_INTERNAL_DECL void duk_be_encode(duk_bitencoder_ctx *ctx, duk_uint32_t data, duk_small_int_t bits);
2916
2917#if !defined(DUK_USE_GET_RANDOM_DOUBLE)
2920#endif
2921
2930 duk_size_t dst_off,
2931 const duk_uint8_t *buf,
2932 duk_size_t len);
2935 duk_size_t dst_off,
2936 const duk_uint8_t *buf,
2937 duk_size_t len);
2940 duk_size_t dst_off,
2941 duk_size_t src_off,
2942 duk_size_t len);
2945 duk_size_t dst_off,
2946 duk_size_t src_off,
2947 duk_size_t len);
2951/* No duk_bw_remove_ensure_slice(), functionality would be identical. */
2952
2953DUK_INTERNAL_DECL duk_uint16_t duk_raw_read_u16_be(const duk_uint8_t *p);
2954DUK_INTERNAL_DECL duk_uint32_t duk_raw_read_u32_be(const duk_uint8_t *p);
2957DUK_INTERNAL_DECL duk_uint16_t duk_raw_readinc_u16_be(const duk_uint8_t **p);
2958DUK_INTERNAL_DECL duk_uint32_t duk_raw_readinc_u32_be(const duk_uint8_t **p);
2961DUK_INTERNAL_DECL void duk_raw_write_u16_be(duk_uint8_t *p, duk_uint16_t val);
2962DUK_INTERNAL_DECL void duk_raw_write_u32_be(duk_uint8_t *p, duk_uint32_t val);
2963DUK_INTERNAL_DECL void duk_raw_write_float_be(duk_uint8_t *p, duk_float_t val);
2967DUK_INTERNAL_DECL void duk_raw_writeinc_u16_be(duk_uint8_t **p, duk_uint16_t val);
2968DUK_INTERNAL_DECL void duk_raw_writeinc_u32_be(duk_uint8_t **p, duk_uint32_t val);
2973
2974#if defined(DUK_USE_DEBUGGER_SUPPORT) /* For now only needed by the debugger. */
2975DUK_INTERNAL_DECL void duk_byteswap_bytes(duk_uint8_t *p, duk_small_uint_t len);
2976#endif
2977
2979
2980/* memcpy(), memmove() etc wrappers. The plain variants like duk_memcpy()
2981 * assume C99+ and 'src' and 'dst' pointers must be non-NULL even when the
2982 * operation size is zero. The unsafe variants like duk_memcpy_safe() deal
2983 * with the zero size case explicitly, and allow NULL pointers in that case
2984 * (which is undefined behavior in C99+). For the majority of actual targets
2985 * a NULL pointer with a zero length is fine in practice. These wrappers are
2986 * macros to force inlining; because there are hundreds of call sites, even a
2987 * few extra bytes per call site adds up to ~1kB footprint.
2988 */
2989#if defined(DUK_USE_ALLOW_UNDEFINED_BEHAVIOR)
2990#define duk_memcpy(dst, src, len) \
2991 do { \
2992 void *duk__dst = (dst); \
2993 const void *duk__src = (src); \
2994 duk_size_t duk__len = (len); \
2995 DUK_ASSERT(duk__dst != NULL || duk__len == 0U); \
2996 DUK_ASSERT(duk__src != NULL || duk__len == 0U); \
2997 (void) DUK_MEMCPY(duk__dst, duk__src, (size_t) duk__len); \
2998 } while (0)
2999#define duk_memcpy_unsafe(dst, src, len) duk_memcpy((dst), (src), (len))
3000#define duk_memmove(dst, src, len) \
3001 do { \
3002 void *duk__dst = (dst); \
3003 const void *duk__src = (src); \
3004 duk_size_t duk__len = (len); \
3005 DUK_ASSERT(duk__dst != NULL || duk__len == 0U); \
3006 DUK_ASSERT(duk__src != NULL || duk__len == 0U); \
3007 (void) DUK_MEMMOVE(duk__dst, duk__src, (size_t) duk__len); \
3008 } while (0)
3009#define duk_memmove_unsafe(dst, src, len) duk_memmove((dst), (src), (len))
3010#define duk_memset(dst, val, len) \
3011 do { \
3012 void *duk__dst = (dst); \
3013 duk_small_int_t duk__val = (val); \
3014 duk_size_t duk__len = (len); \
3015 DUK_ASSERT(duk__dst != NULL || duk__len == 0U); \
3016 (void) DUK_MEMSET(duk__dst, duk__val, (size_t) duk__len); \
3017 } while (0)
3018#define duk_memset_unsafe(dst, val, len) duk_memset((dst), (val), (len))
3019#define duk_memzero(dst, len) \
3020 do { \
3021 void *duk__dst = (dst); \
3022 duk_size_t duk__len = (len); \
3023 DUK_ASSERT(duk__dst != NULL || duk__len == 0U); \
3024 (void) DUK_MEMZERO(duk__dst, (size_t) duk__len); \
3025 } while (0)
3026#define duk_memzero_unsafe(dst, len) duk_memzero((dst), (len))
3027#else /* DUK_USE_ALLOW_UNDEFINED_BEHAVIOR */
3028#define duk_memcpy(dst, src, len) \
3029 do { \
3030 void *duk__dst = (dst); \
3031 const void *duk__src = (src); \
3032 duk_size_t duk__len = (len); \
3033 DUK_ASSERT(duk__dst != NULL); \
3034 DUK_ASSERT(duk__src != NULL); \
3035 (void) DUK_MEMCPY(duk__dst, duk__src, (size_t) duk__len); \
3036 } while (0)
3037#define duk_memcpy_unsafe(dst, src, len) \
3038 do { \
3039 void *duk__dst = (dst); \
3040 const void *duk__src = (src); \
3041 duk_size_t duk__len = (len); \
3042 DUK_ASSERT(duk__dst != NULL || duk__len == 0U); \
3043 DUK_ASSERT(duk__src != NULL || duk__len == 0U); \
3044 if (DUK_LIKELY(duk__len > 0U)) { \
3045 DUK_ASSERT(duk__dst != NULL); \
3046 DUK_ASSERT(duk__src != NULL); \
3047 (void) DUK_MEMCPY(duk__dst, duk__src, (size_t) duk__len); \
3048 } \
3049 } while (0)
3050#define duk_memmove(dst, src, len) \
3051 do { \
3052 void *duk__dst = (dst); \
3053 const void *duk__src = (src); \
3054 duk_size_t duk__len = (len); \
3055 DUK_ASSERT(duk__dst != NULL); \
3056 DUK_ASSERT(duk__src != NULL); \
3057 (void) DUK_MEMMOVE(duk__dst, duk__src, (size_t) duk__len); \
3058 } while (0)
3059#define duk_memmove_unsafe(dst, src, len) \
3060 do { \
3061 void *duk__dst = (dst); \
3062 const void *duk__src = (src); \
3063 duk_size_t duk__len = (len); \
3064 DUK_ASSERT(duk__dst != NULL || duk__len == 0U); \
3065 DUK_ASSERT(duk__src != NULL || duk__len == 0U); \
3066 if (DUK_LIKELY(duk__len > 0U)) { \
3067 DUK_ASSERT(duk__dst != NULL); \
3068 DUK_ASSERT(duk__src != NULL); \
3069 (void) DUK_MEMMOVE(duk__dst, duk__src, (size_t) duk__len); \
3070 } \
3071 } while (0)
3072#define duk_memset(dst, val, len) \
3073 do { \
3074 void *duk__dst = (dst); \
3075 duk_small_int_t duk__val = (val); \
3076 duk_size_t duk__len = (len); \
3077 DUK_ASSERT(duk__dst != NULL); \
3078 (void) DUK_MEMSET(duk__dst, duk__val, (size_t) duk__len); \
3079 } while (0)
3080#define duk_memset_unsafe(dst, val, len) \
3081 do { \
3082 void *duk__dst = (dst); \
3083 duk_small_int_t duk__val = (val); \
3084 duk_size_t duk__len = (len); \
3085 DUK_ASSERT(duk__dst != NULL || duk__len == 0U); \
3086 if (DUK_LIKELY(duk__len > 0U)) { \
3087 DUK_ASSERT(duk__dst != NULL); \
3088 (void) DUK_MEMSET(duk__dst, duk__val, (size_t) duk__len); \
3089 } \
3090 } while (0)
3091#define duk_memzero(dst, len) \
3092 do { \
3093 void *duk__dst = (dst); \
3094 duk_size_t duk__len = (len); \
3095 DUK_ASSERT(duk__dst != NULL); \
3096 (void) DUK_MEMZERO(duk__dst, (size_t) duk__len); \
3097 } while (0)
3098#define duk_memzero_unsafe(dst, len) \
3099 do { \
3100 void *duk__dst = (dst); \
3101 duk_size_t duk__len = (len); \
3102 DUK_ASSERT(duk__dst != NULL || duk__len == 0U); \
3103 if (DUK_LIKELY(duk__len > 0U)) { \
3104 DUK_ASSERT(duk__dst != NULL); \
3105 (void) DUK_MEMZERO(duk__dst, (size_t) duk__len); \
3106 } \
3107 } while (0)
3108#endif /* DUK_USE_ALLOW_UNDEFINED_BEHAVIOR */
3109
3110DUK_INTERNAL_DECL duk_small_int_t duk_memcmp(const void *s1, const void *s2, duk_size_t len);
3111DUK_INTERNAL_DECL duk_small_int_t duk_memcmp_unsafe(const void *s1, const void *s2, duk_size_t len);
3112
3130
3139
3140/*
3141 * Miscellaneous
3142 */
3143
3144/* Example: x = 0x10 = 0b00010000
3145 * x - 1 = 0x0f = 0b00001111
3146 * x & (x - 1) == 0
3147 *
3148 * x = 0x07 = 0b00000111
3149 * x - 1 = 0x06 = 0b00000110
3150 * x & (x - 1) != 0
3151 *
3152 * However, incorrectly true for x == 0 so check for that explicitly.
3153 */
3154#define DUK_IS_POWER_OF_TWO(x) ((x) != 0U && ((x) & ((x) -1U)) == 0U)
3155
3156#endif /* DUK_UTIL_H_INCLUDED */
3157/* #include duk_strings.h */
3158/*
3159 * Shared string macros.
3160 *
3161 * Using shared macros helps minimize strings data size because it's easy
3162 * to check if an existing string could be used. String constants don't
3163 * need to be all defined here; defining a string here makes sense if there's
3164 * a high chance the string could be reused. Also, using macros allows
3165 * a call site express the exact string needed, but the macro may map to an
3166 * approximate string to reduce unique string count. Macros can also be
3167 * more easily tuned for low memory targets than #if defined()s throughout
3168 * the code base.
3169 *
3170 * Because format strings behave differently in the call site (they need to
3171 * be followed by format arguments), they use a special prefix DUK_STR_FMT_.
3172 *
3173 * On some compilers using explicit shared strings is preferable; on others
3174 * it may be better to use straight literals because the compiler will combine
3175 * them anyway, and such strings won't end up unnecessarily in a symbol table.
3176 */
3177
3178#if !defined(DUK_ERRMSG_H_INCLUDED)
3179#define DUK_ERRMSG_H_INCLUDED
3180
3181/* Mostly API and built-in method related */
3182#define DUK_STR_INTERNAL_ERROR "internal error"
3183#define DUK_STR_UNSUPPORTED "unsupported"
3184#define DUK_STR_INVALID_COUNT "invalid count"
3185#define DUK_STR_INVALID_ARGS "invalid args"
3186#define DUK_STR_INVALID_STATE "invalid state"
3187#define DUK_STR_INVALID_INPUT "invalid input"
3188#define DUK_STR_INVALID_LENGTH "invalid length"
3189#define DUK_STR_NOT_CONSTRUCTABLE "not constructable"
3190#define DUK_STR_CONSTRUCT_ONLY "constructor requires 'new'"
3191#define DUK_STR_NOT_CALLABLE "not callable"
3192#define DUK_STR_NOT_EXTENSIBLE "not extensible"
3193#define DUK_STR_NOT_WRITABLE "not writable"
3194#define DUK_STR_NOT_CONFIGURABLE "not configurable"
3195#define DUK_STR_INVALID_CONTEXT "invalid context"
3196#define DUK_STR_INVALID_INDEX "invalid args"
3197#define DUK_STR_PUSH_BEYOND_ALLOC_STACK "cannot push beyond allocated stack"
3198#define DUK_STR_NOT_UNDEFINED "unexpected type"
3199#define DUK_STR_NOT_NULL "unexpected type"
3200#define DUK_STR_NOT_BOOLEAN "unexpected type"
3201#define DUK_STR_NOT_NUMBER "unexpected type"
3202#define DUK_STR_NOT_STRING "unexpected type"
3203#define DUK_STR_NOT_OBJECT "unexpected type"
3204#define DUK_STR_NOT_POINTER "unexpected type"
3205#define DUK_STR_NOT_BUFFER "not buffer" /* still in use with verbose messages */
3206#define DUK_STR_UNEXPECTED_TYPE "unexpected type"
3207#define DUK_STR_NOT_THREAD "unexpected type"
3208#define DUK_STR_NOT_COMPFUNC "unexpected type"
3209#define DUK_STR_NOT_NATFUNC "unexpected type"
3210#define DUK_STR_NOT_C_FUNCTION "unexpected type"
3211#define DUK_STR_NOT_FUNCTION "unexpected type"
3212#define DUK_STR_NOT_REGEXP "unexpected type"
3213#define DUK_STR_TOPRIMITIVE_FAILED "coercion to primitive failed"
3214#define DUK_STR_NUMBER_OUTSIDE_RANGE "number outside range"
3215#define DUK_STR_NOT_OBJECT_COERCIBLE "not object coercible"
3216#define DUK_STR_CANNOT_NUMBER_COERCE_SYMBOL "cannot number coerce Symbol"
3217#define DUK_STR_CANNOT_STRING_COERCE_SYMBOL "cannot string coerce Symbol"
3218#define DUK_STR_STRING_TOO_LONG "string too long"
3219#define DUK_STR_BUFFER_TOO_LONG "buffer too long"
3220#define DUK_STR_ALLOC_FAILED "alloc failed"
3221#define DUK_STR_WRONG_BUFFER_TYPE "wrong buffer type"
3222#define DUK_STR_BASE64_ENCODE_FAILED "base64 encode failed"
3223#define DUK_STR_SOURCE_DECODE_FAILED "source decode failed"
3224#define DUK_STR_UTF8_DECODE_FAILED "utf-8 decode failed"
3225#define DUK_STR_BASE64_DECODE_FAILED "base64 decode failed"
3226#define DUK_STR_HEX_DECODE_FAILED "hex decode failed"
3227#define DUK_STR_INVALID_BYTECODE "invalid bytecode"
3228#define DUK_STR_NO_SOURCECODE "no sourcecode"
3229#define DUK_STR_RESULT_TOO_LONG "result too long"
3230#define DUK_STR_INVALID_CFUNC_RC "invalid C function rc"
3231#define DUK_STR_INVALID_INSTANCEOF_RVAL "invalid instanceof rval"
3232#define DUK_STR_INVALID_INSTANCEOF_RVAL_NOPROTO "instanceof rval has no .prototype"
3233
3234/* JSON */
3235#define DUK_STR_FMT_PTR "%p"
3236#define DUK_STR_FMT_INVALID_JSON "invalid json (at offset %ld)"
3237#define DUK_STR_CYCLIC_INPUT "cyclic input"
3238
3239/* Generic codec */
3240#define DUK_STR_DEC_RECLIMIT "decode recursion limit"
3241#define DUK_STR_ENC_RECLIMIT "encode recursion limit"
3242
3243/* Object property access */
3244#define DUK_STR_INVALID_BASE "invalid base value"
3245#define DUK_STR_STRICT_CALLER_READ "cannot read strict 'caller'"
3246#define DUK_STR_PROXY_REJECTED "proxy rejected"
3247#define DUK_STR_INVALID_ARRAY_LENGTH "invalid array length"
3248#define DUK_STR_SETTER_UNDEFINED "setter undefined"
3249#define DUK_STR_INVALID_DESCRIPTOR "invalid descriptor"
3250
3251/* Proxy */
3252#define DUK_STR_PROXY_REVOKED "proxy revoked"
3253#define DUK_STR_INVALID_TRAP_RESULT "invalid trap result"
3254
3255/* Variables */
3256
3257/* Lexer */
3258#define DUK_STR_INVALID_ESCAPE "invalid escape"
3259#define DUK_STR_UNTERMINATED_STRING "unterminated string"
3260#define DUK_STR_UNTERMINATED_COMMENT "unterminated comment"
3261#define DUK_STR_UNTERMINATED_REGEXP "unterminated regexp"
3262#define DUK_STR_TOKEN_LIMIT "token limit"
3263#define DUK_STR_REGEXP_SUPPORT_DISABLED "regexp support disabled"
3264#define DUK_STR_INVALID_NUMBER_LITERAL "invalid number literal"
3265#define DUK_STR_INVALID_TOKEN "invalid token"
3266
3267/* Compiler */
3268#define DUK_STR_PARSE_ERROR "parse error"
3269#define DUK_STR_DUPLICATE_LABEL "duplicate label"
3270#define DUK_STR_INVALID_LABEL "invalid label"
3271#define DUK_STR_INVALID_ARRAY_LITERAL "invalid array literal"
3272#define DUK_STR_INVALID_OBJECT_LITERAL "invalid object literal"
3273#define DUK_STR_INVALID_VAR_DECLARATION "invalid variable declaration"
3274#define DUK_STR_CANNOT_DELETE_IDENTIFIER "cannot delete identifier"
3275#define DUK_STR_INVALID_EXPRESSION "invalid expression"
3276#define DUK_STR_INVALID_LVALUE "invalid lvalue"
3277#define DUK_STR_INVALID_NEWTARGET "invalid new.target"
3278#define DUK_STR_EXPECTED_IDENTIFIER "expected identifier"
3279#define DUK_STR_EMPTY_EXPR_NOT_ALLOWED "empty expression not allowed"
3280#define DUK_STR_INVALID_FOR "invalid for statement"
3281#define DUK_STR_INVALID_SWITCH "invalid switch statement"
3282#define DUK_STR_INVALID_BREAK_CONT_LABEL "invalid break/continue label"
3283#define DUK_STR_INVALID_RETURN "invalid return"
3284#define DUK_STR_INVALID_TRY "invalid try"
3285#define DUK_STR_INVALID_THROW "invalid throw"
3286#define DUK_STR_WITH_IN_STRICT_MODE "with in strict mode"
3287#define DUK_STR_FUNC_STMT_NOT_ALLOWED "function statement not allowed"
3288#define DUK_STR_UNTERMINATED_STMT "unterminated statement"
3289#define DUK_STR_INVALID_ARG_NAME "invalid argument name"
3290#define DUK_STR_INVALID_FUNC_NAME "invalid function name"
3291#define DUK_STR_INVALID_GETSET_NAME "invalid getter/setter name"
3292#define DUK_STR_FUNC_NAME_REQUIRED "function name required"
3293
3294/* RegExp */
3295#define DUK_STR_INVALID_QUANTIFIER "invalid regexp quantifier"
3296#define DUK_STR_INVALID_QUANTIFIER_NO_ATOM "quantifier without preceding atom"
3297#define DUK_STR_INVALID_QUANTIFIER_VALUES "quantifier values invalid (qmin > qmax)"
3298#define DUK_STR_QUANTIFIER_TOO_MANY_COPIES "quantifier requires too many atom copies"
3299#define DUK_STR_UNEXPECTED_CLOSING_PAREN "unexpected closing parenthesis"
3300#define DUK_STR_UNEXPECTED_END_OF_PATTERN "unexpected end of pattern"
3301#define DUK_STR_UNEXPECTED_REGEXP_TOKEN "unexpected token in regexp"
3302#define DUK_STR_INVALID_REGEXP_FLAGS "invalid regexp flags"
3303#define DUK_STR_INVALID_REGEXP_ESCAPE "invalid regexp escape"
3304#define DUK_STR_INVALID_BACKREFS "invalid backreference(s)"
3305#define DUK_STR_INVALID_REGEXP_CHARACTER "invalid regexp character"
3306#define DUK_STR_INVALID_REGEXP_GROUP "invalid regexp group"
3307#define DUK_STR_UNTERMINATED_CHARCLASS "unterminated character class"
3308#define DUK_STR_INVALID_RANGE "invalid range"
3309
3310/* Limits */
3311#define DUK_STR_VALSTACK_LIMIT "valstack limit"
3312#define DUK_STR_CALLSTACK_LIMIT "callstack limit"
3313#define DUK_STR_PROTOTYPE_CHAIN_LIMIT "prototype chain limit"
3314#define DUK_STR_BOUND_CHAIN_LIMIT "function call bound chain limit"
3315#define DUK_STR_NATIVE_STACK_LIMIT "C stack depth limit"
3316#define DUK_STR_COMPILER_RECURSION_LIMIT "compiler recursion limit"
3317#define DUK_STR_BYTECODE_LIMIT "bytecode limit"
3318#define DUK_STR_REG_LIMIT "register limit"
3319#define DUK_STR_TEMP_LIMIT "temp limit"
3320#define DUK_STR_CONST_LIMIT "const limit"
3321#define DUK_STR_FUNC_LIMIT "function limit"
3322#define DUK_STR_REGEXP_COMPILER_RECURSION_LIMIT "regexp compiler recursion limit"
3323#define DUK_STR_REGEXP_EXECUTOR_RECURSION_LIMIT "regexp executor recursion limit"
3324#define DUK_STR_REGEXP_EXECUTOR_STEP_LIMIT "regexp step limit"
3325
3326#endif /* DUK_ERRMSG_H_INCLUDED */
3327/* #include duk_js_bytecode.h */
3328/*
3329 * ECMAScript bytecode
3330 */
3331
3332#if !defined(DUK_JS_BYTECODE_H_INCLUDED)
3333#define DUK_JS_BYTECODE_H_INCLUDED
3334
3335/*
3336 * Bytecode instruction layout
3337 * ===========================
3338 *
3339 * Instructions are unsigned 32-bit integers divided as follows:
3340 *
3341 * !3!3!2!2!2!2!2!2!2!2!2!2!1!1!1!1!1!1!1!1!1!1! ! ! ! ! ! ! ! ! ! !
3342 * !1!0!9!8!7!6!5!4!3!2!1!0!9!8!7!6!5!4!3!2!1!0!9!8!7!6!5!4!3!2!1!0!
3343 * +-----------------------------------------------+---------------+
3344 * ! C ! B ! A ! OP !
3345 * +-----------------------------------------------+---------------+
3346 *
3347 * OP (8 bits): opcode (DUK_OP_*), access should be fastest
3348 * consecutive opcodes allocated when opcode needs flags
3349 * A (8 bits): typically a target register number
3350 * B (8 bits): typically first source register/constant number
3351 * C (8 bits): typically second source register/constant number
3352 *
3353 * Some instructions combine BC or ABC together for larger parameter values.
3354 * Signed integers (e.g. jump offsets) are encoded as unsigned, with an
3355 * opcode specific bias.
3356 *
3357 * Some opcodes have flags which are handled by allocating consecutive
3358 * opcodes to make space for 1-N flags. Flags can also be e.g. in the 'A'
3359 * field when there's room for the specific opcode.
3360 *
3361 * For example, if three flags were needed, they could be allocated from
3362 * the opcode field as follows:
3363 *
3364 * !3!3!2!2!2!2!2!2!2!2!2!2!1!1!1!1!1!1!1!1!1!1! ! ! ! ! ! ! ! ! ! !
3365 * !1!0!9!8!7!6!5!4!3!2!1!0!9!8!7!6!5!4!3!2!1!0!9!8!7!6!5!4!3!2!1!0!
3366 * +-----------------------------------------------+---------------+
3367 * ! C ! B ! A ! OP !Z!Y!X!
3368 * +-----------------------------------------------+---------------+
3369 *
3370 * Some opcodes accept a reg/const argument which is handled by allocating
3371 * flags in the OP field, see DUK_BC_ISREG() and DUK_BC_ISCONST(). The
3372 * following convention is shared by most opcodes, so that the compiler
3373 * can handle reg/const flagging without opcode specific code paths:
3374 *
3375 * !3!3!2!2!2!2!2!2!2!2!2!2!1!1!1!1!1!1!1!1!1!1! ! ! ! ! ! ! ! ! ! !
3376 * !1!0!9!8!7!6!5!4!3!2!1!0!9!8!7!6!5!4!3!2!1!0!9!8!7!6!5!4!3!2!1!0!
3377 * +-----------------------------------------------+---------------+
3378 * ! C ! B ! A ! OP !Y!X!
3379 * +-----------------------------------------------+---------------+
3380 *
3381 * X 1=B is const, 0=B is reg
3382 * Y 1=C is const, 0=C is reg
3383 *
3384 * In effect OP, OP + 1, OP + 2, and OP + 3 are allocated from the
3385 * 8-bit opcode space for a single logical opcode. The base opcode
3386 * number should be divisible by 4. If the opcode is called 'FOO'
3387 * the following opcode constants would be defined:
3388 *
3389 * DUK_OP_FOO 100 // base opcode number
3390 * DUK_OP_FOO_RR 100 // FOO, B=reg, C=reg
3391 * DUK_OP_FOO_CR 101 // FOO, B=const, C=reg
3392 * DUK_OP_FOO_RC 102 // FOO, B=reg, C=const
3393 * DUK_OP_FOO_CC 103 // FOO, B=const, C=const
3394 *
3395 * If only B or C is a reg/const, the unused opcode combinations can be
3396 * used for other opcodes (which take no reg/const argument). However,
3397 * such opcode values are initially reserved, at least while opcode space
3398 * is available. For example, if 'BAR' uses B for a register field and
3399 * C is a reg/const:
3400 *
3401 * DUK_OP_BAR 116 // base opcode number
3402 * DUK_OP_BAR_RR 116 // BAR, B=reg, C=reg
3403 * DUK_OP_BAR_CR_UNUSED 117 // unused, could be repurposed
3404 * DUK_OP_BAR_RC 118 // BAR, B=reg, C=const
3405 * DUK_OP_BAR_CC_UNUSED 119 // unused, could be repurposed
3406 *
3407 * Macro naming is a bit misleading, e.g. "ABC" in macro name but the
3408 * field layout is concretely "CBA" in the register.
3409 */
3410
3411typedef duk_uint32_t duk_instr_t;
3412
3413#define DUK_BC_SHIFT_OP 0
3414#define DUK_BC_SHIFT_A 8
3415#define DUK_BC_SHIFT_B 16
3416#define DUK_BC_SHIFT_C 24
3417#define DUK_BC_SHIFT_BC DUK_BC_SHIFT_B
3418#define DUK_BC_SHIFT_ABC DUK_BC_SHIFT_A
3419
3420#define DUK_BC_UNSHIFTED_MASK_OP 0xffUL
3421#define DUK_BC_UNSHIFTED_MASK_A 0xffUL
3422#define DUK_BC_UNSHIFTED_MASK_B 0xffUL
3423#define DUK_BC_UNSHIFTED_MASK_C 0xffUL
3424#define DUK_BC_UNSHIFTED_MASK_BC 0xffffUL
3425#define DUK_BC_UNSHIFTED_MASK_ABC 0xffffffUL
3426
3427#define DUK_BC_SHIFTED_MASK_OP (DUK_BC_UNSHIFTED_MASK_OP << DUK_BC_SHIFT_OP)
3428#define DUK_BC_SHIFTED_MASK_A (DUK_BC_UNSHIFTED_MASK_A << DUK_BC_SHIFT_A)
3429#define DUK_BC_SHIFTED_MASK_B (DUK_BC_UNSHIFTED_MASK_B << DUK_BC_SHIFT_B)
3430#define DUK_BC_SHIFTED_MASK_C (DUK_BC_UNSHIFTED_MASK_C << DUK_BC_SHIFT_C)
3431#define DUK_BC_SHIFTED_MASK_BC (DUK_BC_UNSHIFTED_MASK_BC << DUK_BC_SHIFT_BC)
3432#define DUK_BC_SHIFTED_MASK_ABC (DUK_BC_UNSHIFTED_MASK_ABC << DUK_BC_SHIFT_ABC)
3433
3434#define DUK_DEC_OP(x) ((x) &0xffUL)
3435#define DUK_DEC_A(x) (((x) >> 8) & 0xffUL)
3436#define DUK_DEC_B(x) (((x) >> 16) & 0xffUL)
3437#define DUK_DEC_C(x) (((x) >> 24) & 0xffUL)
3438#define DUK_DEC_BC(x) (((x) >> 16) & 0xffffUL)
3439#define DUK_DEC_ABC(x) (((x) >> 8) & 0xffffffUL)
3440
3441#define DUK_ENC_OP(op) ((duk_instr_t) (op))
3442#define DUK_ENC_OP_ABC(op, abc) ((duk_instr_t) ((((duk_instr_t) (abc)) << 8) | ((duk_instr_t) (op))))
3443#define DUK_ENC_OP_A_BC(op, a, bc) \
3444 ((duk_instr_t) ((((duk_instr_t) (bc)) << 16) | (((duk_instr_t) (a)) << 8) | ((duk_instr_t) (op))))
3445#define DUK_ENC_OP_A_B_C(op, a, b, c) \
3446 ((duk_instr_t) ((((duk_instr_t) (c)) << 24) | (((duk_instr_t) (b)) << 16) | (((duk_instr_t) (a)) << 8) | \
3447 ((duk_instr_t) (op))))
3448#define DUK_ENC_OP_A_B(op, a, b) DUK_ENC_OP_A_B_C((op), (a), (b), 0)
3449#define DUK_ENC_OP_A(op, a) DUK_ENC_OP_A_B_C((op), (a), 0, 0)
3450#define DUK_ENC_OP_BC(op, bc) DUK_ENC_OP_A_BC((op), 0, (bc))
3451
3452/* Get opcode base value with B/C reg/const flags cleared. */
3453#define DUK_BC_NOREGCONST_OP(op) ((op) &0xfc)
3454
3455/* Constants should be signed so that signed arithmetic involving them
3456 * won't cause values to be coerced accidentally to unsigned.
3457 */
3458#define DUK_BC_OP_MIN 0
3459#define DUK_BC_OP_MAX 0xffL
3460#define DUK_BC_A_MIN 0
3461#define DUK_BC_A_MAX 0xffL
3462#define DUK_BC_B_MIN 0
3463#define DUK_BC_B_MAX 0xffL
3464#define DUK_BC_C_MIN 0
3465#define DUK_BC_C_MAX 0xffL
3466#define DUK_BC_BC_MIN 0
3467#define DUK_BC_BC_MAX 0xffffL
3468#define DUK_BC_ABC_MIN 0
3469#define DUK_BC_ABC_MAX 0xffffffL
3470
3471/* Masks for B/C reg/const indicator in opcode field. */
3472#define DUK_BC_REGCONST_B (0x01UL)
3473#define DUK_BC_REGCONST_C (0x02UL)
3474
3475/* Misc. masks for opcode field. */
3476#define DUK_BC_INCDECP_FLAG_DEC (0x04UL)
3477#define DUK_BC_INCDECP_FLAG_POST (0x08UL)
3478
3479/* Opcodes. */
3480#define DUK_OP_LDREG 0
3481#define DUK_OP_STREG 1
3482#define DUK_OP_JUMP 2
3483#define DUK_OP_LDCONST 3
3484#define DUK_OP_LDINT 4
3485#define DUK_OP_LDINTX 5
3486#define DUK_OP_LDTHIS 6
3487#define DUK_OP_LDUNDEF 7
3488#define DUK_OP_LDNULL 8
3489#define DUK_OP_LDTRUE 9
3490#define DUK_OP_LDFALSE 10
3491#define DUK_OP_GETVAR 11
3492#define DUK_OP_BNOT 12
3493#define DUK_OP_LNOT 13
3494#define DUK_OP_UNM 14
3495#define DUK_OP_UNP 15
3496#define DUK_OP_EQ 16
3497#define DUK_OP_EQ_RR 16
3498#define DUK_OP_EQ_CR 17
3499#define DUK_OP_EQ_RC 18
3500#define DUK_OP_EQ_CC 19
3501#define DUK_OP_NEQ 20
3502#define DUK_OP_NEQ_RR 20
3503#define DUK_OP_NEQ_CR 21
3504#define DUK_OP_NEQ_RC 22
3505#define DUK_OP_NEQ_CC 23
3506#define DUK_OP_SEQ 24
3507#define DUK_OP_SEQ_RR 24
3508#define DUK_OP_SEQ_CR 25
3509#define DUK_OP_SEQ_RC 26
3510#define DUK_OP_SEQ_CC 27
3511#define DUK_OP_SNEQ 28
3512#define DUK_OP_SNEQ_RR 28
3513#define DUK_OP_SNEQ_CR 29
3514#define DUK_OP_SNEQ_RC 30
3515#define DUK_OP_SNEQ_CC 31
3516#define DUK_OP_GT 32
3517#define DUK_OP_GT_RR 32
3518#define DUK_OP_GT_CR 33
3519#define DUK_OP_GT_RC 34
3520#define DUK_OP_GT_CC 35
3521#define DUK_OP_GE 36
3522#define DUK_OP_GE_RR 36
3523#define DUK_OP_GE_CR 37
3524#define DUK_OP_GE_RC 38
3525#define DUK_OP_GE_CC 39
3526#define DUK_OP_LT 40
3527#define DUK_OP_LT_RR 40
3528#define DUK_OP_LT_CR 41
3529#define DUK_OP_LT_RC 42
3530#define DUK_OP_LT_CC 43
3531#define DUK_OP_LE 44
3532#define DUK_OP_LE_RR 44
3533#define DUK_OP_LE_CR 45
3534#define DUK_OP_LE_RC 46
3535#define DUK_OP_LE_CC 47
3536#define DUK_OP_IFTRUE 48
3537#define DUK_OP_IFTRUE_R 48
3538#define DUK_OP_IFTRUE_C 49
3539#define DUK_OP_IFFALSE 50
3540#define DUK_OP_IFFALSE_R 50
3541#define DUK_OP_IFFALSE_C 51
3542#define DUK_OP_ADD 52
3543#define DUK_OP_ADD_RR 52
3544#define DUK_OP_ADD_CR 53
3545#define DUK_OP_ADD_RC 54
3546#define DUK_OP_ADD_CC 55
3547#define DUK_OP_SUB 56
3548#define DUK_OP_SUB_RR 56
3549#define DUK_OP_SUB_CR 57
3550#define DUK_OP_SUB_RC 58
3551#define DUK_OP_SUB_CC 59
3552#define DUK_OP_MUL 60
3553#define DUK_OP_MUL_RR 60
3554#define DUK_OP_MUL_CR 61
3555#define DUK_OP_MUL_RC 62
3556#define DUK_OP_MUL_CC 63
3557#define DUK_OP_DIV 64
3558#define DUK_OP_DIV_RR 64
3559#define DUK_OP_DIV_CR 65
3560#define DUK_OP_DIV_RC 66
3561#define DUK_OP_DIV_CC 67
3562#define DUK_OP_MOD 68
3563#define DUK_OP_MOD_RR 68
3564#define DUK_OP_MOD_CR 69
3565#define DUK_OP_MOD_RC 70
3566#define DUK_OP_MOD_CC 71
3567#define DUK_OP_EXP 72
3568#define DUK_OP_EXP_RR 72
3569#define DUK_OP_EXP_CR 73
3570#define DUK_OP_EXP_RC 74
3571#define DUK_OP_EXP_CC 75
3572#define DUK_OP_BAND 76
3573#define DUK_OP_BAND_RR 76
3574#define DUK_OP_BAND_CR 77
3575#define DUK_OP_BAND_RC 78
3576#define DUK_OP_BAND_CC 79
3577#define DUK_OP_BOR 80
3578#define DUK_OP_BOR_RR 80
3579#define DUK_OP_BOR_CR 81
3580#define DUK_OP_BOR_RC 82
3581#define DUK_OP_BOR_CC 83
3582#define DUK_OP_BXOR 84
3583#define DUK_OP_BXOR_RR 84
3584#define DUK_OP_BXOR_CR 85
3585#define DUK_OP_BXOR_RC 86
3586#define DUK_OP_BXOR_CC 87
3587#define DUK_OP_BASL 88
3588#define DUK_OP_BASL_RR 88
3589#define DUK_OP_BASL_CR 89
3590#define DUK_OP_BASL_RC 90
3591#define DUK_OP_BASL_CC 91
3592#define DUK_OP_BLSR 92
3593#define DUK_OP_BLSR_RR 92
3594#define DUK_OP_BLSR_CR 93
3595#define DUK_OP_BLSR_RC 94
3596#define DUK_OP_BLSR_CC 95
3597#define DUK_OP_BASR 96
3598#define DUK_OP_BASR_RR 96
3599#define DUK_OP_BASR_CR 97
3600#define DUK_OP_BASR_RC 98
3601#define DUK_OP_BASR_CC 99
3602#define DUK_OP_INSTOF 100
3603#define DUK_OP_INSTOF_RR 100
3604#define DUK_OP_INSTOF_CR 101
3605#define DUK_OP_INSTOF_RC 102
3606#define DUK_OP_INSTOF_CC 103
3607#define DUK_OP_IN 104
3608#define DUK_OP_IN_RR 104
3609#define DUK_OP_IN_CR 105
3610#define DUK_OP_IN_RC 106
3611#define DUK_OP_IN_CC 107
3612#define DUK_OP_GETPROP 108
3613#define DUK_OP_GETPROP_RR 108
3614#define DUK_OP_GETPROP_CR 109
3615#define DUK_OP_GETPROP_RC 110
3616#define DUK_OP_GETPROP_CC 111
3617#define DUK_OP_PUTPROP 112
3618#define DUK_OP_PUTPROP_RR 112
3619#define DUK_OP_PUTPROP_CR 113
3620#define DUK_OP_PUTPROP_RC 114
3621#define DUK_OP_PUTPROP_CC 115
3622#define DUK_OP_DELPROP 116
3623#define DUK_OP_DELPROP_RR 116
3624#define DUK_OP_DELPROP_CR_UNUSED 117 /* unused now */
3625#define DUK_OP_DELPROP_RC 118
3626#define DUK_OP_DELPROP_CC_UNUSED 119 /* unused now */
3627#define DUK_OP_PREINCR 120 /* pre/post opcode values have constraints, */
3628#define DUK_OP_PREDECR 121 /* see duk_js_executor.c and duk_js_compiler.c. */
3629#define DUK_OP_POSTINCR 122
3630#define DUK_OP_POSTDECR 123
3631#define DUK_OP_PREINCV 124
3632#define DUK_OP_PREDECV 125
3633#define DUK_OP_POSTINCV 126
3634#define DUK_OP_POSTDECV 127
3635#define DUK_OP_PREINCP 128 /* pre/post inc/dec prop opcodes have constraints */
3636#define DUK_OP_PREINCP_RR 128
3637#define DUK_OP_PREINCP_CR 129
3638#define DUK_OP_PREINCP_RC 130
3639#define DUK_OP_PREINCP_CC 131
3640#define DUK_OP_PREDECP 132
3641#define DUK_OP_PREDECP_RR 132
3642#define DUK_OP_PREDECP_CR 133
3643#define DUK_OP_PREDECP_RC 134
3644#define DUK_OP_PREDECP_CC 135
3645#define DUK_OP_POSTINCP 136
3646#define DUK_OP_POSTINCP_RR 136
3647#define DUK_OP_POSTINCP_CR 137
3648#define DUK_OP_POSTINCP_RC 138
3649#define DUK_OP_POSTINCP_CC 139
3650#define DUK_OP_POSTDECP 140
3651#define DUK_OP_POSTDECP_RR 140
3652#define DUK_OP_POSTDECP_CR 141
3653#define DUK_OP_POSTDECP_RC 142
3654#define DUK_OP_POSTDECP_CC 143
3655#define DUK_OP_DECLVAR 144
3656#define DUK_OP_DECLVAR_RR 144
3657#define DUK_OP_DECLVAR_CR 145
3658#define DUK_OP_DECLVAR_RC 146
3659#define DUK_OP_DECLVAR_CC 147
3660#define DUK_OP_REGEXP 148
3661#define DUK_OP_REGEXP_RR 148
3662#define DUK_OP_REGEXP_CR 149
3663#define DUK_OP_REGEXP_RC 150
3664#define DUK_OP_REGEXP_CC 151
3665#define DUK_OP_CLOSURE 152
3666#define DUK_OP_TYPEOF 153
3667#define DUK_OP_TYPEOFID 154
3668#define DUK_OP_PUTVAR 155
3669#define DUK_OP_DELVAR 156
3670#define DUK_OP_RETREG 157
3671#define DUK_OP_RETUNDEF 158
3672#define DUK_OP_RETCONST 159
3673#define DUK_OP_RETCONSTN 160 /* return const without incref (e.g. number) */
3674#define DUK_OP_LABEL 161
3675#define DUK_OP_ENDLABEL 162
3676#define DUK_OP_BREAK 163
3677#define DUK_OP_CONTINUE 164
3678#define DUK_OP_TRYCATCH 165
3679#define DUK_OP_ENDTRY 166
3680#define DUK_OP_ENDCATCH 167
3681#define DUK_OP_ENDFIN 168
3682#define DUK_OP_THROW 169
3683#define DUK_OP_INVLHS 170
3684#define DUK_OP_CSREG 171
3685#define DUK_OP_CSVAR 172
3686#define DUK_OP_CSVAR_RR 172
3687#define DUK_OP_CSVAR_CR 173
3688#define DUK_OP_CSVAR_RC 174
3689#define DUK_OP_CSVAR_CC 175
3690#define DUK_OP_CALL0 176 /* DUK_OP_CALL0 & 0x0F must be zero. */
3691#define DUK_OP_CALL1 177
3692#define DUK_OP_CALL2 178
3693#define DUK_OP_CALL3 179
3694#define DUK_OP_CALL4 180
3695#define DUK_OP_CALL5 181
3696#define DUK_OP_CALL6 182
3697#define DUK_OP_CALL7 183
3698#define DUK_OP_CALL8 184
3699#define DUK_OP_CALL9 185
3700#define DUK_OP_CALL10 186
3701#define DUK_OP_CALL11 187
3702#define DUK_OP_CALL12 188
3703#define DUK_OP_CALL13 189
3704#define DUK_OP_CALL14 190
3705#define DUK_OP_CALL15 191
3706#define DUK_OP_NEWOBJ 192
3707#define DUK_OP_NEWARR 193
3708#define DUK_OP_MPUTOBJ 194
3709#define DUK_OP_MPUTOBJI 195
3710#define DUK_OP_INITSET 196
3711#define DUK_OP_INITGET 197
3712#define DUK_OP_MPUTARR 198
3713#define DUK_OP_MPUTARRI 199
3714#define DUK_OP_SETALEN 200
3715#define DUK_OP_INITENUM 201
3716#define DUK_OP_NEXTENUM 202
3717#define DUK_OP_NEWTARGET 203
3718#define DUK_OP_DEBUGGER 204
3719#define DUK_OP_NOP 205
3720#define DUK_OP_INVALID 206
3721#define DUK_OP_UNUSED207 207
3722#define DUK_OP_GETPROPC 208
3723#define DUK_OP_GETPROPC_RR 208
3724#define DUK_OP_GETPROPC_CR 209
3725#define DUK_OP_GETPROPC_RC 210
3726#define DUK_OP_GETPROPC_CC 211
3727#define DUK_OP_UNUSED212 212
3728#define DUK_OP_UNUSED213 213
3729#define DUK_OP_UNUSED214 214
3730#define DUK_OP_UNUSED215 215
3731#define DUK_OP_UNUSED216 216
3732#define DUK_OP_UNUSED217 217
3733#define DUK_OP_UNUSED218 218
3734#define DUK_OP_UNUSED219 219
3735#define DUK_OP_UNUSED220 220
3736#define DUK_OP_UNUSED221 221
3737#define DUK_OP_UNUSED222 222
3738#define DUK_OP_UNUSED223 223
3739#define DUK_OP_UNUSED224 224
3740#define DUK_OP_UNUSED225 225
3741#define DUK_OP_UNUSED226 226
3742#define DUK_OP_UNUSED227 227
3743#define DUK_OP_UNUSED228 228
3744#define DUK_OP_UNUSED229 229
3745#define DUK_OP_UNUSED230 230
3746#define DUK_OP_UNUSED231 231
3747#define DUK_OP_UNUSED232 232
3748#define DUK_OP_UNUSED233 233
3749#define DUK_OP_UNUSED234 234
3750#define DUK_OP_UNUSED235 235
3751#define DUK_OP_UNUSED236 236
3752#define DUK_OP_UNUSED237 237
3753#define DUK_OP_UNUSED238 238
3754#define DUK_OP_UNUSED239 239
3755#define DUK_OP_UNUSED240 240
3756#define DUK_OP_UNUSED241 241
3757#define DUK_OP_UNUSED242 242
3758#define DUK_OP_UNUSED243 243
3759#define DUK_OP_UNUSED244 244
3760#define DUK_OP_UNUSED245 245
3761#define DUK_OP_UNUSED246 246
3762#define DUK_OP_UNUSED247 247
3763#define DUK_OP_UNUSED248 248
3764#define DUK_OP_UNUSED249 249
3765#define DUK_OP_UNUSED250 250
3766#define DUK_OP_UNUSED251 251
3767#define DUK_OP_UNUSED252 252
3768#define DUK_OP_UNUSED253 253
3769#define DUK_OP_UNUSED254 254
3770#define DUK_OP_UNUSED255 255
3771#define DUK_OP_NONE 256 /* dummy value used as marker (doesn't fit in 8-bit field) */
3772
3773/* XXX: Allocate flags from opcode field? Would take 16 opcode slots
3774 * but avoids shuffling in more cases. Maybe not worth it.
3775 */
3776/* DUK_OP_TRYCATCH flags in A. */
3777#define DUK_BC_TRYCATCH_FLAG_HAVE_CATCH (1U << 0)
3778#define DUK_BC_TRYCATCH_FLAG_HAVE_FINALLY (1U << 1)
3779#define DUK_BC_TRYCATCH_FLAG_CATCH_BINDING (1U << 2)
3780#define DUK_BC_TRYCATCH_FLAG_WITH_BINDING (1U << 3)
3781
3782/* DUK_OP_DECLVAR flags in A; bottom bits are reserved for propdesc flags
3783 * (DUK_PROPDESC_FLAG_XXX).
3784 */
3785#define DUK_BC_DECLVAR_FLAG_FUNC_DECL (1U << 4) /* function declaration */
3786
3787/* DUK_OP_CALLn flags, part of opcode field. Three lowest bits must match
3788 * DUK_CALL_FLAG_xxx directly.
3789 */
3790#define DUK_BC_CALL_FLAG_TAILCALL (1U << 0)
3791#define DUK_BC_CALL_FLAG_CONSTRUCT (1U << 1)
3792#define DUK_BC_CALL_FLAG_CALLED_AS_EVAL (1U << 2)
3793#define DUK_BC_CALL_FLAG_INDIRECT (1U << 3)
3794
3795/* Misc constants and helper macros. */
3796#define DUK_BC_LDINT_BIAS (1L << 15)
3797#define DUK_BC_LDINTX_SHIFT 16
3798#define DUK_BC_JUMP_BIAS (1L << 23)
3799
3800#endif /* DUK_JS_BYTECODE_H_INCLUDED */
3801/* #include duk_lexer.h */
3802/*
3803 * Lexer defines.
3804 */
3805
3806#if !defined(DUK_LEXER_H_INCLUDED)
3807#define DUK_LEXER_H_INCLUDED
3808
3809typedef void (*duk_re_range_callback)(void *user, duk_codepoint_t r1, duk_codepoint_t r2, duk_bool_t direct);
3810
3811/*
3812 * A token is interpreted as any possible production of InputElementDiv
3813 * and InputElementRegExp, see E5 Section 7 in its entirety. Note that
3814 * the E5 "Token" production does not cover all actual tokens of the
3815 * language (which is explicitly stated in the specification, Section 7.5).
3816 * Null and boolean literals are defined as part of both ReservedWord
3817 * (E5 Section 7.6.1) and Literal (E5 Section 7.8) productions. Here,
3818 * null and boolean values have literal tokens, and are not reserved
3819 * words.
3820 *
3821 * Decimal literal negative/positive sign is -not- part of DUK_TOK_NUMBER.
3822 * The number tokens always have a non-negative value. The unary minus
3823 * operator in "-1.0" is optimized during compilation to yield a single
3824 * negative constant.
3825 *
3826 * Token numbering is free except that reserved words are required to be
3827 * in a continuous range and in a particular order. See genstrings.py.
3828 */
3829
3830#define DUK_LEXER_INITCTX(ctx) duk_lexer_initctx((ctx))
3831
3832#define DUK_LEXER_SETPOINT(ctx, pt) duk_lexer_setpoint((ctx), (pt))
3833
3834#define DUK_LEXER_GETPOINT(ctx, pt) duk_lexer_getpoint((ctx), (pt))
3835
3836/* Currently 6 characters of lookup are actually needed (duk_lexer.c). */
3837#define DUK_LEXER_WINDOW_SIZE 6
3838#if defined(DUK_USE_LEXER_SLIDING_WINDOW)
3839#define DUK_LEXER_BUFFER_SIZE 64
3840#endif
3841
3842#define DUK_TOK_MINVAL 0
3843
3844/* returned after EOF (infinite amount) */
3845#define DUK_TOK_EOF 0
3846
3847/* identifier names (E5 Section 7.6) */
3848#define DUK_TOK_IDENTIFIER 1
3849
3850/* reserved words: keywords */
3851#define DUK_TOK_START_RESERVED 2
3852#define DUK_TOK_BREAK 2
3853#define DUK_TOK_CASE 3
3854#define DUK_TOK_CATCH 4
3855#define DUK_TOK_CONTINUE 5
3856#define DUK_TOK_DEBUGGER 6
3857#define DUK_TOK_DEFAULT 7
3858#define DUK_TOK_DELETE 8
3859#define DUK_TOK_DO 9
3860#define DUK_TOK_ELSE 10
3861#define DUK_TOK_FINALLY 11
3862#define DUK_TOK_FOR 12
3863#define DUK_TOK_FUNCTION 13
3864#define DUK_TOK_IF 14
3865#define DUK_TOK_IN 15
3866#define DUK_TOK_INSTANCEOF 16
3867#define DUK_TOK_NEW 17
3868#define DUK_TOK_RETURN 18
3869#define DUK_TOK_SWITCH 19
3870#define DUK_TOK_THIS 20
3871#define DUK_TOK_THROW 21
3872#define DUK_TOK_TRY 22
3873#define DUK_TOK_TYPEOF 23
3874#define DUK_TOK_VAR 24
3875#define DUK_TOK_CONST 25
3876#define DUK_TOK_VOID 26
3877#define DUK_TOK_WHILE 27
3878#define DUK_TOK_WITH 28
3879
3880/* reserved words: future reserved words */
3881#define DUK_TOK_CLASS 29
3882#define DUK_TOK_ENUM 30
3883#define DUK_TOK_EXPORT 31
3884#define DUK_TOK_EXTENDS 32
3885#define DUK_TOK_IMPORT 33
3886#define DUK_TOK_SUPER 34
3887
3888/* "null", "true", and "false" are always reserved words.
3889 * Note that "get" and "set" are not!
3890 */
3891#define DUK_TOK_NULL 35
3892#define DUK_TOK_TRUE 36
3893#define DUK_TOK_FALSE 37
3894
3895/* reserved words: additional future reserved words in strict mode */
3896#define DUK_TOK_START_STRICT_RESERVED 38 /* inclusive */
3897#define DUK_TOK_IMPLEMENTS 38
3898#define DUK_TOK_INTERFACE 39
3899#define DUK_TOK_LET 40
3900#define DUK_TOK_PACKAGE 41
3901#define DUK_TOK_PRIVATE 42
3902#define DUK_TOK_PROTECTED 43
3903#define DUK_TOK_PUBLIC 44
3904#define DUK_TOK_STATIC 45
3905#define DUK_TOK_YIELD 46
3906
3907#define DUK_TOK_END_RESERVED 47 /* exclusive */
3908
3909/* "get" and "set" are tokens but NOT ReservedWords. They are currently
3910 * parsed and identifiers and these defines are actually now unused.
3911 */
3912#define DUK_TOK_GET 47
3913#define DUK_TOK_SET 48
3914
3915/* punctuators (unlike the spec, also includes "/" and "/=") */
3916#define DUK_TOK_LCURLY 49
3917#define DUK_TOK_RCURLY 50
3918#define DUK_TOK_LBRACKET 51
3919#define DUK_TOK_RBRACKET 52
3920#define DUK_TOK_LPAREN 53
3921#define DUK_TOK_RPAREN 54
3922#define DUK_TOK_PERIOD 55
3923#define DUK_TOK_SEMICOLON 56
3924#define DUK_TOK_COMMA 57
3925#define DUK_TOK_LT 58
3926#define DUK_TOK_GT 59
3927#define DUK_TOK_LE 60
3928#define DUK_TOK_GE 61
3929#define DUK_TOK_EQ 62
3930#define DUK_TOK_NEQ 63
3931#define DUK_TOK_SEQ 64
3932#define DUK_TOK_SNEQ 65
3933#define DUK_TOK_ADD 66
3934#define DUK_TOK_SUB 67
3935#define DUK_TOK_MUL 68
3936#define DUK_TOK_DIV 69
3937#define DUK_TOK_MOD 70
3938#define DUK_TOK_EXP 71
3939#define DUK_TOK_INCREMENT 72
3940#define DUK_TOK_DECREMENT 73
3941#define DUK_TOK_ALSHIFT 74 /* named "arithmetic" because result is signed */
3942#define DUK_TOK_ARSHIFT 75
3943#define DUK_TOK_RSHIFT 76
3944#define DUK_TOK_BAND 77
3945#define DUK_TOK_BOR 78
3946#define DUK_TOK_BXOR 79
3947#define DUK_TOK_LNOT 80
3948#define DUK_TOK_BNOT 81
3949#define DUK_TOK_LAND 82
3950#define DUK_TOK_LOR 83
3951#define DUK_TOK_QUESTION 84
3952#define DUK_TOK_COLON 85
3953#define DUK_TOK_EQUALSIGN 86
3954#define DUK_TOK_ADD_EQ 87
3955#define DUK_TOK_SUB_EQ 88
3956#define DUK_TOK_MUL_EQ 89
3957#define DUK_TOK_DIV_EQ 90
3958#define DUK_TOK_MOD_EQ 91
3959#define DUK_TOK_EXP_EQ 92
3960#define DUK_TOK_ALSHIFT_EQ 93
3961#define DUK_TOK_ARSHIFT_EQ 94
3962#define DUK_TOK_RSHIFT_EQ 95
3963#define DUK_TOK_BAND_EQ 96
3964#define DUK_TOK_BOR_EQ 97
3965#define DUK_TOK_BXOR_EQ 98
3966
3967/* literals (E5 Section 7.8), except null, true, false, which are treated
3968 * like reserved words (above).
3969 */
3970#define DUK_TOK_NUMBER 99
3971#define DUK_TOK_STRING 100
3972#define DUK_TOK_REGEXP 101
3973
3974#define DUK_TOK_MAXVAL 101 /* inclusive */
3975
3976#define DUK_TOK_INVALID DUK_SMALL_UINT_MAX
3977
3978/* Convert heap string index to a token (reserved words) */
3979#define DUK_STRIDX_TO_TOK(x) ((x) -DUK_STRIDX_START_RESERVED + DUK_TOK_START_RESERVED)
3980
3981/* Sanity check */
3982#if (DUK_TOK_MAXVAL > 255)
3983#error DUK_TOK_MAXVAL too large, code assumes it fits into 8 bits
3984#endif
3985
3986/* Sanity checks for string and token defines */
3987#if (DUK_STRIDX_TO_TOK(DUK_STRIDX_BREAK) != DUK_TOK_BREAK)
3988#error mismatch in token defines
3989#endif
3990#if (DUK_STRIDX_TO_TOK(DUK_STRIDX_CASE) != DUK_TOK_CASE)
3991#error mismatch in token defines
3992#endif
3993#if (DUK_STRIDX_TO_TOK(DUK_STRIDX_CATCH) != DUK_TOK_CATCH)
3994#error mismatch in token defines
3995#endif
3996#if (DUK_STRIDX_TO_TOK(DUK_STRIDX_CONTINUE) != DUK_TOK_CONTINUE)
3997#error mismatch in token defines
3998#endif
3999#if (DUK_STRIDX_TO_TOK(DUK_STRIDX_DEBUGGER) != DUK_TOK_DEBUGGER)
4000#error mismatch in token defines
4001#endif
4002#if (DUK_STRIDX_TO_TOK(DUK_STRIDX_DEFAULT) != DUK_TOK_DEFAULT)
4003#error mismatch in token defines
4004#endif
4005#if (DUK_STRIDX_TO_TOK(DUK_STRIDX_DELETE) != DUK_TOK_DELETE)
4006#error mismatch in token defines
4007#endif
4008#if (DUK_STRIDX_TO_TOK(DUK_STRIDX_DO) != DUK_TOK_DO)
4009#error mismatch in token defines
4010#endif
4011#if (DUK_STRIDX_TO_TOK(DUK_STRIDX_ELSE) != DUK_TOK_ELSE)
4012#error mismatch in token defines
4013#endif
4014#if (DUK_STRIDX_TO_TOK(DUK_STRIDX_FINALLY) != DUK_TOK_FINALLY)
4015#error mismatch in token defines
4016#endif
4017#if (DUK_STRIDX_TO_TOK(DUK_STRIDX_FOR) != DUK_TOK_FOR)
4018#error mismatch in token defines
4019#endif
4020#if (DUK_STRIDX_TO_TOK(DUK_STRIDX_LC_FUNCTION) != DUK_TOK_FUNCTION)
4021#error mismatch in token defines
4022#endif
4023#if (DUK_STRIDX_TO_TOK(DUK_STRIDX_IF) != DUK_TOK_IF)
4024#error mismatch in token defines
4025#endif
4026#if (DUK_STRIDX_TO_TOK(DUK_STRIDX_IN) != DUK_TOK_IN)
4027#error mismatch in token defines
4028#endif
4029#if (DUK_STRIDX_TO_TOK(DUK_STRIDX_INSTANCEOF) != DUK_TOK_INSTANCEOF)
4030#error mismatch in token defines
4031#endif
4032#if (DUK_STRIDX_TO_TOK(DUK_STRIDX_NEW) != DUK_TOK_NEW)
4033#error mismatch in token defines
4034#endif
4035#if (DUK_STRIDX_TO_TOK(DUK_STRIDX_RETURN) != DUK_TOK_RETURN)
4036#error mismatch in token defines
4037#endif
4038#if (DUK_STRIDX_TO_TOK(DUK_STRIDX_SWITCH) != DUK_TOK_SWITCH)
4039#error mismatch in token defines
4040#endif
4041#if (DUK_STRIDX_TO_TOK(DUK_STRIDX_THIS) != DUK_TOK_THIS)
4042#error mismatch in token defines
4043#endif
4044#if (DUK_STRIDX_TO_TOK(DUK_STRIDX_THROW) != DUK_TOK_THROW)
4045#error mismatch in token defines
4046#endif
4047#if (DUK_STRIDX_TO_TOK(DUK_STRIDX_TRY) != DUK_TOK_TRY)
4048#error mismatch in token defines
4049#endif
4050#if (DUK_STRIDX_TO_TOK(DUK_STRIDX_TYPEOF) != DUK_TOK_TYPEOF)
4051#error mismatch in token defines
4052#endif
4053#if (DUK_STRIDX_TO_TOK(DUK_STRIDX_VAR) != DUK_TOK_VAR)
4054#error mismatch in token defines
4055#endif
4056#if (DUK_STRIDX_TO_TOK(DUK_STRIDX_VOID) != DUK_TOK_VOID)
4057#error mismatch in token defines
4058#endif
4059#if (DUK_STRIDX_TO_TOK(DUK_STRIDX_WHILE) != DUK_TOK_WHILE)
4060#error mismatch in token defines
4061#endif
4062#if (DUK_STRIDX_TO_TOK(DUK_STRIDX_WITH) != DUK_TOK_WITH)
4063#error mismatch in token defines
4064#endif
4065#if (DUK_STRIDX_TO_TOK(DUK_STRIDX_CLASS) != DUK_TOK_CLASS)
4066#error mismatch in token defines
4067#endif
4068#if (DUK_STRIDX_TO_TOK(DUK_STRIDX_CONST) != DUK_TOK_CONST)
4069#error mismatch in token defines
4070#endif
4071#if (DUK_STRIDX_TO_TOK(DUK_STRIDX_ENUM) != DUK_TOK_ENUM)
4072#error mismatch in token defines
4073#endif
4074#if (DUK_STRIDX_TO_TOK(DUK_STRIDX_EXPORT) != DUK_TOK_EXPORT)
4075#error mismatch in token defines
4076#endif
4077#if (DUK_STRIDX_TO_TOK(DUK_STRIDX_EXTENDS) != DUK_TOK_EXTENDS)
4078#error mismatch in token defines
4079#endif
4080#if (DUK_STRIDX_TO_TOK(DUK_STRIDX_IMPORT) != DUK_TOK_IMPORT)
4081#error mismatch in token defines
4082#endif
4083#if (DUK_STRIDX_TO_TOK(DUK_STRIDX_SUPER) != DUK_TOK_SUPER)
4084#error mismatch in token defines
4085#endif
4086#if (DUK_STRIDX_TO_TOK(DUK_STRIDX_LC_NULL) != DUK_TOK_NULL)
4087#error mismatch in token defines
4088#endif
4089#if (DUK_STRIDX_TO_TOK(DUK_STRIDX_TRUE) != DUK_TOK_TRUE)
4090#error mismatch in token defines
4091#endif
4092#if (DUK_STRIDX_TO_TOK(DUK_STRIDX_FALSE) != DUK_TOK_FALSE)
4093#error mismatch in token defines
4094#endif
4095#if (DUK_STRIDX_TO_TOK(DUK_STRIDX_IMPLEMENTS) != DUK_TOK_IMPLEMENTS)
4096#error mismatch in token defines
4097#endif
4098#if (DUK_STRIDX_TO_TOK(DUK_STRIDX_INTERFACE) != DUK_TOK_INTERFACE)
4099#error mismatch in token defines
4100#endif
4101#if (DUK_STRIDX_TO_TOK(DUK_STRIDX_LET) != DUK_TOK_LET)
4102#error mismatch in token defines
4103#endif
4104#if (DUK_STRIDX_TO_TOK(DUK_STRIDX_PACKAGE) != DUK_TOK_PACKAGE)
4105#error mismatch in token defines
4106#endif
4107#if (DUK_STRIDX_TO_TOK(DUK_STRIDX_PRIVATE) != DUK_TOK_PRIVATE)
4108#error mismatch in token defines
4109#endif
4110#if (DUK_STRIDX_TO_TOK(DUK_STRIDX_PROTECTED) != DUK_TOK_PROTECTED)
4111#error mismatch in token defines
4112#endif
4113#if (DUK_STRIDX_TO_TOK(DUK_STRIDX_PUBLIC) != DUK_TOK_PUBLIC)
4114#error mismatch in token defines
4115#endif
4116#if (DUK_STRIDX_TO_TOK(DUK_STRIDX_STATIC) != DUK_TOK_STATIC)
4117#error mismatch in token defines
4118#endif
4119#if (DUK_STRIDX_TO_TOK(DUK_STRIDX_YIELD) != DUK_TOK_YIELD)
4120#error mismatch in token defines
4121#endif
4122
4123/* Regexp tokens */
4124#define DUK_RETOK_EOF 0
4125#define DUK_RETOK_DISJUNCTION 1
4126#define DUK_RETOK_QUANTIFIER 2
4127#define DUK_RETOK_ASSERT_START 3
4128#define DUK_RETOK_ASSERT_END 4
4129#define DUK_RETOK_ASSERT_WORD_BOUNDARY 5
4130#define DUK_RETOK_ASSERT_NOT_WORD_BOUNDARY 6
4131#define DUK_RETOK_ASSERT_START_POS_LOOKAHEAD 7
4132#define DUK_RETOK_ASSERT_START_NEG_LOOKAHEAD 8
4133#define DUK_RETOK_ATOM_PERIOD 9
4134#define DUK_RETOK_ATOM_CHAR 10
4135#define DUK_RETOK_ATOM_DIGIT 11 /* assumptions in regexp compiler */
4136#define DUK_RETOK_ATOM_NOT_DIGIT 12 /* -""- */
4137#define DUK_RETOK_ATOM_WHITE 13 /* -""- */
4138#define DUK_RETOK_ATOM_NOT_WHITE 14 /* -""- */
4139#define DUK_RETOK_ATOM_WORD_CHAR 15 /* -""- */
4140#define DUK_RETOK_ATOM_NOT_WORD_CHAR 16 /* -""- */
4141#define DUK_RETOK_ATOM_BACKREFERENCE 17
4142#define DUK_RETOK_ATOM_START_CAPTURE_GROUP 18
4143#define DUK_RETOK_ATOM_START_NONCAPTURE_GROUP 19
4144#define DUK_RETOK_ATOM_START_CHARCLASS 20
4145#define DUK_RETOK_ATOM_START_CHARCLASS_INVERTED 21
4146#define DUK_RETOK_ATOM_END_GROUP 22
4147
4148/* Constants for duk_lexer_ctx.buf. */
4149#define DUK_LEXER_TEMP_BUF_LIMIT 256
4150
4151/* A token value. Can be memcpy()'d, but note that slot1/slot2 values are on the valstack.
4152 * Some fields (like num, str1, str2) are only valid for specific token types and may have
4153 * stale values otherwise.
4154 */
4156 duk_small_uint_t t; /* token type (with reserved word identification) */
4157 duk_small_uint_t t_nores; /* token type (with reserved words as DUK_TOK_IDENTIFER) */
4158 duk_double_t num; /* numeric value of token */
4159 duk_hstring *str1; /* string 1 of token (borrowed, stored to ctx->slot1_idx) */
4160 duk_hstring *str2; /* string 2 of token (borrowed, stored to ctx->slot2_idx) */
4161 duk_size_t start_offset; /* start byte offset of token in lexer input */
4162 duk_int_t start_line; /* start line of token (first char) */
4163 duk_int_t num_escapes; /* number of escapes and line continuations (for directive prologue) */
4164 duk_bool_t lineterm; /* token was preceded by a lineterm */
4165 duk_bool_t allow_auto_semi; /* token allows automatic semicolon insertion (eof or preceded by newline) */
4166};
4167
4168#define DUK_RE_QUANTIFIER_INFINITE ((duk_uint32_t) 0xffffffffUL)
4169
4170/* A regexp token value. */
4172 duk_small_uint_t t; /* token type */
4174 duk_uint32_t num; /* numeric value (character, count) */
4175 duk_uint32_t qmin;
4176 duk_uint32_t qmax;
4177};
4178
4179/* A structure for 'snapshotting' a point for rewinding */
4183};
4184
4185/* Lexer codepoint with additional info like offset/line number */
4190};
4191
4192/* Lexer context. Same context is used for ECMAScript and Regexp parsing. */
4194#if defined(DUK_USE_LEXER_SLIDING_WINDOW)
4195 duk_lexer_codepoint *window; /* unicode code points, window[0] is always next, points to 'buffer' */
4197#else
4198 duk_lexer_codepoint window[DUK_LEXER_WINDOW_SIZE]; /* unicode code points, window[0] is always next */
4199#endif
4200
4201 duk_hthread *thr; /* thread; minimizes argument passing */
4202
4203 const duk_uint8_t *input; /* input string (may be a user pointer) */
4204 duk_size_t input_length; /* input byte length */
4205 duk_size_t input_offset; /* input offset for window leading edge (not window[0]) */
4206 duk_int_t input_line; /* input linenumber at input_offset (not window[0]), init to 1 */
4207
4208 duk_idx_t slot1_idx; /* valstack slot for 1st token value */
4209 duk_idx_t slot2_idx; /* valstack slot for 2nd token value */
4210 duk_idx_t buf_idx; /* valstack slot for temp buffer */
4211 duk_hbuffer_dynamic *buf; /* temp accumulation buffer */
4212 duk_bufwriter_ctx bw; /* bufwriter for temp accumulation */
4213
4214 duk_int_t token_count; /* number of tokens parsed */
4215 duk_int_t token_limit; /* maximum token count before error (sanity backstop) */
4216
4217 duk_small_uint_t flags; /* lexer flags, use compiler flag defines for now */
4218};
4219
4220/*
4221 * Prototypes
4222 */
4223
4225
4228
4230void duk_lexer_parse_js_input_element(duk_lexer_ctx *lex_ctx, duk_token *out_token, duk_bool_t strict_mode, duk_bool_t regexp_mode);
4231#if defined(DUK_USE_REGEXP_SUPPORT)
4233DUK_INTERNAL_DECL void duk_lexer_parse_re_ranges(duk_lexer_ctx *lex_ctx, duk_re_range_callback gen_range, void *userdata);
4234#endif /* DUK_USE_REGEXP_SUPPORT */
4235
4236#endif /* DUK_LEXER_H_INCLUDED */
4237/* #include duk_js_compiler.h */
4238/*
4239 * ECMAScript compiler.
4240 */
4241
4242#if !defined(DUK_JS_COMPILER_H_INCLUDED)
4243#define DUK_JS_COMPILER_H_INCLUDED
4244
4245/* ECMAScript compiler limits */
4246#define DUK_COMPILER_TOKEN_LIMIT 100000000L /* 1e8: protects against deeply nested inner functions */
4247
4248/* maximum loopcount for peephole optimization */
4249#define DUK_COMPILER_PEEPHOLE_MAXITER 3
4250
4251/* maximum bytecode length in instructions */
4252#define DUK_COMPILER_MAX_BYTECODE_LENGTH (256L * 1024L * 1024L) /* 1 GB */
4253
4254/*
4255 * Compiler intermediate values
4256 *
4257 * Intermediate values describe either plain values (e.g. strings or
4258 * numbers) or binary operations which have not yet been coerced into
4259 * either a left-hand-side or right-hand-side role (e.g. object property).
4260 */
4261
4262#define DUK_IVAL_NONE 0 /* no value */
4263#define DUK_IVAL_PLAIN 1 /* register, constant, or value */
4264#define DUK_IVAL_ARITH 2 /* binary arithmetic; DUK_OP_ADD, DUK_OP_EQ, other binary ops */
4265#define DUK_IVAL_PROP 3 /* property access */
4266#define DUK_IVAL_VAR 4 /* variable access */
4267
4268#define DUK_ISPEC_NONE 0 /* no value */
4269#define DUK_ISPEC_VALUE 1 /* value resides in 'valstack_idx' */
4270#define DUK_ISPEC_REGCONST 2 /* value resides in a register or constant */
4271
4272/* Bit mask which indicates that a regconst is a constant instead of a register.
4273 * Chosen so that when a regconst is cast to duk_int32_t, all consts are
4274 * negative values.
4275 */
4276#define DUK_REGCONST_CONST_MARKER DUK_INT32_MIN /* = -0x80000000 */
4277
4278/* Type to represent a reg/const reference during compilation, with <0
4279 * indicating a constant. Some call sites also use -1 to indicate 'none'.
4280 */
4281typedef duk_int32_t duk_regconst_t;
4282
4283typedef struct {
4284 duk_small_uint_t t; /* DUK_ISPEC_XXX */
4286 duk_idx_t valstack_idx; /* always set; points to a reserved valstack slot */
4287} duk_ispec;
4288
4289typedef struct {
4290 /*
4291 * PLAIN: x1
4292 * ARITH: x1 <op> x2
4293 * PROP: x1.x2
4294 * VAR: x1 (name)
4295 */
4296
4297 /* XXX: can be optimized for smaller footprint esp. on 32-bit environments */
4298 duk_small_uint_t t; /* DUK_IVAL_XXX */
4299 duk_small_uint_t op; /* bytecode opcode for binary ops */
4302} duk_ivalue;
4303
4304/*
4305 * Bytecode instruction representation during compilation
4306 *
4307 * Contains the actual instruction and (optionally) debug info.
4308 */
4309
4312#if defined(DUK_USE_PC2LINE)
4313 duk_uint32_t line;
4314#endif
4315};
4316
4317/*
4318 * Compiler state
4319 */
4320
4321#define DUK_LABEL_FLAG_ALLOW_BREAK (1U << 0)
4322#define DUK_LABEL_FLAG_ALLOW_CONTINUE (1U << 1)
4323
4324#define DUK_DECL_TYPE_VAR 0
4325#define DUK_DECL_TYPE_FUNC 1
4326
4327/* XXX: optimize to 16 bytes */
4328typedef struct {
4330 duk_int_t label_id; /* numeric label_id (-1 reserved as marker) */
4331 duk_hstring *h_label; /* borrowed label name */
4332 duk_int_t catch_depth; /* catch depth at point of definition */
4333 duk_int_t pc_label; /* pc of label statement:
4334 * pc+1: break jump site
4335 * pc+2: continue jump site
4336 */
4337
4338 /* Fast jumps (which avoid longjmp) jump directly to the jump sites
4339 * which are always known even while the iteration/switch statement
4340 * is still being parsed. A final peephole pass "straightens out"
4341 * the jumps.
4342 */
4344
4345/* Compiling state of one function, eventually converted to duk_hcompfunc */
4347 /* These pointers are at the start of the struct so that they pack
4348 * nicely. Mixing pointers and integer values is bad on some
4349 * platforms (e.g. if int is 32 bits and pointers are 64 bits).
4350 */
4351
4352 duk_bufwriter_ctx bw_code; /* bufwriter for code */
4353
4354 duk_hstring *h_name; /* function name (borrowed reference), ends up in _name */
4355 /* h_code: held in bw_code */
4356 duk_hobject *h_consts; /* array */
4357 duk_hobject *h_funcs; /* array of function templates: [func1, offset1, line1, func2, offset2, line2]
4358 * offset/line points to closing brace to allow skipping on pass 2
4359 */
4360 duk_hobject *h_decls; /* array of declarations: [ name1, val1, name2, val2, ... ]
4361 * valN = (typeN) | (fnum << 8), where fnum is inner func number (0 for vars)
4362 * record function and variable declarations in pass 1
4363 */
4364 duk_hobject *h_labelnames; /* array of active label names */
4365 duk_hbuffer_dynamic *h_labelinfos; /* C array of duk_labelinfo */
4366 duk_hobject *h_argnames; /* array of formal argument names (-> _Formals) */
4367 duk_hobject *h_varmap; /* variable map for pass 2 (identifier -> register number or null (unmapped)) */
4368
4369 /* Value stack indices for tracking objects. */
4370 /* code_idx: not needed */
4378
4379 /* Temp reg handling. */
4380 duk_regconst_t temp_first; /* first register that is a temporary (below: variables) */
4381 duk_regconst_t temp_next; /* next temporary register to allocate */
4382 duk_regconst_t temp_max; /* highest value of temp_reg (temp_max - 1 is highest used reg) */
4383
4384 /* Shuffle registers if large number of regs/consts. */
4388
4389 /* Stats for current expression being parsed. */
4392 duk_int_t paren_level; /* parenthesis count, 0 = top level */
4393 duk_bool_t expr_lhs; /* expression is left-hand-side compatible */
4394 duk_bool_t allow_in; /* current paren level allows 'in' token */
4395
4396 /* Misc. */
4397 duk_int_t stmt_next; /* statement id allocation (running counter) */
4398 duk_int_t label_next; /* label id allocation (running counter) */
4399 duk_int_t catch_depth; /* catch stack depth */
4400 duk_int_t with_depth; /* with stack depth (affects identifier lookups) */
4401 duk_int_t fnum_next; /* inner function numbering */
4402 duk_int_t num_formals; /* number of formal arguments */
4404 reg_stmt_value; /* register for writing value of 'non-empty' statements (global or eval code), -1 is marker */
4405#if defined(DUK_USE_DEBUGGER_SUPPORT)
4406 duk_int_t min_line; /* XXX: typing (duk_hcompfunc has duk_uint32_t) */
4407 duk_int_t max_line;
4408#endif
4409
4410 /* Status booleans. */
4411 duk_uint8_t is_function; /* is an actual function (not global/eval code) */
4412 duk_uint8_t is_eval; /* is eval code */
4413 duk_uint8_t is_global; /* is global code */
4414 duk_uint8_t is_namebinding; /* needs a name binding */
4415 duk_uint8_t is_constructable; /* result is constructable */
4416 duk_uint8_t is_setget; /* is a setter/getter */
4417 duk_uint8_t is_strict; /* function is strict */
4418 duk_uint8_t is_notail; /* function must not be tail called */
4419 duk_uint8_t in_directive_prologue; /* parsing in "directive prologue", recognize directives */
4420 duk_uint8_t in_scanning; /* parsing in "scanning" phase (first pass) */
4421 duk_uint8_t may_direct_eval; /* function may call direct eval */
4422 duk_uint8_t id_access_arguments; /* function refers to 'arguments' identifier */
4423 duk_uint8_t id_access_slow; /* function makes one or more slow path accesses that won't match own static variables */
4424 duk_uint8_t id_access_slow_own; /* function makes one or more slow path accesses that may match own static variables */
4425 duk_uint8_t is_arguments_shadowed; /* argument/function declaration shadows 'arguments' */
4426 duk_uint8_t needs_shuffle; /* function needs shuffle registers */
4427 duk_uint8_t
4428 reject_regexp_in_adv; /* reject RegExp literal on next advance() call; needed for handling IdentifierName productions */
4429 duk_uint8_t allow_regexp_in_adv; /* allow RegExp literal on next advance() call */
4430};
4431
4434
4435 /* filename being compiled (ends up in functions' '_filename' property) */
4436 duk_hstring *h_filename; /* borrowed reference */
4437
4438 /* lexing (tokenization) state (contains two valstack slot indices) */
4440
4441 /* current and previous token for parsing */
4444 duk_idx_t tok11_idx; /* curr_token slot1 (matches 'lex' slot1_idx) */
4445 duk_idx_t tok12_idx; /* curr_token slot2 (matches 'lex' slot2_idx) */
4446 duk_idx_t tok21_idx; /* prev_token slot1 */
4447 duk_idx_t tok22_idx; /* prev_token slot2 */
4448
4449 /* recursion limit */
4452
4453 /* code emission temporary */
4455
4456 /* current function being compiled (embedded instead of pointer for more compact access) */
4458};
4459
4460/*
4461 * Prototypes
4462 */
4463
4465 const duk_uint8_t *src_buffer,
4466 duk_size_t src_length,
4467 duk_small_uint_t flags);
4468
4469#endif /* DUK_JS_COMPILER_H_INCLUDED */
4470/* #include duk_regexp.h */
4471/*
4472 * Regular expression structs, constants, and bytecode defines.
4473 */
4474
4475#if !defined(DUK_REGEXP_H_INCLUDED)
4476#define DUK_REGEXP_H_INCLUDED
4477
4478/* maximum bytecode copies for {n,m} quantifiers */
4479#define DUK_RE_MAX_ATOM_COPIES 1000
4480
4481/* regexp compilation limits */
4482#define DUK_RE_COMPILE_TOKEN_LIMIT 100000000L /* 1e8 */
4483
4484/* regexp execution limits */
4485#define DUK_RE_EXECUTE_STEPS_LIMIT 1000000000L /* 1e9 */
4486
4487/* regexp opcodes */
4488#define DUK_REOP_MATCH 1
4489#define DUK_REOP_CHAR 2
4490#define DUK_REOP_PERIOD 3
4491#define DUK_REOP_RANGES 4
4492#define DUK_REOP_INVRANGES 5
4493#define DUK_REOP_JUMP 6
4494#define DUK_REOP_SPLIT1 7
4495#define DUK_REOP_SPLIT2 8
4496#define DUK_REOP_SQMINIMAL 9
4497#define DUK_REOP_SQGREEDY 10
4498#define DUK_REOP_SAVE 11
4499#define DUK_REOP_WIPERANGE 12
4500#define DUK_REOP_LOOKPOS 13
4501#define DUK_REOP_LOOKNEG 14
4502#define DUK_REOP_BACKREFERENCE 15
4503#define DUK_REOP_ASSERT_START 16
4504#define DUK_REOP_ASSERT_END 17
4505#define DUK_REOP_ASSERT_WORD_BOUNDARY 18
4506#define DUK_REOP_ASSERT_NOT_WORD_BOUNDARY 19
4507
4508/* flags */
4509#define DUK_RE_FLAG_GLOBAL (1U << 0)
4510#define DUK_RE_FLAG_IGNORE_CASE (1U << 1)
4511#define DUK_RE_FLAG_MULTILINE (1U << 2)
4512
4515
4516 duk_uint32_t re_flags;
4517 const duk_uint8_t *input;
4518 const duk_uint8_t *input_end;
4519 const duk_uint8_t *bytecode;
4520 const duk_uint8_t *bytecode_end;
4521 const duk_uint8_t **saved; /* allocated from valstack (fixed buffer) */
4522 duk_uint32_t nsaved;
4523 duk_uint32_t recursion_depth;
4524 duk_uint32_t recursion_limit;
4525 duk_uint32_t steps_count;
4526 duk_uint32_t steps_limit;
4527};
4528
4531
4532 duk_uint32_t re_flags;
4536 duk_uint32_t captures; /* highest capture number emitted so far (used as: ++captures) */
4537 duk_uint32_t highest_backref;
4538 duk_uint32_t recursion_depth;
4539 duk_uint32_t recursion_limit;
4540 duk_uint32_t nranges; /* internal temporary value, used for char classes */
4541};
4542
4543/*
4544 * Prototypes
4545 */
4546
4547#if defined(DUK_USE_REGEXP_SUPPORT)
4551DUK_INTERNAL_DECL void duk_regexp_match_force_global(duk_hthread *thr); /* hacky helper for String.prototype.split() */
4552#endif
4553
4554#endif /* DUK_REGEXP_H_INCLUDED */
4555/* #include duk_heaphdr.h */
4556/*
4557 * Heap header definition and assorted macros, including ref counting.
4558 * Access all fields through the accessor macros.
4559 */
4560
4561#if !defined(DUK_HEAPHDR_H_INCLUDED)
4562#define DUK_HEAPHDR_H_INCLUDED
4563
4564/*
4565 * Common heap header
4566 *
4567 * All heap objects share the same flags and refcount fields. Objects other
4568 * than strings also need to have a single or double linked list pointers
4569 * for insertion into the "heap allocated" list. Strings have single linked
4570 * list pointers for string table chaining.
4571 *
4572 * Technically, 'h_refcount' must be wide enough to guarantee that it cannot
4573 * wrap; otherwise objects might be freed incorrectly after wrapping. The
4574 * default refcount field is 32 bits even on 64-bit systems: while that's in
4575 * theory incorrect, the Duktape heap needs to be larger than 64GB for the
4576 * count to actually wrap (assuming 16-byte duk_tvals). This is very unlikely
4577 * to ever be an issue, but if it is, disabling DUK_USE_REFCOUNT32 causes
4578 * Duktape to use size_t for refcounts which should always be safe.
4579 *
4580 * Heap header size on 32-bit platforms: 8 bytes without reference counting,
4581 * 16 bytes with reference counting.
4582 *
4583 * Note that 'raw' macros such as DUK_HEAPHDR_GET_REFCOUNT() are not
4584 * defined without DUK_USE_REFERENCE_COUNTING, so caller must #if defined()
4585 * around them.
4586 */
4587
4588/* XXX: macro for shared header fields (avoids some padding issues) */
4589
4591 duk_uint32_t h_flags;
4592
4593#if defined(DUK_USE_REFERENCE_COUNTING)
4594#if defined(DUK_USE_ASSERTIONS)
4595 /* When assertions enabled, used by mark-and-sweep for refcount
4596 * validation. Largest reasonable type; also detects overflows.
4597 */
4598 duk_size_t h_assert_refcount;
4599#endif
4600#if defined(DUK_USE_REFCOUNT16)
4601 duk_uint16_t h_refcount;
4602#elif defined(DUK_USE_REFCOUNT32)
4603 duk_uint32_t h_refcount;
4604#else
4606#endif
4607#endif /* DUK_USE_REFERENCE_COUNTING */
4608
4609#if defined(DUK_USE_HEAPPTR16)
4610 duk_uint16_t h_next16;
4611#else
4613#endif
4614
4615#if defined(DUK_USE_DOUBLE_LINKED_HEAP)
4616 /* refcounting requires direct heap frees, which in turn requires a dual linked heap */
4617#if defined(DUK_USE_HEAPPTR16)
4618 duk_uint16_t h_prev16;
4619#else
4621#endif
4622#endif
4623
4624 /* When DUK_USE_HEAPPTR16 (and DUK_USE_REFCOUNT16) is in use, the
4625 * struct won't align nicely to 4 bytes. This 16-bit extra field
4626 * is added to make the alignment clean; the field can be used by
4627 * heap objects when 16-bit packing is used. This field is now
4628 * conditional to DUK_USE_HEAPPTR16 only, but it is intended to be
4629 * used with DUK_USE_REFCOUNT16 and DUK_USE_DOUBLE_LINKED_HEAP;
4630 * this only matter to low memory environments anyway.
4631 */
4632#if defined(DUK_USE_HEAPPTR16)
4633 duk_uint16_t h_extra16;
4634#endif
4635};
4636
4638 /* 16 bits would be enough for shared heaphdr flags and duk_hstring
4639 * flags. The initial parts of duk_heaphdr_string and duk_heaphdr
4640 * must match so changing the flags field size here would be quite
4641 * awkward. However, to minimize struct size, we can pack at least
4642 * 16 bits of duk_hstring data into the flags field.
4643 */
4644 duk_uint32_t h_flags;
4645
4646#if defined(DUK_USE_REFERENCE_COUNTING)
4647#if defined(DUK_USE_ASSERTIONS)
4648 /* When assertions enabled, used by mark-and-sweep for refcount
4649 * validation. Largest reasonable type; also detects overflows.
4650 */
4651 duk_size_t h_assert_refcount;
4652#endif
4653#if defined(DUK_USE_REFCOUNT16)
4654 duk_uint16_t h_refcount;
4655 duk_uint16_t h_strextra16; /* round out to 8 bytes */
4656#elif defined(DUK_USE_REFCOUNT32)
4657 duk_uint32_t h_refcount;
4658#else
4660#endif
4661#else
4662 duk_uint16_t h_strextra16;
4663#endif /* DUK_USE_REFERENCE_COUNTING */
4664
4666 /* No 'h_prev' pointer for strings. */
4667};
4668
4669#define DUK_HEAPHDR_FLAGS_TYPE_MASK 0x00000003UL
4670#define DUK_HEAPHDR_FLAGS_FLAG_MASK (~DUK_HEAPHDR_FLAGS_TYPE_MASK)
4671
4672/* 2 bits for heap type */
4673#define DUK_HEAPHDR_FLAGS_HEAP_START 2 /* 5 heap flags */
4674#define DUK_HEAPHDR_FLAGS_USER_START 7 /* 25 user flags */
4675
4676#define DUK_HEAPHDR_HEAP_FLAG_NUMBER(n) (DUK_HEAPHDR_FLAGS_HEAP_START + (n))
4677#define DUK_HEAPHDR_USER_FLAG_NUMBER(n) (DUK_HEAPHDR_FLAGS_USER_START + (n))
4678#define DUK_HEAPHDR_HEAP_FLAG(n) (1UL << (DUK_HEAPHDR_FLAGS_HEAP_START + (n)))
4679#define DUK_HEAPHDR_USER_FLAG(n) (1UL << (DUK_HEAPHDR_FLAGS_USER_START + (n)))
4680
4681#define DUK_HEAPHDR_FLAG_REACHABLE DUK_HEAPHDR_HEAP_FLAG(0) /* mark-and-sweep: reachable */
4682#define DUK_HEAPHDR_FLAG_TEMPROOT DUK_HEAPHDR_HEAP_FLAG(1) /* mark-and-sweep: children not processed */
4683#define DUK_HEAPHDR_FLAG_FINALIZABLE DUK_HEAPHDR_HEAP_FLAG(2) /* mark-and-sweep: finalizable (on current pass) */
4684#define DUK_HEAPHDR_FLAG_FINALIZED DUK_HEAPHDR_HEAP_FLAG(3) /* mark-and-sweep: finalized (on previous pass) */
4685#define DUK_HEAPHDR_FLAG_READONLY DUK_HEAPHDR_HEAP_FLAG(4) /* read-only object, in code section */
4686
4687#define DUK_HTYPE_MIN 0
4688#define DUK_HTYPE_STRING 0
4689#define DUK_HTYPE_OBJECT 1
4690#define DUK_HTYPE_BUFFER 2
4691#define DUK_HTYPE_MAX 2
4692
4693#if defined(DUK_USE_HEAPPTR16)
4694#define DUK_HEAPHDR_GET_NEXT(heap, h) ((duk_heaphdr *) DUK_USE_HEAPPTR_DEC16((heap)->heap_udata, (h)->h_next16))
4695#define DUK_HEAPHDR_SET_NEXT(heap, h, val) \
4696 do { \
4697 (h)->h_next16 = DUK_USE_HEAPPTR_ENC16((heap)->heap_udata, (void *) val); \
4698 } while (0)
4699#else
4700#define DUK_HEAPHDR_GET_NEXT(heap, h) ((h)->h_next)
4701#define DUK_HEAPHDR_SET_NEXT(heap, h, val) \
4702 do { \
4703 (h)->h_next = (val); \
4704 } while (0)
4705#endif
4706
4707#if defined(DUK_USE_DOUBLE_LINKED_HEAP)
4708#if defined(DUK_USE_HEAPPTR16)
4709#define DUK_HEAPHDR_GET_PREV(heap, h) ((duk_heaphdr *) DUK_USE_HEAPPTR_DEC16((heap)->heap_udata, (h)->h_prev16))
4710#define DUK_HEAPHDR_SET_PREV(heap, h, val) \
4711 do { \
4712 (h)->h_prev16 = DUK_USE_HEAPPTR_ENC16((heap)->heap_udata, (void *) (val)); \
4713 } while (0)
4714#else
4715#define DUK_HEAPHDR_GET_PREV(heap, h) ((h)->h_prev)
4716#define DUK_HEAPHDR_SET_PREV(heap, h, val) \
4717 do { \
4718 (h)->h_prev = (val); \
4719 } while (0)
4720#endif
4721#endif
4722
4723#if defined(DUK_USE_REFERENCE_COUNTING)
4724#define DUK_HEAPHDR_GET_REFCOUNT(h) ((h)->h_refcount)
4725#define DUK_HEAPHDR_SET_REFCOUNT(h, val) \
4726 do { \
4727 (h)->h_refcount = (val); \
4728 DUK_ASSERT((h)->h_refcount == (val)); /* No truncation. */ \
4729 } while (0)
4730#define DUK_HEAPHDR_PREINC_REFCOUNT(h) (++(h)->h_refcount) /* result: updated refcount */
4731#define DUK_HEAPHDR_PREDEC_REFCOUNT(h) (--(h)->h_refcount) /* result: updated refcount */
4732#else
4733/* refcount macros not defined without refcounting, caller must #if defined() now */
4734#endif /* DUK_USE_REFERENCE_COUNTING */
4735
4736/*
4737 * Note: type is treated as a field separate from flags, so some masking is
4738 * involved in the macros below.
4739 */
4740
4741#define DUK_HEAPHDR_GET_FLAGS_RAW(h) ((h)->h_flags)
4742#define DUK_HEAPHDR_SET_FLAGS_RAW(h, val) \
4743 do { \
4744 (h)->h_flags = (val); \
4745 } \
4746 }
4747#define DUK_HEAPHDR_GET_FLAGS(h) ((h)->h_flags & DUK_HEAPHDR_FLAGS_FLAG_MASK)
4748#define DUK_HEAPHDR_SET_FLAGS(h, val) \
4749 do { \
4750 (h)->h_flags = ((h)->h_flags & ~(DUK_HEAPHDR_FLAGS_FLAG_MASK)) | (val); \
4751 } while (0)
4752#define DUK_HEAPHDR_GET_TYPE(h) ((h)->h_flags & DUK_HEAPHDR_FLAGS_TYPE_MASK)
4753#define DUK_HEAPHDR_SET_TYPE(h, val) \
4754 do { \
4755 (h)->h_flags = ((h)->h_flags & ~(DUK_HEAPHDR_FLAGS_TYPE_MASK)) | (val); \
4756 } while (0)
4757
4758/* Comparison for type >= DUK_HTYPE_MIN skipped; because DUK_HTYPE_MIN is zero
4759 * and the comparison is unsigned, it's always true and generates warnings.
4760 */
4761#define DUK_HEAPHDR_HTYPE_VALID(h) (DUK_HEAPHDR_GET_TYPE((h)) <= DUK_HTYPE_MAX)
4762
4763#define DUK_HEAPHDR_SET_TYPE_AND_FLAGS(h, tval, fval) \
4764 do { \
4765 (h)->h_flags = ((tval) &DUK_HEAPHDR_FLAGS_TYPE_MASK) | ((fval) &DUK_HEAPHDR_FLAGS_FLAG_MASK); \
4766 } while (0)
4767
4768#define DUK_HEAPHDR_SET_FLAG_BITS(h, bits) \
4769 do { \
4770 DUK_ASSERT(((bits) & ~(DUK_HEAPHDR_FLAGS_FLAG_MASK)) == 0); \
4771 (h)->h_flags |= (bits); \
4772 } while (0)
4773
4774#define DUK_HEAPHDR_CLEAR_FLAG_BITS(h, bits) \
4775 do { \
4776 DUK_ASSERT(((bits) & ~(DUK_HEAPHDR_FLAGS_FLAG_MASK)) == 0); \
4777 (h)->h_flags &= ~((bits)); \
4778 } while (0)
4779
4780#define DUK_HEAPHDR_CHECK_FLAG_BITS(h, bits) (((h)->h_flags & (bits)) != 0)
4781
4782#define DUK_HEAPHDR_SET_REACHABLE(h) DUK_HEAPHDR_SET_FLAG_BITS((h), DUK_HEAPHDR_FLAG_REACHABLE)
4783#define DUK_HEAPHDR_CLEAR_REACHABLE(h) DUK_HEAPHDR_CLEAR_FLAG_BITS((h), DUK_HEAPHDR_FLAG_REACHABLE)
4784#define DUK_HEAPHDR_HAS_REACHABLE(h) DUK_HEAPHDR_CHECK_FLAG_BITS((h), DUK_HEAPHDR_FLAG_REACHABLE)
4785
4786#define DUK_HEAPHDR_SET_TEMPROOT(h) DUK_HEAPHDR_SET_FLAG_BITS((h), DUK_HEAPHDR_FLAG_TEMPROOT)
4787#define DUK_HEAPHDR_CLEAR_TEMPROOT(h) DUK_HEAPHDR_CLEAR_FLAG_BITS((h), DUK_HEAPHDR_FLAG_TEMPROOT)
4788#define DUK_HEAPHDR_HAS_TEMPROOT(h) DUK_HEAPHDR_CHECK_FLAG_BITS((h), DUK_HEAPHDR_FLAG_TEMPROOT)
4789
4790#define DUK_HEAPHDR_SET_FINALIZABLE(h) DUK_HEAPHDR_SET_FLAG_BITS((h), DUK_HEAPHDR_FLAG_FINALIZABLE)
4791#define DUK_HEAPHDR_CLEAR_FINALIZABLE(h) DUK_HEAPHDR_CLEAR_FLAG_BITS((h), DUK_HEAPHDR_FLAG_FINALIZABLE)
4792#define DUK_HEAPHDR_HAS_FINALIZABLE(h) DUK_HEAPHDR_CHECK_FLAG_BITS((h), DUK_HEAPHDR_FLAG_FINALIZABLE)
4793
4794#define DUK_HEAPHDR_SET_FINALIZED(h) DUK_HEAPHDR_SET_FLAG_BITS((h), DUK_HEAPHDR_FLAG_FINALIZED)
4795#define DUK_HEAPHDR_CLEAR_FINALIZED(h) DUK_HEAPHDR_CLEAR_FLAG_BITS((h), DUK_HEAPHDR_FLAG_FINALIZED)
4796#define DUK_HEAPHDR_HAS_FINALIZED(h) DUK_HEAPHDR_CHECK_FLAG_BITS((h), DUK_HEAPHDR_FLAG_FINALIZED)
4797
4798#define DUK_HEAPHDR_SET_READONLY(h) DUK_HEAPHDR_SET_FLAG_BITS((h), DUK_HEAPHDR_FLAG_READONLY)
4799#define DUK_HEAPHDR_CLEAR_READONLY(h) DUK_HEAPHDR_CLEAR_FLAG_BITS((h), DUK_HEAPHDR_FLAG_READONLY)
4800#define DUK_HEAPHDR_HAS_READONLY(h) DUK_HEAPHDR_CHECK_FLAG_BITS((h), DUK_HEAPHDR_FLAG_READONLY)
4801
4802/* get or set a range of flags; m=first bit number, n=number of bits */
4803#define DUK_HEAPHDR_GET_FLAG_RANGE(h, m, n) (((h)->h_flags >> (m)) & ((1UL << (n)) - 1UL))
4804
4805#define DUK_HEAPHDR_SET_FLAG_RANGE(h, m, n, v) \
4806 do { \
4807 (h)->h_flags = ((h)->h_flags & (~(((1UL << (n)) - 1UL) << (m)))) | ((v) << (m)); \
4808 } while (0)
4809
4810/* init pointer fields to null */
4811#if defined(DUK_USE_DOUBLE_LINKED_HEAP)
4812#define DUK_HEAPHDR_INIT_NULLS(h) \
4813 do { \
4814 DUK_HEAPHDR_SET_NEXT((h), (void *) NULL); \
4815 DUK_HEAPHDR_SET_PREV((h), (void *) NULL); \
4816 } while (0)
4817#else
4818#define DUK_HEAPHDR_INIT_NULLS(h) \
4819 do { \
4820 DUK_HEAPHDR_SET_NEXT((h), (void *) NULL); \
4821 } while (0)
4822#endif
4823
4824#define DUK_HEAPHDR_STRING_INIT_NULLS(h) \
4825 do { \
4826 (h)->h_next = NULL; \
4827 } while (0)
4828
4829/*
4830 * Type tests
4831 */
4832
4833/* Take advantage of the fact that for DUK_HTYPE_xxx numbers the lowest bit
4834 * is only set for DUK_HTYPE_OBJECT (= 1).
4835 */
4836#if 0
4837#define DUK_HEAPHDR_IS_OBJECT(h) (DUK_HEAPHDR_GET_TYPE((h)) == DUK_HTYPE_OBJECT)
4838#endif
4839#define DUK_HEAPHDR_IS_OBJECT(h) ((h)->h_flags & 0x01UL)
4840#define DUK_HEAPHDR_IS_STRING(h) (DUK_HEAPHDR_GET_TYPE((h)) == DUK_HTYPE_STRING)
4841#define DUK_HEAPHDR_IS_BUFFER(h) (DUK_HEAPHDR_GET_TYPE((h)) == DUK_HTYPE_BUFFER)
4842
4843/*
4844 * Assert helpers
4845 */
4846
4847/* Check that prev/next links are consistent: if e.g. h->prev is != NULL,
4848 * h->prev->next should point back to h.
4849 */
4850#if defined(DUK_USE_ASSERTIONS)
4851DUK_INTERNAL_DECL void duk_heaphdr_assert_valid_subclassed(duk_heaphdr *h);
4852DUK_INTERNAL_DECL void duk_heaphdr_assert_links(duk_heap *heap, duk_heaphdr *h);
4853DUK_INTERNAL_DECL void duk_heaphdr_assert_valid(duk_heaphdr *h);
4854#define DUK_HEAPHDR_ASSERT_LINKS(heap, h) \
4855 do { \
4856 duk_heaphdr_assert_links((heap), (h)); \
4857 } while (0)
4858#define DUK_HEAPHDR_ASSERT_VALID(h) \
4859 do { \
4860 duk_heaphdr_assert_valid((h)); \
4861 } while (0)
4862#else
4863#define DUK_HEAPHDR_ASSERT_LINKS(heap, h) \
4864 do { \
4865 } while (0)
4866#define DUK_HEAPHDR_ASSERT_VALID(h) \
4867 do { \
4868 } while (0)
4869#endif
4870
4871#endif /* DUK_HEAPHDR_H_INCLUDED */
4872/* #include duk_refcount.h */
4873/*
4874 * Reference counting helper macros. The macros take a thread argument
4875 * and must thus always be executed in a specific thread context. The
4876 * thread argument is not really needed anymore: DECREF can operate with
4877 * a heap pointer only, and INCREF needs neither.
4878 */
4879
4880#if !defined(DUK_REFCOUNT_H_INCLUDED)
4881#define DUK_REFCOUNT_H_INCLUDED
4882
4883#if defined(DUK_USE_REFERENCE_COUNTING)
4884
4885#if defined(DUK_USE_ROM_OBJECTS)
4886/* With ROM objects "needs refcount update" is true when the value is
4887 * heap allocated and is not a ROM object.
4888 */
4889/* XXX: double evaluation for 'tv' argument. */
4890#define DUK_TVAL_NEEDS_REFCOUNT_UPDATE(tv) \
4891 (DUK_TVAL_IS_HEAP_ALLOCATED((tv)) && !DUK_HEAPHDR_HAS_READONLY(DUK_TVAL_GET_HEAPHDR((tv))))
4892#define DUK_HEAPHDR_NEEDS_REFCOUNT_UPDATE(h) (!DUK_HEAPHDR_HAS_READONLY((h)))
4893#else /* DUK_USE_ROM_OBJECTS */
4894/* Without ROM objects "needs refcount update" == is heap allocated. */
4895#define DUK_TVAL_NEEDS_REFCOUNT_UPDATE(tv) DUK_TVAL_IS_HEAP_ALLOCATED((tv))
4896#define DUK_HEAPHDR_NEEDS_REFCOUNT_UPDATE(h) 1
4897#endif /* DUK_USE_ROM_OBJECTS */
4898
4899/* Fast variants, inline refcount operations except for refzero handling.
4900 * Can be used explicitly when speed is always more important than size.
4901 * For a good compiler and a single file build, these are basically the
4902 * same as a forced inline.
4903 */
4904#define DUK_TVAL_INCREF_FAST(thr, tv) \
4905 do { \
4906 duk_tval *duk__tv = (tv); \
4907 DUK_ASSERT(duk__tv != NULL); \
4908 if (DUK_TVAL_NEEDS_REFCOUNT_UPDATE(duk__tv)) { \
4909 duk_heaphdr *duk__h = DUK_TVAL_GET_HEAPHDR(duk__tv); \
4910 DUK_ASSERT(duk__h != NULL); \
4911 DUK_ASSERT(DUK_HEAPHDR_HTYPE_VALID(duk__h)); \
4912 DUK_HEAPHDR_PREINC_REFCOUNT(duk__h); \
4913 DUK_ASSERT(DUK_HEAPHDR_GET_REFCOUNT(duk__h) != 0); /* No wrapping. */ \
4914 } \
4915 } while (0)
4916#define DUK_TVAL_DECREF_FAST(thr, tv) \
4917 do { \
4918 duk_tval *duk__tv = (tv); \
4919 DUK_ASSERT(duk__tv != NULL); \
4920 if (DUK_TVAL_NEEDS_REFCOUNT_UPDATE(duk__tv)) { \
4921 duk_heaphdr *duk__h = DUK_TVAL_GET_HEAPHDR(duk__tv); \
4922 DUK_ASSERT(duk__h != NULL); \
4923 DUK_ASSERT(DUK_HEAPHDR_HTYPE_VALID(duk__h)); \
4924 DUK_ASSERT(DUK_HEAPHDR_GET_REFCOUNT(duk__h) > 0); \
4925 if (DUK_HEAPHDR_PREDEC_REFCOUNT(duk__h) == 0) { \
4926 duk_heaphdr_refzero((thr), duk__h); \
4927 } \
4928 } \
4929 } while (0)
4930#define DUK_TVAL_DECREF_NORZ_FAST(thr, tv) \
4931 do { \
4932 duk_tval *duk__tv = (tv); \
4933 DUK_ASSERT(duk__tv != NULL); \
4934 if (DUK_TVAL_NEEDS_REFCOUNT_UPDATE(duk__tv)) { \
4935 duk_heaphdr *duk__h = DUK_TVAL_GET_HEAPHDR(duk__tv); \
4936 DUK_ASSERT(duk__h != NULL); \
4937 DUK_ASSERT(DUK_HEAPHDR_HTYPE_VALID(duk__h)); \
4938 DUK_ASSERT(DUK_HEAPHDR_GET_REFCOUNT(duk__h) > 0); \
4939 if (DUK_HEAPHDR_PREDEC_REFCOUNT(duk__h) == 0) { \
4940 duk_heaphdr_refzero_norz((thr), duk__h); \
4941 } \
4942 } \
4943 } while (0)
4944#define DUK_HEAPHDR_INCREF_FAST(thr, h) \
4945 do { \
4946 duk_heaphdr *duk__h = (duk_heaphdr *) (h); \
4947 DUK_ASSERT(duk__h != NULL); \
4948 DUK_ASSERT(DUK_HEAPHDR_HTYPE_VALID(duk__h)); \
4949 if (DUK_HEAPHDR_NEEDS_REFCOUNT_UPDATE(duk__h)) { \
4950 DUK_HEAPHDR_PREINC_REFCOUNT(duk__h); \
4951 DUK_ASSERT(DUK_HEAPHDR_GET_REFCOUNT(duk__h) != 0); /* No wrapping. */ \
4952 } \
4953 } while (0)
4954#define DUK_HEAPHDR_DECREF_FAST_RAW(thr, h, rzcall, rzcast) \
4955 do { \
4956 duk_heaphdr *duk__h = (duk_heaphdr *) (h); \
4957 DUK_ASSERT(duk__h != NULL); \
4958 DUK_ASSERT(DUK_HEAPHDR_HTYPE_VALID(duk__h)); \
4959 DUK_ASSERT(DUK_HEAPHDR_GET_REFCOUNT(duk__h) > 0); \
4960 if (DUK_HEAPHDR_NEEDS_REFCOUNT_UPDATE(duk__h)) { \
4961 if (DUK_HEAPHDR_PREDEC_REFCOUNT(duk__h) == 0) { \
4962 (rzcall)((thr), (rzcast) duk__h); \
4963 } \
4964 } \
4965 } while (0)
4966#define DUK_HEAPHDR_DECREF_FAST(thr, h) DUK_HEAPHDR_DECREF_FAST_RAW((thr), (h), duk_heaphdr_refzero, duk_heaphdr *)
4967#define DUK_HEAPHDR_DECREF_NORZ_FAST(thr, h) DUK_HEAPHDR_DECREF_FAST_RAW((thr), (h), duk_heaphdr_refzero_norz, duk_heaphdr *)
4968
4969/* Slow variants, call to a helper to reduce code size.
4970 * Can be used explicitly when size is always more important than speed.
4971 */
4972#define DUK_TVAL_INCREF_SLOW(thr, tv) \
4973 do { \
4974 duk_tval_incref((tv)); \
4975 } while (0)
4976#define DUK_TVAL_DECREF_SLOW(thr, tv) \
4977 do { \
4978 duk_tval_decref((thr), (tv)); \
4979 } while (0)
4980#define DUK_TVAL_DECREF_NORZ_SLOW(thr, tv) \
4981 do { \
4982 duk_tval_decref_norz((thr), (tv)); \
4983 } while (0)
4984#define DUK_HEAPHDR_INCREF_SLOW(thr, h) \
4985 do { \
4986 duk_heaphdr_incref((duk_heaphdr *) (h)); \
4987 } while (0)
4988#define DUK_HEAPHDR_DECREF_SLOW(thr, h) \
4989 do { \
4990 duk_heaphdr_decref((thr), (duk_heaphdr *) (h)); \
4991 } while (0)
4992#define DUK_HEAPHDR_DECREF_NORZ_SLOW(thr, h) \
4993 do { \
4994 duk_heaphdr_decref_norz((thr), (duk_heaphdr *) (h)); \
4995 } while (0)
4996#define DUK_HSTRING_INCREF_SLOW(thr, h) \
4997 do { \
4998 duk_heaphdr_incref((duk_heaphdr *) (h)); \
4999 } while (0)
5000#define DUK_HSTRING_DECREF_SLOW(thr, h) \
5001 do { \
5002 duk_heaphdr_decref((thr), (duk_heaphdr *) (h)); \
5003 } while (0)
5004#define DUK_HSTRING_DECREF_NORZ_SLOW(thr, h) \
5005 do { \
5006 duk_heaphdr_decref_norz((thr), (duk_heaphdr *) (h)); \
5007 } while (0)
5008#define DUK_HBUFFER_INCREF_SLOW(thr, h) \
5009 do { \
5010 duk_heaphdr_incref((duk_heaphdr *) (h)); \
5011 } while (0)
5012#define DUK_HBUFFER_DECREF_SLOW(thr, h) \
5013 do { \
5014 duk_heaphdr_decref((thr), (duk_heaphdr *) (h)); \
5015 } while (0)
5016#define DUK_HBUFFER_DECREF_NORZ_SLOW(thr, h) \
5017 do { \
5018 duk_heaphdr_decref_norz((thr), (duk_heaphdr *) (h)); \
5019 } while (0)
5020#define DUK_HOBJECT_INCREF_SLOW(thr, h) \
5021 do { \
5022 duk_heaphdr_incref((duk_heaphdr *) (h)); \
5023 } while (0)
5024#define DUK_HOBJECT_DECREF_SLOW(thr, h) \
5025 do { \
5026 duk_heaphdr_decref((thr), (duk_heaphdr *) (h)); \
5027 } while (0)
5028#define DUK_HOBJECT_DECREF_NORZ_SLOW(thr, h) \
5029 do { \
5030 duk_heaphdr_decref_norz((thr), (duk_heaphdr *) (h)); \
5031 } while (0)
5032
5033/* Default variants. Selection depends on speed/size preference.
5034 * Concretely: with gcc 4.8.1 -Os x64 the difference in final binary
5035 * is about +1kB for _FAST variants.
5036 */
5037#if defined(DUK_USE_FAST_REFCOUNT_DEFAULT)
5038/* XXX: It would be nice to specialize for specific duk_hobject subtypes
5039 * but current refzero queue handling prevents that.
5040 */
5041#define DUK_TVAL_INCREF(thr, tv) DUK_TVAL_INCREF_FAST((thr), (tv))
5042#define DUK_TVAL_DECREF(thr, tv) DUK_TVAL_DECREF_FAST((thr), (tv))
5043#define DUK_TVAL_DECREF_NORZ(thr, tv) DUK_TVAL_DECREF_NORZ_FAST((thr), (tv))
5044#define DUK_HEAPHDR_INCREF(thr, h) DUK_HEAPHDR_INCREF_FAST((thr), (h))
5045#define DUK_HEAPHDR_DECREF(thr, h) DUK_HEAPHDR_DECREF_FAST_RAW((thr), (h), duk_heaphdr_refzero, duk_heaphdr *)
5046#define DUK_HEAPHDR_DECREF_NORZ(thr, h) DUK_HEAPHDR_DECREF_FAST_RAW((thr), (h), duk_heaphdr_refzero_norz, duk_heaphdr *)
5047#define DUK_HSTRING_INCREF(thr, h) DUK_HEAPHDR_INCREF((thr), (duk_heaphdr *) (h))
5048#define DUK_HSTRING_DECREF(thr, h) DUK_HEAPHDR_DECREF_FAST_RAW((thr), (h), duk_hstring_refzero, duk_hstring *)
5049#define DUK_HSTRING_DECREF_NORZ(thr, h) \
5050 DUK_HEAPHDR_DECREF_FAST_RAW((thr), (h), duk_hstring_refzero, duk_hstring *) /* no 'norz' variant */
5051#define DUK_HOBJECT_INCREF(thr, h) DUK_HEAPHDR_INCREF((thr), (duk_heaphdr *) (h))
5052#define DUK_HOBJECT_DECREF(thr, h) DUK_HEAPHDR_DECREF_FAST_RAW((thr), (h), duk_hobject_refzero, duk_hobject *)
5053#define DUK_HOBJECT_DECREF_NORZ(thr, h) DUK_HEAPHDR_DECREF_FAST_RAW((thr), (h), duk_hobject_refzero_norz, duk_hobject *)
5054#define DUK_HBUFFER_INCREF(thr, h) DUK_HEAPHDR_INCREF((thr), (duk_heaphdr *) (h))
5055#define DUK_HBUFFER_DECREF(thr, h) DUK_HEAPHDR_DECREF_FAST_RAW((thr), (h), duk_hbuffer_refzero, duk_hbuffer *)
5056#define DUK_HBUFFER_DECREF_NORZ(thr, h) \
5057 DUK_HEAPHDR_DECREF_FAST_RAW((thr), (h), duk_hbuffer_refzero, duk_hbuffer *) /* no 'norz' variant */
5058#define DUK_HCOMPFUNC_INCREF(thr, h) DUK_HEAPHDR_INCREF((thr), (duk_heaphdr *) &(h)->obj)
5059#define DUK_HCOMPFUNC_DECREF(thr, h) DUK_HEAPHDR_DECREF_FAST_RAW((thr), (h), duk_hobject_refzero, duk_hobject *)
5060#define DUK_HCOMPFUNC_DECREF_NORZ(thr, h) DUK_HEAPHDR_DECREF_FAST_RAW((thr), (h), duk_hobject_refzero_norz, duk_hobject *)
5061#define DUK_HNATFUNC_INCREF(thr, h) DUK_HEAPHDR_INCREF((thr), (duk_heaphdr *) &(h)->obj)
5062#define DUK_HNATFUNC_DECREF(thr, h) DUK_HEAPHDR_DECREF_FAST_RAW((thr), (h), duk_hobject_refzero, duk_hobject *)
5063#define DUK_HNATFUNC_DECREF_NORZ(thr, h) DUK_HEAPHDR_DECREF_FAST_RAW((thr), (h), duk_hobject_refzero_norz, duk_hobject *)
5064#define DUK_HBUFOBJ_INCREF(thr, h) DUK_HEAPHDR_INCREF((thr), (duk_heaphdr *) &(h)->obj)
5065#define DUK_HBUFOBJ_DECREF(thr, h) DUK_HEAPHDR_DECREF_FAST_RAW((thr), (h), duk_hobject_refzero, duk_hobject *)
5066#define DUK_HBUFOBJ_DECREF_NORZ(thr, h) DUK_HEAPHDR_DECREF_FAST_RAW((thr), (h), duk_hobject_refzero_norz, duk_hobject *)
5067#define DUK_HTHREAD_INCREF(thr, h) DUK_HEAPHDR_INCREF((thr), (duk_heaphdr *) &(h)->obj)
5068#define DUK_HTHREAD_DECREF(thr, h) DUK_HEAPHDR_DECREF_FAST_RAW((thr), (h), duk_hobject_refzero, duk_hobject *)
5069#define DUK_HTHREAD_DECREF_NORZ(thr, h) DUK_HEAPHDR_DECREF_FAST_RAW((thr), (h), duk_hobject_refzero_norz, duk_hobject *)
5070#else
5071#define DUK_TVAL_INCREF(thr, tv) DUK_TVAL_INCREF_SLOW((thr), (tv))
5072#define DUK_TVAL_DECREF(thr, tv) DUK_TVAL_DECREF_SLOW((thr), (tv))
5073#define DUK_TVAL_DECREF_NORZ(thr, tv) DUK_TVAL_DECREF_NORZ_SLOW((thr), (tv))
5074#define DUK_HEAPHDR_INCREF(thr, h) DUK_HEAPHDR_INCREF_SLOW((thr), (h))
5075#define DUK_HEAPHDR_DECREF(thr, h) DUK_HEAPHDR_DECREF_SLOW((thr), (h))
5076#define DUK_HEAPHDR_DECREF_NORZ(thr, h) DUK_HEAPHDR_DECREF_NORZ_SLOW((thr), (h))
5077#define DUK_HSTRING_INCREF(thr, h) DUK_HEAPHDR_INCREF((thr), (duk_heaphdr *) (h))
5078#define DUK_HSTRING_DECREF(thr, h) DUK_HSTRING_DECREF_SLOW((thr), (h))
5079#define DUK_HSTRING_DECREF_NORZ(thr, h) DUK_HSTRING_DECREF_NORZ_SLOW((thr), (h))
5080#define DUK_HOBJECT_INCREF(thr, h) DUK_HEAPHDR_INCREF((thr), (duk_heaphdr *) (h))
5081#define DUK_HOBJECT_DECREF(thr, h) DUK_HOBJECT_DECREF_SLOW((thr), (h))
5082#define DUK_HOBJECT_DECREF_NORZ(thr, h) DUK_HOBJECT_DECREF_NORZ_SLOW((thr), (h))
5083#define DUK_HBUFFER_INCREF(thr, h) DUK_HEAPHDR_INCREF((thr), (duk_heaphdr *) (h))
5084#define DUK_HBUFFER_DECREF(thr, h) DUK_HBUFFER_DECREF_SLOW((thr), (h))
5085#define DUK_HBUFFER_DECREF_NORZ(thr, h) DUK_HBUFFER_DECREF_NORZ_SLOW((thr), (h))
5086#define DUK_HCOMPFUNC_INCREF(thr, h) DUK_HEAPHDR_INCREF((thr), (duk_heaphdr *) &(h)->obj)
5087#define DUK_HCOMPFUNC_DECREF(thr, h) DUK_HOBJECT_DECREF_SLOW((thr), (duk_hobject *) &(h)->obj)
5088#define DUK_HCOMPFUNC_DECREF_NORZ(thr, h) DUK_HOBJECT_DECREF_NORZ_SLOW((thr), (duk_hobject *) &(h)->obj)
5089#define DUK_HNATFUNC_INCREF(thr, h) DUK_HEAPHDR_INCREF((thr), (duk_heaphdr *) &(h)->obj)
5090#define DUK_HNATFUNC_DECREF(thr, h) DUK_HOBJECT_DECREF_SLOW((thr), (duk_hobject *) &(h)->obj)
5091#define DUK_HNATFUNC_DECREF_NORZ(thr, h) DUK_HOBJECT_DECREF_NORZ_SLOW((thr), (duk_hobject *) &(h)->obj)
5092#define DUK_HBUFOBJ_INCREF(thr, h) DUK_HEAPHDR_INCREF((thr), (duk_heaphdr *) &(h)->obj)
5093#define DUK_HBUFOBJ_DECREF(thr, h) DUK_HOBJECT_DECREF_SLOW((thr), (duk_hobject *) &(h)->obj)
5094#define DUK_HBUFOB_DECREF_NORZ(thr, h) DUK_HOBJECT_DECREF_NORZ_SLOW((thr), (duk_hobject *) &(h)->obj)
5095#define DUK_HTHREAD_INCREF(thr, h) DUK_HEAPHDR_INCREF((thr), (duk_heaphdr *) &(h)->obj)
5096#define DUK_HTHREAD_DECREF(thr, h) DUK_HOBJECT_DECREF_SLOW((thr), (duk_hobject *) &(h)->obj)
5097#define DUK_HTHREAD_DECREF_NORZ(thr, h) DUK_HOBJECT_DECREF_NORZ_SLOW((thr), (duk_hobject *) &(h)->obj)
5098#endif
5099
5100/* Convenience for some situations; the above macros don't allow NULLs
5101 * for performance reasons. Macros cover only actually needed cases.
5102 */
5103#define DUK_HEAPHDR_INCREF_ALLOWNULL(thr, h) \
5104 do { \
5105 if ((h) != NULL) { \
5106 DUK_HEAPHDR_INCREF((thr), (duk_heaphdr *) (h)); \
5107 } \
5108 } while (0)
5109#define DUK_HEAPHDR_DECREF_ALLOWNULL(thr, h) \
5110 do { \
5111 if ((h) != NULL) { \
5112 DUK_HEAPHDR_DECREF((thr), (duk_heaphdr *) (h)); \
5113 } \
5114 } while (0)
5115#define DUK_HEAPHDR_DECREF_NORZ_ALLOWNULL(thr, h) \
5116 do { \
5117 if ((h) != NULL) { \
5118 DUK_HEAPHDR_DECREF_NORZ((thr), (duk_heaphdr *) (h)); \
5119 } \
5120 } while (0)
5121#define DUK_HOBJECT_INCREF_ALLOWNULL(thr, h) \
5122 do { \
5123 if ((h) != NULL) { \
5124 DUK_HOBJECT_INCREF((thr), (h)); \
5125 } \
5126 } while (0)
5127#define DUK_HOBJECT_DECREF_ALLOWNULL(thr, h) \
5128 do { \
5129 if ((h) != NULL) { \
5130 DUK_HOBJECT_DECREF((thr), (h)); \
5131 } \
5132 } while (0)
5133#define DUK_HOBJECT_DECREF_NORZ_ALLOWNULL(thr, h) \
5134 do { \
5135 if ((h) != NULL) { \
5136 DUK_HOBJECT_DECREF_NORZ((thr), (h)); \
5137 } \
5138 } while (0)
5139#define DUK_HBUFFER_INCREF_ALLOWNULL(thr, h) \
5140 do { \
5141 if ((h) != NULL) { \
5142 DUK_HBUFFER_INCREF((thr), (h)); \
5143 } \
5144 } while (0)
5145#define DUK_HBUFFER_DECREF_ALLOWNULL(thr, h) \
5146 do { \
5147 if ((h) != NULL) { \
5148 DUK_HBUFFER_DECREF((thr), (h)); \
5149 } \
5150 } while (0)
5151#define DUK_HBUFFER_DECREF_NORZ_ALLOWNULL(thr, h) \
5152 do { \
5153 if ((h) != NULL) { \
5154 DUK_HBUFFER_DECREF_NORZ((thr), (h)); \
5155 } \
5156 } while (0)
5157#define DUK_HTHREAD_INCREF_ALLOWNULL(thr, h) \
5158 do { \
5159 if ((h) != NULL) { \
5160 DUK_HTHREAD_INCREF((thr), (h)); \
5161 } \
5162 } while (0)
5163#define DUK_HTHREAD_DECREF_ALLOWNULL(thr, h) \
5164 do { \
5165 if ((h) != NULL) { \
5166 DUK_HTHREAD_DECREF((thr), (h)); \
5167 } \
5168 } while (0)
5169#define DUK_HTHREAD_DECREF_NORZ_ALLOWNULL(thr, h) \
5170 do { \
5171 if ((h) != NULL) { \
5172 DUK_HTHREAD_DECREF_NORZ((thr), (h)); \
5173 } \
5174 } while (0)
5175
5176/* Called after one or more DECREF NORZ calls to handle pending side effects.
5177 * At present DECREF NORZ does freeing inline but doesn't execute finalizers,
5178 * so these macros check for pending finalizers and execute them. The FAST
5179 * variant is performance critical.
5180 */
5181#if defined(DUK_USE_FINALIZER_SUPPORT)
5182#define DUK_REFZERO_CHECK_FAST(thr) \
5183 do { \
5184 duk_refzero_check_fast((thr)); \
5185 } while (0)
5186#define DUK_REFZERO_CHECK_SLOW(thr) \
5187 do { \
5188 duk_refzero_check_slow((thr)); \
5189 } while (0)
5190#else /* DUK_USE_FINALIZER_SUPPORT */
5191#define DUK_REFZERO_CHECK_FAST(thr) \
5192 do { \
5193 } while (0)
5194#define DUK_REFZERO_CHECK_SLOW(thr) \
5195 do { \
5196 } while (0)
5197#endif /* DUK_USE_FINALIZER_SUPPORT */
5198
5199/*
5200 * Macros to set a duk_tval and update refcount of the target (decref the
5201 * old value and incref the new value if necessary). This is both performance
5202 * and footprint critical; any changes made should be measured for size/speed.
5203 */
5204
5205#define DUK_TVAL_SET_UNDEFINED_UPDREF_ALT0(thr, tvptr_dst) \
5206 do { \
5207 duk_tval *tv__dst; \
5208 duk_tval tv__tmp; \
5209 tv__dst = (tvptr_dst); \
5210 DUK_TVAL_SET_TVAL(&tv__tmp, tv__dst); \
5211 DUK_TVAL_SET_UNDEFINED(tv__dst); \
5212 DUK_TVAL_DECREF((thr), &tv__tmp); /* side effects */ \
5213 } while (0)
5214
5215#define DUK_TVAL_SET_UNDEFINED_UPDREF_NORZ_ALT0(thr, tvptr_dst) \
5216 do { \
5217 duk_tval *tv__dst; \
5218 duk_tval tv__tmp; \
5219 tv__dst = (tvptr_dst); \
5220 DUK_TVAL_SET_TVAL(&tv__tmp, tv__dst); \
5221 DUK_TVAL_SET_UNDEFINED(tv__dst); \
5222 DUK_TVAL_DECREF_NORZ((thr), &tv__tmp); \
5223 } while (0)
5224
5225#define DUK_TVAL_SET_UNUSED_UPDREF_ALT0(thr, tvptr_dst) \
5226 do { \
5227 duk_tval *tv__dst; \
5228 duk_tval tv__tmp; \
5229 tv__dst = (tvptr_dst); \
5230 DUK_TVAL_SET_TVAL(&tv__tmp, tv__dst); \
5231 DUK_TVAL_SET_UNUSED(tv__dst); \
5232 DUK_TVAL_DECREF((thr), &tv__tmp); /* side effects */ \
5233 } while (0)
5234
5235#define DUK_TVAL_SET_NULL_UPDREF_ALT0(thr, tvptr_dst) \
5236 do { \
5237 duk_tval *tv__dst; \
5238 duk_tval tv__tmp; \
5239 tv__dst = (tvptr_dst); \
5240 DUK_TVAL_SET_TVAL(&tv__tmp, tv__dst); \
5241 DUK_TVAL_SET_NULL(tv__dst); \
5242 DUK_TVAL_DECREF((thr), &tv__tmp); /* side effects */ \
5243 } while (0)
5244
5245#define DUK_TVAL_SET_BOOLEAN_UPDREF_ALT0(thr, tvptr_dst, newval) \
5246 do { \
5247 duk_tval *tv__dst; \
5248 duk_tval tv__tmp; \
5249 tv__dst = (tvptr_dst); \
5250 DUK_TVAL_SET_TVAL(&tv__tmp, tv__dst); \
5251 DUK_TVAL_SET_BOOLEAN(tv__dst, (newval)); \
5252 DUK_TVAL_DECREF((thr), &tv__tmp); /* side effects */ \
5253 } while (0)
5254
5255#define DUK_TVAL_SET_NUMBER_UPDREF_ALT0(thr, tvptr_dst, newval) \
5256 do { \
5257 duk_tval *tv__dst; \
5258 duk_tval tv__tmp; \
5259 tv__dst = (tvptr_dst); \
5260 DUK_TVAL_SET_TVAL(&tv__tmp, tv__dst); \
5261 DUK_TVAL_SET_NUMBER(tv__dst, (newval)); \
5262 DUK_TVAL_DECREF((thr), &tv__tmp); /* side effects */ \
5263 } while (0)
5264#define DUK_TVAL_SET_NUMBER_CHKFAST_UPDREF_ALT0(thr, tvptr_dst, newval) \
5265 do { \
5266 duk_tval *tv__dst; \
5267 duk_tval tv__tmp; \
5268 tv__dst = (tvptr_dst); \
5269 DUK_TVAL_SET_TVAL(&tv__tmp, tv__dst); \
5270 DUK_TVAL_SET_NUMBER_CHKFAST_FAST(tv__dst, (newval)); \
5271 DUK_TVAL_DECREF((thr), &tv__tmp); /* side effects */ \
5272 } while (0)
5273#define DUK_TVAL_SET_DOUBLE_UPDREF_ALT0(thr, tvptr_dst, newval) \
5274 do { \
5275 duk_tval *tv__dst; \
5276 duk_tval tv__tmp; \
5277 tv__dst = (tvptr_dst); \
5278 DUK_TVAL_SET_TVAL(&tv__tmp, tv__dst); \
5279 DUK_TVAL_SET_DOUBLE(tv__dst, (newval)); \
5280 DUK_TVAL_DECREF((thr), &tv__tmp); /* side effects */ \
5281 } while (0)
5282#define DUK_TVAL_SET_NAN_UPDREF_ALT0(thr, tvptr_dst) \
5283 do { \
5284 duk_tval *tv__dst; \
5285 duk_tval tv__tmp; \
5286 tv__dst = (tvptr_dst); \
5287 DUK_TVAL_SET_TVAL(&tv__tmp, tv__dst); \
5288 DUK_TVAL_SET_NAN(tv__dst); \
5289 DUK_TVAL_DECREF((thr), &tv__tmp); /* side effects */ \
5290 } while (0)
5291#if defined(DUK_USE_FASTINT)
5292#define DUK_TVAL_SET_I48_UPDREF_ALT0(thr, tvptr_dst, newval) \
5293 do { \
5294 duk_tval *tv__dst; \
5295 duk_tval tv__tmp; \
5296 tv__dst = (tvptr_dst); \
5297 DUK_TVAL_SET_TVAL(&tv__tmp, tv__dst); \
5298 DUK_TVAL_SET_I48(tv__dst, (newval)); \
5299 DUK_TVAL_DECREF((thr), &tv__tmp); /* side effects */ \
5300 } while (0)
5301#define DUK_TVAL_SET_I32_UPDREF_ALT0(thr, tvptr_dst, newval) \
5302 do { \
5303 duk_tval *tv__dst; \
5304 duk_tval tv__tmp; \
5305 tv__dst = (tvptr_dst); \
5306 DUK_TVAL_SET_TVAL(&tv__tmp, tv__dst); \
5307 DUK_TVAL_SET_I32(tv__dst, (newval)); \
5308 DUK_TVAL_DECREF((thr), &tv__tmp); /* side effects */ \
5309 } while (0)
5310#define DUK_TVAL_SET_U32_UPDREF_ALT0(thr, tvptr_dst, newval) \
5311 do { \
5312 duk_tval *tv__dst; \
5313 duk_tval tv__tmp; \
5314 tv__dst = (tvptr_dst); \
5315 DUK_TVAL_SET_TVAL(&tv__tmp, tv__dst); \
5316 DUK_TVAL_SET_U32(tv__dst, (newval)); \
5317 DUK_TVAL_DECREF((thr), &tv__tmp); /* side effects */ \
5318 } while (0)
5319#else
5320#define DUK_TVAL_SET_DOUBLE_CAST_UPDREF(thr, tvptr_dst, newval) \
5321 DUK_TVAL_SET_DOUBLE_UPDREF((thr), (tvptr_dst), (duk_double_t) (newval))
5322#endif /* DUK_USE_FASTINT */
5323
5324#define DUK_TVAL_SET_LIGHTFUNC_UPDREF_ALT0(thr, tvptr_dst, lf_v, lf_fp, lf_flags) \
5325 do { \
5326 duk_tval *tv__dst; \
5327 duk_tval tv__tmp; \
5328 tv__dst = (tvptr_dst); \
5329 DUK_TVAL_SET_TVAL(&tv__tmp, tv__dst); \
5330 DUK_TVAL_SET_LIGHTFUNC(tv__dst, (lf_v), (lf_fp), (lf_flags)); \
5331 DUK_TVAL_DECREF((thr), &tv__tmp); /* side effects */ \
5332 } while (0)
5333
5334#define DUK_TVAL_SET_STRING_UPDREF_ALT0(thr, tvptr_dst, newval) \
5335 do { \
5336 duk_tval *tv__dst; \
5337 duk_tval tv__tmp; \
5338 tv__dst = (tvptr_dst); \
5339 DUK_TVAL_SET_TVAL(&tv__tmp, tv__dst); \
5340 DUK_TVAL_SET_STRING(tv__dst, (newval)); \
5341 DUK_HSTRING_INCREF((thr), (newval)); \
5342 DUK_TVAL_DECREF((thr), &tv__tmp); /* side effects */ \
5343 } while (0)
5344
5345#define DUK_TVAL_SET_OBJECT_UPDREF_ALT0(thr, tvptr_dst, newval) \
5346 do { \
5347 duk_tval *tv__dst; \
5348 duk_tval tv__tmp; \
5349 tv__dst = (tvptr_dst); \
5350 DUK_TVAL_SET_TVAL(&tv__tmp, tv__dst); \
5351 DUK_TVAL_SET_OBJECT(tv__dst, (newval)); \
5352 DUK_HOBJECT_INCREF((thr), (newval)); \
5353 DUK_TVAL_DECREF((thr), &tv__tmp); /* side effects */ \
5354 } while (0)
5355
5356#define DUK_TVAL_SET_BUFFER_UPDREF_ALT0(thr, tvptr_dst, newval) \
5357 do { \
5358 duk_tval *tv__dst; \
5359 duk_tval tv__tmp; \
5360 tv__dst = (tvptr_dst); \
5361 DUK_TVAL_SET_TVAL(&tv__tmp, tv__dst); \
5362 DUK_TVAL_SET_BUFFER(tv__dst, (newval)); \
5363 DUK_HBUFFER_INCREF((thr), (newval)); \
5364 DUK_TVAL_DECREF((thr), &tv__tmp); /* side effects */ \
5365 } while (0)
5366
5367#define DUK_TVAL_SET_POINTER_UPDREF_ALT0(thr, tvptr_dst, newval) \
5368 do { \
5369 duk_tval *tv__dst; \
5370 duk_tval tv__tmp; \
5371 tv__dst = (tvptr_dst); \
5372 DUK_TVAL_SET_TVAL(&tv__tmp, tv__dst); \
5373 DUK_TVAL_SET_POINTER(tv__dst, (newval)); \
5374 DUK_TVAL_DECREF((thr), &tv__tmp); /* side effects */ \
5375 } while (0)
5376
5377/* DUK_TVAL_SET_TVAL_UPDREF() is used a lot in executor, property lookups,
5378 * etc, so it's very important for performance. Measure when changing.
5379 *
5380 * NOTE: the source and destination duk_tval pointers may be the same, and
5381 * the macros MUST deal with that correctly.
5382 */
5383
5384/* Original idiom used, minimal code size. */
5385#define DUK_TVAL_SET_TVAL_UPDREF_ALT0(thr, tvptr_dst, tvptr_src) \
5386 do { \
5387 duk_tval *tv__dst, *tv__src; \
5388 duk_tval tv__tmp; \
5389 tv__dst = (tvptr_dst); \
5390 tv__src = (tvptr_src); \
5391 DUK_TVAL_SET_TVAL(&tv__tmp, tv__dst); \
5392 DUK_TVAL_SET_TVAL(tv__dst, tv__src); \
5393 DUK_TVAL_INCREF((thr), tv__src); \
5394 DUK_TVAL_DECREF((thr), &tv__tmp); /* side effects */ \
5395 } while (0)
5396
5397/* Faster alternative: avoid making a temporary copy of tvptr_dst and use
5398 * fast incref/decref macros.
5399 */
5400#define DUK_TVAL_SET_TVAL_UPDREF_ALT1(thr, tvptr_dst, tvptr_src) \
5401 do { \
5402 duk_tval *tv__dst, *tv__src; \
5403 duk_heaphdr *h__obj; \
5404 tv__dst = (tvptr_dst); \
5405 tv__src = (tvptr_src); \
5406 DUK_TVAL_INCREF_FAST((thr), tv__src); \
5407 if (DUK_TVAL_NEEDS_REFCOUNT_UPDATE(tv__dst)) { \
5408 h__obj = DUK_TVAL_GET_HEAPHDR(tv__dst); \
5409 DUK_ASSERT(h__obj != NULL); \
5410 DUK_TVAL_SET_TVAL(tv__dst, tv__src); \
5411 DUK_HEAPHDR_DECREF_FAST((thr), h__obj); /* side effects */ \
5412 } else { \
5413 DUK_TVAL_SET_TVAL(tv__dst, tv__src); \
5414 } \
5415 } while (0)
5416
5417/* XXX: no optimized variants yet */
5418#define DUK_TVAL_SET_UNDEFINED_UPDREF DUK_TVAL_SET_UNDEFINED_UPDREF_ALT0
5419#define DUK_TVAL_SET_UNDEFINED_UPDREF_NORZ DUK_TVAL_SET_UNDEFINED_UPDREF_NORZ_ALT0
5420#define DUK_TVAL_SET_UNUSED_UPDREF DUK_TVAL_SET_UNUSED_UPDREF_ALT0
5421#define DUK_TVAL_SET_NULL_UPDREF DUK_TVAL_SET_NULL_UPDREF_ALT0
5422#define DUK_TVAL_SET_BOOLEAN_UPDREF DUK_TVAL_SET_BOOLEAN_UPDREF_ALT0
5423#define DUK_TVAL_SET_NUMBER_UPDREF DUK_TVAL_SET_NUMBER_UPDREF_ALT0
5424#define DUK_TVAL_SET_NUMBER_CHKFAST_UPDREF DUK_TVAL_SET_NUMBER_CHKFAST_UPDREF_ALT0
5425#define DUK_TVAL_SET_DOUBLE_UPDREF DUK_TVAL_SET_DOUBLE_UPDREF_ALT0
5426#define DUK_TVAL_SET_NAN_UPDREF DUK_TVAL_SET_NAN_UPDREF_ALT0
5427#if defined(DUK_USE_FASTINT)
5428#define DUK_TVAL_SET_I48_UPDREF DUK_TVAL_SET_I48_UPDREF_ALT0
5429#define DUK_TVAL_SET_I32_UPDREF DUK_TVAL_SET_I32_UPDREF_ALT0
5430#define DUK_TVAL_SET_U32_UPDREF DUK_TVAL_SET_U32_UPDREF_ALT0
5431#else
5432#define DUK_TVAL_SET_I48_UPDREF DUK_TVAL_SET_DOUBLE_CAST_UPDREF /* XXX: fast int-to-double */
5433#define DUK_TVAL_SET_I32_UPDREF DUK_TVAL_SET_DOUBLE_CAST_UPDREF
5434#define DUK_TVAL_SET_U32_UPDREF DUK_TVAL_SET_DOUBLE_CAST_UPDREF
5435#endif /* DUK_USE_FASTINT */
5436#define DUK_TVAL_SET_FASTINT_UPDREF DUK_TVAL_SET_I48_UPDREF /* convenience */
5437#define DUK_TVAL_SET_LIGHTFUNC_UPDREF DUK_TVAL_SET_LIGHTFUNC_UPDREF_ALT0
5438#define DUK_TVAL_SET_STRING_UPDREF DUK_TVAL_SET_STRING_UPDREF_ALT0
5439#define DUK_TVAL_SET_OBJECT_UPDREF DUK_TVAL_SET_OBJECT_UPDREF_ALT0
5440#define DUK_TVAL_SET_BUFFER_UPDREF DUK_TVAL_SET_BUFFER_UPDREF_ALT0
5441#define DUK_TVAL_SET_POINTER_UPDREF DUK_TVAL_SET_POINTER_UPDREF_ALT0
5442
5443#if defined(DUK_USE_FAST_REFCOUNT_DEFAULT)
5444/* Optimized for speed. */
5445#define DUK_TVAL_SET_TVAL_UPDREF DUK_TVAL_SET_TVAL_UPDREF_ALT1
5446#define DUK_TVAL_SET_TVAL_UPDREF_FAST DUK_TVAL_SET_TVAL_UPDREF_ALT1
5447#define DUK_TVAL_SET_TVAL_UPDREF_SLOW DUK_TVAL_SET_TVAL_UPDREF_ALT0
5448#else
5449/* Optimized for size. */
5450#define DUK_TVAL_SET_TVAL_UPDREF DUK_TVAL_SET_TVAL_UPDREF_ALT0
5451#define DUK_TVAL_SET_TVAL_UPDREF_FAST DUK_TVAL_SET_TVAL_UPDREF_ALT0
5452#define DUK_TVAL_SET_TVAL_UPDREF_SLOW DUK_TVAL_SET_TVAL_UPDREF_ALT0
5453#endif
5454
5455#else /* DUK_USE_REFERENCE_COUNTING */
5456
5457#define DUK_TVAL_NEEDS_REFCOUNT_UPDATE(tv) 0
5458#define DUK_HEAPHDR_NEEDS_REFCOUNT_UPDATE(h) 0
5459
5460#define DUK_TVAL_INCREF_FAST(thr, v) \
5461 do { \
5462 } while (0) /* nop */
5463#define DUK_TVAL_DECREF_FAST(thr, v) \
5464 do { \
5465 } while (0) /* nop */
5466#define DUK_TVAL_DECREF_NORZ_FAST(thr, v) \
5467 do { \
5468 } while (0) /* nop */
5469#define DUK_TVAL_INCREF_SLOW(thr, v) \
5470 do { \
5471 } while (0) /* nop */
5472#define DUK_TVAL_DECREF_SLOW(thr, v) \
5473 do { \
5474 } while (0) /* nop */
5475#define DUK_TVAL_DECREF_NORZ_SLOW(thr, v) \
5476 do { \
5477 } while (0) /* nop */
5478#define DUK_TVAL_INCREF(thr, v) \
5479 do { \
5480 } while (0) /* nop */
5481#define DUK_TVAL_DECREF(thr, v) \
5482 do { \
5483 } while (0) /* nop */
5484#define DUK_TVAL_DECREF_NORZ(thr, v) \
5485 do { \
5486 } while (0) /* nop */
5487#define DUK_HEAPHDR_INCREF_FAST(thr, h) \
5488 do { \
5489 } while (0) /* nop */
5490#define DUK_HEAPHDR_DECREF_FAST(thr, h) \
5491 do { \
5492 } while (0) /* nop */
5493#define DUK_HEAPHDR_DECREF_NORZ_FAST(thr, h) \
5494 do { \
5495 } while (0) /* nop */
5496#define DUK_HEAPHDR_INCREF_SLOW(thr, h) \
5497 do { \
5498 } while (0) /* nop */
5499#define DUK_HEAPHDR_DECREF_SLOW(thr, h) \
5500 do { \
5501 } while (0) /* nop */
5502#define DUK_HEAPHDR_DECREF_NORZ_SLOW(thr, h) \
5503 do { \
5504 } while (0) /* nop */
5505#define DUK_HEAPHDR_INCREF(thr, h) \
5506 do { \
5507 } while (0) /* nop */
5508#define DUK_HEAPHDR_DECREF(thr, h) \
5509 do { \
5510 } while (0) /* nop */
5511#define DUK_HEAPHDR_DECREF_NORZ(thr, h) \
5512 do { \
5513 } while (0) /* nop */
5514#define DUK_HSTRING_INCREF_FAST(thr, h) \
5515 do { \
5516 } while (0) /* nop */
5517#define DUK_HSTRING_DECREF_FAST(thr, h) \
5518 do { \
5519 } while (0) /* nop */
5520#define DUK_HSTRING_DECREF_NORZ_FAST(thr, h) \
5521 do { \
5522 } while (0) /* nop */
5523#define DUK_HSTRING_INCREF_SLOW(thr, h) \
5524 do { \
5525 } while (0) /* nop */
5526#define DUK_HSTRING_DECREF_SLOW(thr, h) \
5527 do { \
5528 } while (0) /* nop */
5529#define DUK_HSTRING_DECREF_NORZ_SLOW(thr, h) \
5530 do { \
5531 } while (0) /* nop */
5532#define DUK_HSTRING_INCREF(thr, h) \
5533 do { \
5534 } while (0) /* nop */
5535#define DUK_HSTRING_DECREF(thr, h) \
5536 do { \
5537 } while (0) /* nop */
5538#define DUK_HSTRING_DECREF_NORZ(thr, h) \
5539 do { \
5540 } while (0) /* nop */
5541#define DUK_HOBJECT_INCREF_FAST(thr, h) \
5542 do { \
5543 } while (0) /* nop */
5544#define DUK_HOBJECT_DECREF_FAST(thr, h) \
5545 do { \
5546 } while (0) /* nop */
5547#define DUK_HOBJECT_DECREF_NORZ_FAST(thr, h) \
5548 do { \
5549 } while (0) /* nop */
5550#define DUK_HOBJECT_INCREF_SLOW(thr, h) \
5551 do { \
5552 } while (0) /* nop */
5553#define DUK_HOBJECT_DECREF_SLOW(thr, h) \
5554 do { \
5555 } while (0) /* nop */
5556#define DUK_HOBJECT_DECREF_NORZ_SLOW(thr, h) \
5557 do { \
5558 } while (0) /* nop */
5559#define DUK_HOBJECT_INCREF(thr, h) \
5560 do { \
5561 } while (0) /* nop */
5562#define DUK_HOBJECT_DECREF(thr, h) \
5563 do { \
5564 } while (0) /* nop */
5565#define DUK_HOBJECT_DECREF_NORZ(thr, h) \
5566 do { \
5567 } while (0) /* nop */
5568#define DUK_HBUFFER_INCREF_FAST(thr, h) \
5569 do { \
5570 } while (0) /* nop */
5571#define DUK_HBUFFER_DECREF_FAST(thr, h) \
5572 do { \
5573 } while (0) /* nop */
5574#define DUK_HBUFFER_DECREF_NORZ_FAST(thr, h) \
5575 do { \
5576 } while (0) /* nop */
5577#define DUK_HBUFFER_INCREF_SLOW(thr, h) \
5578 do { \
5579 } while (0) /* nop */
5580#define DUK_HBUFFER_DECREF_SLOW(thr, h) \
5581 do { \
5582 } while (0) /* nop */
5583#define DUK_HBUFFER_DECREF_NORZ_SLOW(thr, h) \
5584 do { \
5585 } while (0) /* nop */
5586#define DUK_HBUFFER_INCREF(thr, h) \
5587 do { \
5588 } while (0) /* nop */
5589#define DUK_HBUFFER_DECREF(thr, h) \
5590 do { \
5591 } while (0) /* nop */
5592#define DUK_HBUFFER_DECREF_NORZ(thr, h) \
5593 do { \
5594 } while (0) /* nop */
5595
5596#define DUK_HCOMPFUNC_INCREF(thr, h) \
5597 do { \
5598 } while (0) /* nop */
5599#define DUK_HCOMPFUNC_DECREF(thr, h) \
5600 do { \
5601 } while (0) /* nop */
5602#define DUK_HCOMPFUNC_DECREF_NORZ(thr, h) \
5603 do { \
5604 } while (0) /* nop */
5605#define DUK_HNATFUNC_INCREF(thr, h) \
5606 do { \
5607 } while (0) /* nop */
5608#define DUK_HNATFUNC_DECREF(thr, h) \
5609 do { \
5610 } while (0) /* nop */
5611#define DUK_HNATFUNC_DECREF_NORZ(thr, h) \
5612 do { \
5613 } while (0) /* nop */
5614#define DUK_HBUFOBJ_INCREF(thr, h) \
5615 do { \
5616 } while (0) /* nop */
5617#define DUK_HBUFOBJ_DECREF(thr, h) \
5618 do { \
5619 } while (0) /* nop */
5620#define DUK_HBUFOBJ_DECREF_NORZ(thr, h) \
5621 do { \
5622 } while (0) /* nop */
5623#define DUK_HTHREAD_INCREF(thr, h) \
5624 do { \
5625 } while (0) /* nop */
5626#define DUK_HTHREAD_DECREF(thr, h) \
5627 do { \
5628 } while (0) /* nop */
5629#define DUK_HTHREAD_DECREF_NORZ(thr, h) \
5630 do { \
5631 } while (0) /* nop */
5632#define DUK_HOBJECT_INCREF_ALLOWNULL(thr, h) \
5633 do { \
5634 } while (0) /* nop */
5635#define DUK_HOBJECT_DECREF_ALLOWNULL(thr, h) \
5636 do { \
5637 } while (0) /* nop */
5638#define DUK_HOBJECT_DECREF_NORZ_ALLOWNULL(thr, h) \
5639 do { \
5640 } while (0) /* nop */
5641#define DUK_HBUFFER_INCREF_ALLOWNULL(thr, h) \
5642 do { \
5643 } while (0) /* nop */
5644#define DUK_HBUFFER_DECREF_ALLOWNULL(thr, h) \
5645 do { \
5646 } while (0) /* nop */
5647#define DUK_HBUFFER_DECREF_NORZ_ALLOWNULL(thr, h) \
5648 do { \
5649 } while (0) /* nop */
5650
5651#define DUK_REFZERO_CHECK_FAST(thr) \
5652 do { \
5653 } while (0) /* nop */
5654#define DUK_REFZERO_CHECK_SLOW(thr) \
5655 do { \
5656 } while (0) /* nop */
5657
5658#define DUK_TVAL_SET_UNDEFINED_UPDREF_ALT0(thr, tvptr_dst) \
5659 do { \
5660 duk_tval *tv__dst; \
5661 tv__dst = (tvptr_dst); \
5662 DUK_TVAL_SET_UNDEFINED(tv__dst); \
5663 DUK_UNREF((thr)); \
5664 } while (0)
5665
5666#define DUK_TVAL_SET_UNUSED_UPDREF_ALT0(thr, tvptr_dst) \
5667 do { \
5668 duk_tval *tv__dst; \
5669 tv__dst = (tvptr_dst); \
5670 DUK_TVAL_SET_UNUSED(tv__dst); \
5671 DUK_UNREF((thr)); \
5672 } while (0)
5673
5674#define DUK_TVAL_SET_NULL_UPDREF_ALT0(thr, tvptr_dst) \
5675 do { \
5676 duk_tval *tv__dst; \
5677 tv__dst = (tvptr_dst); \
5678 DUK_TVAL_SET_NULL(tv__dst); \
5679 DUK_UNREF((thr)); \
5680 } while (0)
5681
5682#define DUK_TVAL_SET_BOOLEAN_UPDREF_ALT0(thr, tvptr_dst, newval) \
5683 do { \
5684 duk_tval *tv__dst; \
5685 tv__dst = (tvptr_dst); \
5686 DUK_TVAL_SET_BOOLEAN(tv__dst, (newval)); \
5687 DUK_UNREF((thr)); \
5688 } while (0)
5689
5690#define DUK_TVAL_SET_NUMBER_UPDREF_ALT0(thr, tvptr_dst, newval) \
5691 do { \
5692 duk_tval *tv__dst; \
5693 tv__dst = (tvptr_dst); \
5694 DUK_TVAL_SET_NUMBER(tv__dst, (newval)); \
5695 DUK_UNREF((thr)); \
5696 } while (0)
5697#define DUK_TVAL_SET_NUMBER_CHKFAST_UPDREF_ALT0(thr, tvptr_dst, newval) \
5698 do { \
5699 duk_tval *tv__dst; \
5700 tv__dst = (tvptr_dst); \
5701 DUK_TVAL_SET_NUMBER_CHKFAST_FAST(tv__dst, (newval)); \
5702 DUK_UNREF((thr)); \
5703 } while (0)
5704#define DUK_TVAL_SET_DOUBLE_UPDREF_ALT0(thr, tvptr_dst, newval) \
5705 do { \
5706 duk_tval *tv__dst; \
5707 tv__dst = (tvptr_dst); \
5708 DUK_TVAL_SET_DOUBLE(tv__dst, (newval)); \
5709 DUK_UNREF((thr)); \
5710 } while (0)
5711#define DUK_TVAL_SET_NAN_UPDREF_ALT0(thr, tvptr_dst) \
5712 do { \
5713 duk_tval *tv__dst; \
5714 tv__dst = (tvptr_dst); \
5715 DUK_TVAL_SET_NAN(tv__dst); \
5716 DUK_UNREF((thr)); \
5717 } while (0)
5718#if defined(DUK_USE_FASTINT)
5719#define DUK_TVAL_SET_I48_UPDREF_ALT0(thr, tvptr_dst, newval) \
5720 do { \
5721 duk_tval *tv__dst; \
5722 tv__dst = (tvptr_dst); \
5723 DUK_TVAL_SET_I48(tv__dst, (newval)); \
5724 DUK_UNREF((thr)); \
5725 } while (0)
5726#define DUK_TVAL_SET_I32_UPDREF_ALT0(thr, tvptr_dst, newval) \
5727 do { \
5728 duk_tval *tv__dst; \
5729 tv__dst = (tvptr_dst); \
5730 DUK_TVAL_SET_I32(tv__dst, (newval)); \
5731 DUK_UNREF((thr)); \
5732 } while (0)
5733#define DUK_TVAL_SET_U32_UPDREF_ALT0(thr, tvptr_dst, newval) \
5734 do { \
5735 duk_tval *tv__dst; \
5736 tv__dst = (tvptr_dst); \
5737 DUK_TVAL_SET_U32(tv__dst, (newval)); \
5738 DUK_UNREF((thr)); \
5739 } while (0)
5740#else
5741#define DUK_TVAL_SET_DOUBLE_CAST_UPDREF(thr, tvptr_dst, newval) \
5742 DUK_TVAL_SET_DOUBLE_UPDREF((thr), (tvptr_dst), (duk_double_t) (newval))
5743#endif /* DUK_USE_FASTINT */
5744
5745#define DUK_TVAL_SET_LIGHTFUNC_UPDREF_ALT0(thr, tvptr_dst, lf_v, lf_fp, lf_flags) \
5746 do { \
5747 duk_tval *tv__dst; \
5748 tv__dst = (tvptr_dst); \
5749 DUK_TVAL_SET_LIGHTFUNC(tv__dst, (lf_v), (lf_fp), (lf_flags)); \
5750 DUK_UNREF((thr)); \
5751 } while (0)
5752
5753#define DUK_TVAL_SET_STRING_UPDREF_ALT0(thr, tvptr_dst, newval) \
5754 do { \
5755 duk_tval *tv__dst; \
5756 tv__dst = (tvptr_dst); \
5757 DUK_TVAL_SET_STRING(tv__dst, (newval)); \
5758 DUK_UNREF((thr)); \
5759 } while (0)
5760
5761#define DUK_TVAL_SET_OBJECT_UPDREF_ALT0(thr, tvptr_dst, newval) \
5762 do { \
5763 duk_tval *tv__dst; \
5764 tv__dst = (tvptr_dst); \
5765 DUK_TVAL_SET_OBJECT(tv__dst, (newval)); \
5766 DUK_UNREF((thr)); \
5767 } while (0)
5768
5769#define DUK_TVAL_SET_BUFFER_UPDREF_ALT0(thr, tvptr_dst, newval) \
5770 do { \
5771 duk_tval *tv__dst; \
5772 tv__dst = (tvptr_dst); \
5773 DUK_TVAL_SET_BUFFER(tv__dst, (newval)); \
5774 DUK_UNREF((thr)); \
5775 } while (0)
5776
5777#define DUK_TVAL_SET_POINTER_UPDREF_ALT0(thr, tvptr_dst, newval) \
5778 do { \
5779 duk_tval *tv__dst; \
5780 tv__dst = (tvptr_dst); \
5781 DUK_TVAL_SET_POINTER(tv__dst, (newval)); \
5782 DUK_UNREF((thr)); \
5783 } while (0)
5784
5785#define DUK_TVAL_SET_TVAL_UPDREF_ALT0(thr, tvptr_dst, tvptr_src) \
5786 do { \
5787 duk_tval *tv__dst, *tv__src; \
5788 tv__dst = (tvptr_dst); \
5789 tv__src = (tvptr_src); \
5790 DUK_TVAL_SET_TVAL(tv__dst, tv__src); \
5791 DUK_UNREF((thr)); \
5792 } while (0)
5793
5794#define DUK_TVAL_SET_UNDEFINED_UPDREF DUK_TVAL_SET_UNDEFINED_UPDREF_ALT0
5795#define DUK_TVAL_SET_UNDEFINED_UPDREF_NORZ DUK_TVAL_SET_UNDEFINED_UPDREF_ALT0
5796#define DUK_TVAL_SET_UNUSED_UPDREF DUK_TVAL_SET_UNUSED_UPDREF_ALT0
5797#define DUK_TVAL_SET_NULL_UPDREF DUK_TVAL_SET_NULL_UPDREF_ALT0
5798#define DUK_TVAL_SET_BOOLEAN_UPDREF DUK_TVAL_SET_BOOLEAN_UPDREF_ALT0
5799#define DUK_TVAL_SET_NUMBER_UPDREF DUK_TVAL_SET_NUMBER_UPDREF_ALT0
5800#define DUK_TVAL_SET_NUMBER_CHKFAST_UPDREF DUK_TVAL_SET_NUMBER_CHKFAST_UPDREF_ALT0
5801#define DUK_TVAL_SET_DOUBLE_UPDREF DUK_TVAL_SET_DOUBLE_UPDREF_ALT0
5802#define DUK_TVAL_SET_NAN_UPDREF DUK_TVAL_SET_NAN_UPDREF_ALT0
5803#if defined(DUK_USE_FASTINT)
5804#define DUK_TVAL_SET_I48_UPDREF DUK_TVAL_SET_I48_UPDREF_ALT0
5805#define DUK_TVAL_SET_I32_UPDREF DUK_TVAL_SET_I32_UPDREF_ALT0
5806#define DUK_TVAL_SET_U32_UPDREF DUK_TVAL_SET_U32_UPDREF_ALT0
5807#else
5808#define DUK_TVAL_SET_I48_UPDREF DUK_TVAL_SET_DOUBLE_CAST_UPDREF /* XXX: fast-int-to-double */
5809#define DUK_TVAL_SET_I32_UPDREF DUK_TVAL_SET_DOUBLE_CAST_UPDREF
5810#define DUK_TVAL_SET_U32_UPDREF DUK_TVAL_SET_DOUBLE_CAST_UPDREF
5811#endif /* DUK_USE_FASTINT */
5812#define DUK_TVAL_SET_FASTINT_UPDREF DUK_TVAL_SET_I48_UPDREF /* convenience */
5813#define DUK_TVAL_SET_LIGHTFUNC_UPDREF DUK_TVAL_SET_LIGHTFUNC_UPDREF_ALT0
5814#define DUK_TVAL_SET_STRING_UPDREF DUK_TVAL_SET_STRING_UPDREF_ALT0
5815#define DUK_TVAL_SET_OBJECT_UPDREF DUK_TVAL_SET_OBJECT_UPDREF_ALT0
5816#define DUK_TVAL_SET_BUFFER_UPDREF DUK_TVAL_SET_BUFFER_UPDREF_ALT0
5817#define DUK_TVAL_SET_POINTER_UPDREF DUK_TVAL_SET_POINTER_UPDREF_ALT0
5818
5819#define DUK_TVAL_SET_TVAL_UPDREF DUK_TVAL_SET_TVAL_UPDREF_ALT0
5820#define DUK_TVAL_SET_TVAL_UPDREF_FAST DUK_TVAL_SET_TVAL_UPDREF_ALT0
5821#define DUK_TVAL_SET_TVAL_UPDREF_SLOW DUK_TVAL_SET_TVAL_UPDREF_ALT0
5822
5823#endif /* DUK_USE_REFERENCE_COUNTING */
5824
5825/*
5826 * Some convenience macros that don't have optimized implementations now.
5827 */
5828
5829#define DUK_TVAL_SET_TVAL_UPDREF_NORZ(thr, tv_dst, tv_src) \
5830 do { \
5831 duk_hthread *duk__thr = (thr); \
5832 duk_tval *duk__dst = (tv_dst); \
5833 duk_tval *duk__src = (tv_src); \
5834 DUK_UNREF(duk__thr); \
5835 DUK_TVAL_DECREF_NORZ(thr, duk__dst); \
5836 DUK_TVAL_SET_TVAL(duk__dst, duk__src); \
5837 DUK_TVAL_INCREF(thr, duk__dst); \
5838 } while (0)
5839
5840#define DUK_TVAL_SET_U32_UPDREF_NORZ(thr, tv_dst, val) \
5841 do { \
5842 duk_hthread *duk__thr = (thr); \
5843 duk_tval *duk__dst = (tv_dst); \
5844 duk_uint32_t duk__val = (duk_uint32_t) (val); \
5845 DUK_UNREF(duk__thr); \
5846 DUK_TVAL_DECREF_NORZ(thr, duk__dst); \
5847 DUK_TVAL_SET_U32(duk__dst, duk__val); \
5848 } while (0)
5849
5850/*
5851 * Prototypes
5852 */
5853
5854#if defined(DUK_USE_REFERENCE_COUNTING)
5855#if defined(DUK_USE_FINALIZER_SUPPORT)
5858#endif
5861#if 0 /* Not needed: fast path handles inline; slow path uses duk_heaphdr_decref() which is needed anyway. */
5862DUK_INTERNAL_DECL void duk_hstring_decref(duk_hthread *thr, duk_hstring *h);
5863DUK_INTERNAL_DECL void duk_hstring_decref_norz(duk_hthread *thr, duk_hstring *h);
5864DUK_INTERNAL_DECL void duk_hbuffer_decref(duk_hthread *thr, duk_hbuffer *h);
5865DUK_INTERNAL_DECL void duk_hbuffer_decref_norz(duk_hthread *thr, duk_hbuffer *h);
5866DUK_INTERNAL_DECL void duk_hobject_decref(duk_hthread *thr, duk_hobject *h);
5867DUK_INTERNAL_DECL void duk_hobject_decref_norz(duk_hthread *thr, duk_hobject *h);
5868#endif
5871#if defined(DUK_USE_FAST_REFCOUNT_DEFAULT)
5872DUK_INTERNAL_DECL void duk_hstring_refzero(duk_hthread *thr, duk_hstring *h); /* no 'norz' variant */
5873DUK_INTERNAL_DECL void duk_hbuffer_refzero(duk_hthread *thr, duk_hbuffer *h); /* no 'norz' variant */
5876#else
5877DUK_INTERNAL_DECL void duk_tval_incref(duk_tval *tv);
5878DUK_INTERNAL_DECL void duk_tval_decref(duk_hthread *thr, duk_tval *tv);
5879DUK_INTERNAL_DECL void duk_tval_decref_norz(duk_hthread *thr, duk_tval *tv);
5880DUK_INTERNAL_DECL void duk_heaphdr_incref(duk_heaphdr *h);
5881DUK_INTERNAL_DECL void duk_heaphdr_decref(duk_hthread *thr, duk_heaphdr *h);
5882DUK_INTERNAL_DECL void duk_heaphdr_decref_norz(duk_hthread *thr, duk_heaphdr *h);
5883#endif
5884#else /* DUK_USE_REFERENCE_COUNTING */
5885/* no refcounting */
5886#endif /* DUK_USE_REFERENCE_COUNTING */
5887
5888#endif /* DUK_REFCOUNT_H_INCLUDED */
5889/* #include duk_api_internal.h */
5890/*
5891 * Internal API calls which have (stack and other) semantics similar
5892 * to the public API.
5893 */
5894
5895#if !defined(DUK_API_INTERNAL_H_INCLUDED)
5896#define DUK_API_INTERNAL_H_INCLUDED
5897
5898/* Inline macro helpers. */
5899#if defined(DUK_USE_PREFER_SIZE)
5900#define DUK_INLINE_PERF
5901#define DUK_ALWAYS_INLINE_PERF
5902#define DUK_NOINLINE_PERF
5903#else
5904#define DUK_INLINE_PERF DUK_INLINE
5905#define DUK_ALWAYS_INLINE_PERF DUK_ALWAYS_INLINE
5906#define DUK_NOINLINE_PERF DUK_NOINLINE
5907#endif
5908
5909/* Inline macro helpers, for bytecode executor. */
5910#if defined(DUK_USE_EXEC_PREFER_SIZE)
5911#define DUK_EXEC_INLINE_PERF
5912#define DUK_EXEC_ALWAYS_INLINE_PERF
5913#define DUK_EXEC_NOINLINE_PERF
5914#else
5915#define DUK_EXEC_INLINE_PERF DUK_INLINE
5916#define DUK_EXEC_ALWAYS_INLINE_PERF DUK_ALWAYS_INLINE
5917#define DUK_EXEC_NOINLINE_PERF DUK_NOINLINE
5918#endif
5919
5920/* duk_push_sprintf constants */
5921#define DUK_PUSH_SPRINTF_INITIAL_SIZE 256L
5922#define DUK_PUSH_SPRINTF_SANITY_LIMIT (1L * 1024L * 1024L * 1024L)
5923
5924/* Flag ORed to err_code to indicate __FILE__ / __LINE__ is not
5925 * blamed as source of error for error fileName / lineNumber.
5926 */
5927#define DUK_ERRCODE_FLAG_NOBLAME_FILELINE (1L << 24)
5928
5929/* Current convention is to use duk_size_t for value stack sizes and global indices,
5930 * and duk_idx_t for local frame indices.
5931 */
5935
5937
5939
5942
5946/* duk_dup_m1() would be same as duk_dup_top() */
5950
5955
5958
5959#if defined(DUK_USE_VERBOSE_ERRORS) && defined(DUK_USE_PARANOID_ERRORS)
5960DUK_INTERNAL_DECL const char *duk_get_type_name(duk_hthread *thr, duk_idx_t idx);
5961#endif
5963
5968
5969/* Push the current 'this' binding; throw TypeError if binding is not object
5970 * coercible (CheckObjectCoercible).
5971 */
5973
5974/* duk_push_this() + CheckObjectCoercible() + duk_to_object() */
5976
5977/* duk_push_this() + CheckObjectCoercible() + duk_to_string() */
5979
5981
5982/* Get a borrowed duk_tval pointer to the current 'this' binding. Caller must
5983 * make sure there's an active callstack entry. Note that the returned pointer
5984 * is unstable with regards to side effects.
5985 */
5987
5988/* XXX: add fastint support? */
5989#define duk_push_u64(thr, val) duk_push_number((thr), (duk_double_t) (val))
5990#define duk_push_i64(thr, val) duk_push_number((thr), (duk_double_t) (val))
5991
5992/* duk_push_(u)int() is guaranteed to support at least (un)signed 32-bit range */
5993#define duk_push_u32(thr, val) duk_push_uint((thr), (duk_uint_t) (val))
5994#define duk_push_i32(thr, val) duk_push_int((thr), (duk_int_t) (val))
5995
5996/* sometimes stack and array indices need to go on the stack */
5997#define duk_push_idx(thr, val) duk_push_int((thr), (duk_int_t) (val))
5998#define duk_push_uarridx(thr, val) duk_push_uint((thr), (duk_uint_t) (val))
5999#define duk_push_size_t(thr, val) duk_push_uint((thr), (duk_uint_t) (val)) /* XXX: assumed to fit for now */
6000
6002
6004
6006
6015
6017 duk_idx_t idx,
6018 duk_size_t *out_size,
6019 void *def_ptr,
6020 duk_size_t def_len,
6021 duk_bool_t throw_flag,
6022 duk_bool_t *out_isbuffer);
6023
6025
6029#define duk_require_hobject_promote_lfunc(thr, idx) duk_require_hobject_promote_mask((thr), (idx), DUK_TYPE_MASK_LIGHTFUNC)
6030#define duk_get_hobject_promote_lfunc(thr, idx) duk_get_hobject_promote_mask((thr), (idx), DUK_TYPE_MASK_LIGHTFUNC)
6031
6032#if 0 /*unused*/
6033DUK_INTERNAL_DECL void *duk_get_voidptr(duk_hthread *thr, duk_idx_t idx);
6034#endif
6035
6041
6043
6047
6049
6052
6054
6055#if defined(DUK_USE_DEBUGGER_SUPPORT) /* only needed by debugger for now */
6056DUK_INTERNAL_DECL duk_hstring *duk_safe_to_hstring(duk_hthread *thr, duk_idx_t idx);
6057#endif
6059
6061 duk_idx_t idx,
6062 duk_int_t minval,
6063 duk_int_t maxval,
6064 duk_bool_t *out_clamped); /* out_clamped=NULL, RangeError if outside range */
6067#if defined(DUK_USE_BUFFEROBJECT_SUPPORT)
6069#endif
6071
6081
6083
6089#define duk_push_hthread(thr, h) duk_push_hobject((thr), (duk_hobject *) (h))
6090#define duk_push_hnatfunc(thr, h) duk_push_hobject((thr), (duk_hobject *) (h))
6093 duk_uint_t hobject_flags_and_class,
6094 duk_small_int_t prototype_bidx);
6096 duk_uint_t hobject_flags_and_class,
6097 duk_hobject *proto);
6102
6103/* XXX: duk_push_harray() and duk_push_hcompfunc() are inconsistent with
6104 * duk_push_hobject() etc which don't create a new value.
6105 */
6109
6110DUK_INTERNAL_DECL void duk_push_string_funcptr(duk_hthread *thr, duk_uint8_t *ptr, duk_size_t sz);
6114#if 0 /* not used yet */
6115DUK_INTERNAL_DECL void duk_push_hnatfunc_name(duk_hthread *thr, duk_hnatfunc *h);
6116#endif
6117#if defined(DUK_USE_BUFFEROBJECT_SUPPORT)
6119 duk_uint_t hobject_flags_and_class,
6120 duk_small_int_t prototype_bidx);
6121#endif
6122
6125
6129
6130/* The duk_xxx_prop_stridx_short() variants expect their arguments to be short
6131 * enough to be packed into a single 32-bit integer argument. Argument limits
6132 * vary per call; typically 16 bits are assigned to the signed value stack index
6133 * and the stridx. In practice these work well for footprint with constant
6134 * arguments and such call sites are also easiest to verify to be correct.
6135 */
6136
6139#define duk_get_prop_stridx_short(thr, obj_idx, stridx) \
6140 (DUK_ASSERT_EXPR((duk_int_t) (obj_idx) >= -0x8000L && (duk_int_t) (obj_idx) <= 0x7fffL), \
6141 DUK_ASSERT_EXPR((duk_int_t) (stridx) >= 0 && (duk_int_t) (stridx) <= 0xffffL), \
6142 duk_get_prop_stridx_short_raw((thr), (((duk_uint_t) (obj_idx)) << 16) + ((duk_uint_t) (stridx))))
6144 duk_idx_t obj_idx,
6145 duk_small_uint_t stridx,
6146 duk_bool_t *out_has_prop); /* [] -> [] */
6147
6151#define duk_xget_owndataprop_stridx_short(thr, obj_idx, stridx) \
6152 (DUK_ASSERT_EXPR((duk_int_t) (obj_idx) >= -0x8000L && (duk_int_t) (obj_idx) <= 0x7fffL), \
6153 DUK_ASSERT_EXPR((duk_int_t) (stridx) >= 0 && (duk_int_t) (stridx) <= 0xffffL), \
6154 duk_xget_owndataprop_stridx_short_raw((thr), (((duk_uint_t) (obj_idx)) << 16) + ((duk_uint_t) (stridx))))
6155
6158#define duk_put_prop_stridx_short(thr, obj_idx, stridx) \
6159 (DUK_ASSERT_EXPR((duk_int_t) (obj_idx) >= -0x8000L && (duk_int_t) (obj_idx) <= 0x7fffL), \
6160 DUK_ASSERT_EXPR((duk_int_t) (stridx) >= 0 && (duk_int_t) (stridx) <= 0xffffL), \
6161 duk_put_prop_stridx_short_raw((thr), (((duk_uint_t) (obj_idx)) << 16) + ((duk_uint_t) (stridx))))
6162
6164#if 0 /* Too few call sites to be useful. */
6165DUK_INTERNAL_DECL duk_bool_t duk_del_prop_stridx_short_raw(duk_hthread *thr, duk_uint_t packed_args);
6166#define duk_del_prop_stridx_short(thr, obj_idx, stridx) \
6167 (DUK_ASSERT_EXPR((obj_idx) >= -0x8000L && (obj_idx) <= 0x7fffL), \
6168 DUK_ASSERT_EXPR((stridx) >= 0 && (stridx) <= 0xffffL), \
6169 duk_del_prop_stridx_short_raw((thr), (((duk_uint_t) (obj_idx)) << 16) + ((duk_uint_t) (stridx))))
6170#endif
6171#define duk_del_prop_stridx_short(thr, obj_idx, stridx) duk_del_prop_stridx((thr), (obj_idx), (stridx))
6172
6174#if 0 /* Too few call sites to be useful. */
6175DUK_INTERNAL_DECL duk_bool_t duk_has_prop_stridx_short_raw(duk_hthread *thr, duk_uint_t packed_args);
6176#define duk_has_prop_stridx_short(thr, obj_idx, stridx) \
6177 (DUK_ASSERT_EXPR((obj_idx) >= -0x8000L && (obj_idx) <= 0x7fffL), \
6178 DUK_ASSERT_EXPR((stridx) >= 0 && (stridx) <= 0xffffL), \
6179 duk_has_prop_stridx_short_raw((thr), (((duk_uint_t) (obj_idx)) << 16) + ((duk_uint_t) (stridx))))
6180#endif
6181#define duk_has_prop_stridx_short(thr, obj_idx, stridx) duk_has_prop_stridx((thr), (obj_idx), (stridx))
6182
6183DUK_INTERNAL_DECL void duk_xdef_prop(duk_hthread *thr, duk_idx_t obj_idx, duk_small_uint_t desc_flags); /* [key val] -> [] */
6184
6186 duk_idx_t obj_idx,
6187 duk_uarridx_t arr_idx,
6188 duk_small_uint_t desc_flags); /* [val] -> [] */
6189
6190/* XXX: Because stridx and desc_flags have a limited range, this call could
6191 * always pack stridx and desc_flags into a single argument.
6192 */
6194 duk_idx_t obj_idx,
6195 duk_small_uint_t stridx,
6196 duk_small_uint_t desc_flags); /* [val] -> [] */
6198#define duk_xdef_prop_stridx_short(thr, obj_idx, stridx, desc_flags) \
6199 (DUK_ASSERT_EXPR((duk_int_t) (obj_idx) >= -0x80L && (duk_int_t) (obj_idx) <= 0x7fL), \
6200 DUK_ASSERT_EXPR((duk_int_t) (stridx) >= 0 && (duk_int_t) (stridx) <= 0xffffL), \
6201 DUK_ASSERT_EXPR((duk_int_t) (desc_flags) >= 0 && (duk_int_t) (desc_flags) <= 0xffL), \
6202 duk_xdef_prop_stridx_short_raw((thr), \
6203 (((duk_uint_t) (obj_idx)) << 24) + (((duk_uint_t) (stridx)) << 8) + \
6204 (duk_uint_t) (desc_flags)))
6205
6206#define duk_xdef_prop_wec(thr, obj_idx) duk_xdef_prop((thr), (obj_idx), DUK_PROPDESC_FLAGS_WEC)
6207#define duk_xdef_prop_index_wec(thr, obj_idx, arr_idx) duk_xdef_prop_index((thr), (obj_idx), (arr_idx), DUK_PROPDESC_FLAGS_WEC)
6208#define duk_xdef_prop_stridx_wec(thr, obj_idx, stridx) duk_xdef_prop_stridx((thr), (obj_idx), (stridx), DUK_PROPDESC_FLAGS_WEC)
6209#define duk_xdef_prop_stridx_short_wec(thr, obj_idx, stridx) \
6210 duk_xdef_prop_stridx_short((thr), (obj_idx), (stridx), DUK_PROPDESC_FLAGS_WEC)
6211
6212#if 0 /*unused*/
6213DUK_INTERNAL_DECL void duk_xdef_prop_stridx_builtin(duk_hthread *thr, duk_idx_t obj_idx, duk_small_uint_t stridx, duk_small_int_t builtin_idx, duk_small_uint_t desc_flags); /* [] -> [] */
6214#endif
6215
6217
6219
6222#if 0
6223DUK_INTERNAL_DECL void duk_unpack(duk_hthread *thr);
6224#endif
6225
6227
6229
6232
6242
6244
6246
6249
6251
6253
6254#if defined(DUK_USE_SYMBOL_BUILTIN)
6256#endif
6257
6259
6260/* Raw internal valstack access macros: access is unsafe so call site
6261 * must have a guarantee that the index is valid. When that is the case,
6262 * using these macro results in faster and smaller code than duk_get_tval().
6263 * Both 'ctx' and 'idx' are evaluted multiple times, but only for asserts.
6264 */
6265#define DUK_ASSERT_VALID_NEGIDX(thr, idx) \
6266 (DUK_ASSERT_EXPR((duk_int_t) (idx) < 0), DUK_ASSERT_EXPR(duk_is_valid_index((thr), (idx))))
6267#define DUK_ASSERT_VALID_POSIDX(thr, idx) \
6268 (DUK_ASSERT_EXPR((duk_int_t) (idx) >= 0), DUK_ASSERT_EXPR(duk_is_valid_index((thr), (idx))))
6269#define DUK_GET_TVAL_NEGIDX(thr, idx) (DUK_ASSERT_VALID_NEGIDX((thr), (idx)), ((duk_hthread *) (thr))->valstack_top + (idx))
6270#define DUK_GET_TVAL_POSIDX(thr, idx) (DUK_ASSERT_VALID_POSIDX((thr), (idx)), ((duk_hthread *) (thr))->valstack_bottom + (idx))
6271#define DUK_GET_HOBJECT_NEGIDX(thr, idx) \
6272 (DUK_ASSERT_VALID_NEGIDX((thr), (idx)), DUK_TVAL_GET_OBJECT(((duk_hthread *) (thr))->valstack_top + (idx)))
6273#define DUK_GET_HOBJECT_POSIDX(thr, idx) \
6274 (DUK_ASSERT_VALID_POSIDX((thr), (idx)), DUK_TVAL_GET_OBJECT(((duk_hthread *) (thr))->valstack_bottom + (idx)))
6275
6276#define DUK_GET_THIS_TVAL_PTR(thr) (DUK_ASSERT_EXPR((thr)->valstack_bottom > (thr)->valstack), (thr)->valstack_bottom - 1)
6277
6281
6282#endif /* DUK_API_INTERNAL_H_INCLUDED */
6283/* #include duk_hstring.h */
6284/*
6285 * Heap string representation.
6286 *
6287 * Strings are byte sequences ordinarily stored in extended UTF-8 format,
6288 * allowing values larger than the official UTF-8 range (used internally)
6289 * and also allowing UTF-8 encoding of surrogate pairs (CESU-8 format).
6290 * Strings may also be invalid UTF-8 altogether which is the case e.g. with
6291 * strings used as internal property names and raw buffers converted to
6292 * strings. In such cases the 'clen' field contains an inaccurate value.
6293 *
6294 * ECMAScript requires support for 32-bit long strings. However, since each
6295 * 16-bit codepoint can take 3 bytes in CESU-8, this representation can only
6296 * support about 1.4G codepoint long strings in extreme cases. This is not
6297 * really a practical issue.
6298 */
6299
6300#if !defined(DUK_HSTRING_H_INCLUDED)
6301#define DUK_HSTRING_H_INCLUDED
6302
6303/* Impose a maximum string length for now. Restricted artificially to
6304 * ensure adding a heap header length won't overflow size_t. The limit
6305 * should be synchronized with DUK_HBUFFER_MAX_BYTELEN.
6306 *
6307 * E5.1 makes provisions to support strings longer than 4G characters.
6308 * This limit should be eliminated on 64-bit platforms (and increased
6309 * closer to maximum support on 32-bit platforms).
6310 */
6311
6312#if defined(DUK_USE_STRLEN16)
6313#define DUK_HSTRING_MAX_BYTELEN (0x0000ffffUL)
6314#else
6315#define DUK_HSTRING_MAX_BYTELEN (0x7fffffffUL)
6316#endif
6317
6318/* XXX: could add flags for "is valid CESU-8" (ECMAScript compatible strings),
6319 * "is valid UTF-8", "is valid extended UTF-8" (internal strings are not,
6320 * regexp bytecode is), and "contains non-BMP characters". These are not
6321 * needed right now.
6322 */
6323
6324/* With lowmem builds the high 16 bits of duk_heaphdr are used for other
6325 * purposes, so this leaves 7 duk_heaphdr flags and 9 duk_hstring flags.
6326 */
6327#define DUK_HSTRING_FLAG_ASCII DUK_HEAPHDR_USER_FLAG(0) /* string is ASCII, clen == blen */
6328#define DUK_HSTRING_FLAG_ARRIDX DUK_HEAPHDR_USER_FLAG(1) /* string is a valid array index */
6329#define DUK_HSTRING_FLAG_SYMBOL DUK_HEAPHDR_USER_FLAG(2) /* string is a symbol (invalid utf-8) */
6330#define DUK_HSTRING_FLAG_HIDDEN \
6331 DUK_HEAPHDR_USER_FLAG(3) /* string is a hidden symbol (implies symbol, Duktape 1.x internal string) */
6332#define DUK_HSTRING_FLAG_RESERVED_WORD DUK_HEAPHDR_USER_FLAG(4) /* string is a reserved word (non-strict) */
6333#define DUK_HSTRING_FLAG_STRICT_RESERVED_WORD DUK_HEAPHDR_USER_FLAG(5) /* string is a reserved word (strict) */
6334#define DUK_HSTRING_FLAG_EVAL_OR_ARGUMENTS DUK_HEAPHDR_USER_FLAG(6) /* string is 'eval' or 'arguments' */
6335#define DUK_HSTRING_FLAG_EXTDATA DUK_HEAPHDR_USER_FLAG(7) /* string data is external (duk_hstring_external) */
6336#define DUK_HSTRING_FLAG_PINNED_LITERAL DUK_HEAPHDR_USER_FLAG(8) /* string is a literal, and pinned */
6337
6338#define DUK_HSTRING_HAS_ASCII(x) DUK_HEAPHDR_CHECK_FLAG_BITS(&(x)->hdr, DUK_HSTRING_FLAG_ASCII)
6339#define DUK_HSTRING_HAS_ARRIDX(x) DUK_HEAPHDR_CHECK_FLAG_BITS(&(x)->hdr, DUK_HSTRING_FLAG_ARRIDX)
6340#define DUK_HSTRING_HAS_SYMBOL(x) DUK_HEAPHDR_CHECK_FLAG_BITS(&(x)->hdr, DUK_HSTRING_FLAG_SYMBOL)
6341#define DUK_HSTRING_HAS_HIDDEN(x) DUK_HEAPHDR_CHECK_FLAG_BITS(&(x)->hdr, DUK_HSTRING_FLAG_HIDDEN)
6342#define DUK_HSTRING_HAS_RESERVED_WORD(x) DUK_HEAPHDR_CHECK_FLAG_BITS(&(x)->hdr, DUK_HSTRING_FLAG_RESERVED_WORD)
6343#define DUK_HSTRING_HAS_STRICT_RESERVED_WORD(x) DUK_HEAPHDR_CHECK_FLAG_BITS(&(x)->hdr, DUK_HSTRING_FLAG_STRICT_RESERVED_WORD)
6344#define DUK_HSTRING_HAS_EVAL_OR_ARGUMENTS(x) DUK_HEAPHDR_CHECK_FLAG_BITS(&(x)->hdr, DUK_HSTRING_FLAG_EVAL_OR_ARGUMENTS)
6345#define DUK_HSTRING_HAS_EXTDATA(x) DUK_HEAPHDR_CHECK_FLAG_BITS(&(x)->hdr, DUK_HSTRING_FLAG_EXTDATA)
6346#define DUK_HSTRING_HAS_PINNED_LITERAL(x) DUK_HEAPHDR_CHECK_FLAG_BITS(&(x)->hdr, DUK_HSTRING_FLAG_PINNED_LITERAL)
6347
6348#define DUK_HSTRING_SET_ASCII(x) DUK_HEAPHDR_SET_FLAG_BITS(&(x)->hdr, DUK_HSTRING_FLAG_ASCII)
6349#define DUK_HSTRING_SET_ARRIDX(x) DUK_HEAPHDR_SET_FLAG_BITS(&(x)->hdr, DUK_HSTRING_FLAG_ARRIDX)
6350#define DUK_HSTRING_SET_SYMBOL(x) DUK_HEAPHDR_SET_FLAG_BITS(&(x)->hdr, DUK_HSTRING_FLAG_SYMBOL)
6351#define DUK_HSTRING_SET_HIDDEN(x) DUK_HEAPHDR_SET_FLAG_BITS(&(x)->hdr, DUK_HSTRING_FLAG_HIDDEN)
6352#define DUK_HSTRING_SET_RESERVED_WORD(x) DUK_HEAPHDR_SET_FLAG_BITS(&(x)->hdr, DUK_HSTRING_FLAG_RESERVED_WORD)
6353#define DUK_HSTRING_SET_STRICT_RESERVED_WORD(x) DUK_HEAPHDR_SET_FLAG_BITS(&(x)->hdr, DUK_HSTRING_FLAG_STRICT_RESERVED_WORD)
6354#define DUK_HSTRING_SET_EVAL_OR_ARGUMENTS(x) DUK_HEAPHDR_SET_FLAG_BITS(&(x)->hdr, DUK_HSTRING_FLAG_EVAL_OR_ARGUMENTS)
6355#define DUK_HSTRING_SET_EXTDATA(x) DUK_HEAPHDR_SET_FLAG_BITS(&(x)->hdr, DUK_HSTRING_FLAG_EXTDATA)
6356#define DUK_HSTRING_SET_PINNED_LITERAL(x) DUK_HEAPHDR_SET_FLAG_BITS(&(x)->hdr, DUK_HSTRING_FLAG_PINNED_LITERAL)
6357
6358#define DUK_HSTRING_CLEAR_ASCII(x) DUK_HEAPHDR_CLEAR_FLAG_BITS(&(x)->hdr, DUK_HSTRING_FLAG_ASCII)
6359#define DUK_HSTRING_CLEAR_ARRIDX(x) DUK_HEAPHDR_CLEAR_FLAG_BITS(&(x)->hdr, DUK_HSTRING_FLAG_ARRIDX)
6360#define DUK_HSTRING_CLEAR_SYMBOL(x) DUK_HEAPHDR_CLEAR_FLAG_BITS(&(x)->hdr, DUK_HSTRING_FLAG_SYMBOL)
6361#define DUK_HSTRING_CLEAR_HIDDEN(x) DUK_HEAPHDR_CLEAR_FLAG_BITS(&(x)->hdr, DUK_HSTRING_FLAG_HIDDEN)
6362#define DUK_HSTRING_CLEAR_RESERVED_WORD(x) DUK_HEAPHDR_CLEAR_FLAG_BITS(&(x)->hdr, DUK_HSTRING_FLAG_RESERVED_WORD)
6363#define DUK_HSTRING_CLEAR_STRICT_RESERVED_WORD(x) DUK_HEAPHDR_CLEAR_FLAG_BITS(&(x)->hdr, DUK_HSTRING_FLAG_STRICT_RESERVED_WORD)
6364#define DUK_HSTRING_CLEAR_EVAL_OR_ARGUMENTS(x) DUK_HEAPHDR_CLEAR_FLAG_BITS(&(x)->hdr, DUK_HSTRING_FLAG_EVAL_OR_ARGUMENTS)
6365#define DUK_HSTRING_CLEAR_EXTDATA(x) DUK_HEAPHDR_CLEAR_FLAG_BITS(&(x)->hdr, DUK_HSTRING_FLAG_EXTDATA)
6366#define DUK_HSTRING_CLEAR_PINNED_LITERAL(x) DUK_HEAPHDR_CLEAR_FLAG_BITS(&(x)->hdr, DUK_HSTRING_FLAG_PINNED_LITERAL)
6367
6368#if 0 /* Slightly smaller code without explicit flag, but explicit flag \
6369 * is very useful when 'clen' is dropped. \
6370 */
6371#define DUK_HSTRING_IS_ASCII(x) (DUK_HSTRING_GET_BYTELEN((x)) == DUK_HSTRING_GET_CHARLEN((x)))
6372#endif
6373#define DUK_HSTRING_IS_ASCII(x) DUK_HSTRING_HAS_ASCII((x)) /* lazily set! */
6374#define DUK_HSTRING_IS_EMPTY(x) (DUK_HSTRING_GET_BYTELEN((x)) == 0)
6375
6376#if defined(DUK_USE_STRHASH16)
6377#define DUK_HSTRING_GET_HASH(x) ((x)->hdr.h_flags >> 16)
6378#define DUK_HSTRING_SET_HASH(x, v) \
6379 do { \
6380 (x)->hdr.h_flags = ((x)->hdr.h_flags & 0x0000ffffUL) | ((v) << 16); \
6381 } while (0)
6382#else
6383#define DUK_HSTRING_GET_HASH(x) ((x)->hash)
6384#define DUK_HSTRING_SET_HASH(x, v) \
6385 do { \
6386 (x)->hash = (v); \
6387 } while (0)
6388#endif
6389
6390#if defined(DUK_USE_STRLEN16)
6391#define DUK_HSTRING_GET_BYTELEN(x) ((x)->hdr.h_strextra16)
6392#define DUK_HSTRING_SET_BYTELEN(x, v) \
6393 do { \
6394 (x)->hdr.h_strextra16 = (v); \
6395 } while (0)
6396#if defined(DUK_USE_HSTRING_CLEN)
6397#define DUK_HSTRING_GET_CHARLEN(x) duk_hstring_get_charlen((x))
6398#define DUK_HSTRING_SET_CHARLEN(x, v) \
6399 do { \
6400 (x)->clen16 = (v); \
6401 } while (0)
6402#else
6403#define DUK_HSTRING_GET_CHARLEN(x) duk_hstring_get_charlen((x))
6404#define DUK_HSTRING_SET_CHARLEN(x, v) \
6405 do { \
6406 DUK_ASSERT(0); /* should never be called */ \
6407 } while (0)
6408#endif
6409#else
6410#define DUK_HSTRING_GET_BYTELEN(x) ((x)->blen)
6411#define DUK_HSTRING_SET_BYTELEN(x, v) \
6412 do { \
6413 (x)->blen = (v); \
6414 } while (0)
6415#define DUK_HSTRING_GET_CHARLEN(x) duk_hstring_get_charlen((x))
6416#define DUK_HSTRING_SET_CHARLEN(x, v) \
6417 do { \
6418 (x)->clen = (v); \
6419 } while (0)
6420#endif
6421
6422#if defined(DUK_USE_HSTRING_EXTDATA)
6423#define DUK_HSTRING_GET_EXTDATA(x) ((x)->extdata)
6424#define DUK_HSTRING_GET_DATA(x) \
6425 (DUK_HSTRING_HAS_EXTDATA((x)) ? DUK_HSTRING_GET_EXTDATA((const duk_hstring_external *) (x)) : \
6426 ((const duk_uint8_t *) ((x) + 1)))
6427#else
6428#define DUK_HSTRING_GET_DATA(x) ((const duk_uint8_t *) ((x) + 1))
6429#endif
6430
6431#define DUK_HSTRING_GET_DATA_END(x) (DUK_HSTRING_GET_DATA((x)) + (x)->blen)
6432
6433/* Marker value; in E5 2^32-1 is not a valid array index (2^32-2 is highest
6434 * valid).
6435 */
6436#define DUK_HSTRING_NO_ARRAY_INDEX (0xffffffffUL)
6437
6438#if defined(DUK_USE_HSTRING_ARRIDX)
6439#define DUK_HSTRING_GET_ARRIDX_FAST(h) ((h)->arridx)
6440#define DUK_HSTRING_GET_ARRIDX_SLOW(h) ((h)->arridx)
6441#else
6442/* Get array index related to string (or return DUK_HSTRING_NO_ARRAY_INDEX);
6443 * avoids helper call if string has no array index value.
6444 */
6445#define DUK_HSTRING_GET_ARRIDX_FAST(h) \
6446 (DUK_HSTRING_HAS_ARRIDX((h)) ? duk_js_to_arrayindex_hstring_fast_known((h)) : DUK_HSTRING_NO_ARRAY_INDEX)
6447
6448/* Slower but more compact variant. */
6449#define DUK_HSTRING_GET_ARRIDX_SLOW(h) (duk_js_to_arrayindex_hstring_fast((h)))
6450#endif
6451
6452/* XXX: these actually fit into duk_hstring */
6453#define DUK_SYMBOL_TYPE_HIDDEN 0
6454#define DUK_SYMBOL_TYPE_GLOBAL 1
6455#define DUK_SYMBOL_TYPE_LOCAL 2
6456#define DUK_SYMBOL_TYPE_WELLKNOWN 3
6457
6458/* Assertion for duk_hstring validity. */
6459#if defined(DUK_USE_ASSERTIONS)
6460DUK_INTERNAL_DECL void duk_hstring_assert_valid(duk_hstring *h);
6461#define DUK_HSTRING_ASSERT_VALID(h) \
6462 do { \
6463 duk_hstring_assert_valid((h)); \
6464 } while (0)
6465#else
6466#define DUK_HSTRING_ASSERT_VALID(h) \
6467 do { \
6468 } while (0)
6469#endif
6470
6471/*
6472 * Misc
6473 */
6474
6476 /* Smaller heaphdr than for other objects, because strings are held
6477 * in string intern table which requires no link pointers. Much of
6478 * the 32-bit flags field is unused by flags, so we can stuff a 16-bit
6479 * field in there.
6480 */
6482
6483 /* String hash. */
6484#if defined(DUK_USE_STRHASH16)
6485 /* If 16-bit hash is in use, stuff it into duk_heaphdr_string flags. */
6486#else
6487 duk_uint32_t hash;
6488#endif
6489
6490 /* Precomputed array index (or DUK_HSTRING_NO_ARRAY_INDEX). */
6491#if defined(DUK_USE_HSTRING_ARRIDX)
6493#endif
6494
6495 /* Length in bytes (not counting NUL term). */
6496#if defined(DUK_USE_STRLEN16)
6497 /* placed in duk_heaphdr_string */
6498#else
6499 duk_uint32_t blen;
6500#endif
6501
6502 /* Length in codepoints (must be E5 compatible). */
6503#if defined(DUK_USE_STRLEN16)
6504#if defined(DUK_USE_HSTRING_CLEN)
6505 duk_uint16_t clen16;
6506#else
6507 /* computed live */
6508#endif
6509#else
6510 duk_uint32_t clen;
6511#endif
6512
6513 /*
6514 * String data of 'blen+1' bytes follows (+1 for NUL termination
6515 * convenience for C API). No alignment needs to be guaranteed
6516 * for strings, but fields above should guarantee alignment-by-4
6517 * (but not alignment-by-8).
6518 */
6519};
6520
6521/* The external string struct is defined even when the feature is inactive. */
6524
6525 /*
6526 * For an external string, the NUL-terminated string data is stored
6527 * externally. The user must guarantee that data behind this pointer
6528 * doesn't change while it's used.
6529 */
6530
6531 const duk_uint8_t *extdata;
6532};
6533
6534/*
6535 * Prototypes
6536 */
6537
6539 duk_hstring *h,
6540 duk_uint_t pos,
6541 duk_bool_t surrogate_aware);
6544#if !defined(DUK_USE_HSTRING_LAZY_CLEN)
6545DUK_INTERNAL_DECL void duk_hstring_init_charlen(duk_hstring *h);
6546#endif
6547
6548#endif /* DUK_HSTRING_H_INCLUDED */
6549/* #include duk_hobject.h */
6550/*
6551 * Heap object representation.
6552 *
6553 * Heap objects are used for ECMAScript objects, arrays, and functions,
6554 * but also for internal control like declarative and object environment
6555 * records. Compiled functions, native functions, and threads are also
6556 * objects but with an extended C struct.
6557 *
6558 * Objects provide the required ECMAScript semantics and exotic behaviors
6559 * especially for property access.
6560 *
6561 * Properties are stored in three conceptual parts:
6562 *
6563 * 1. A linear 'entry part' contains ordered key-value-attributes triples
6564 * and is the main method of string properties.
6565 *
6566 * 2. An optional linear 'array part' is used for array objects to store a
6567 * (dense) range of [0,N[ array indexed entries with default attributes
6568 * (writable, enumerable, configurable). If the array part would become
6569 * sparse or non-default attributes are required, the array part is
6570 * abandoned and moved to the 'entry part'.
6571 *
6572 * 3. An optional 'hash part' is used to optimize lookups of the entry
6573 * part; it is used only for objects with sufficiently many properties
6574 * and can be abandoned without loss of information.
6575 *
6576 * These three conceptual parts are stored in a single memory allocated area.
6577 * This minimizes memory allocation overhead but also means that all three
6578 * parts are resized together, and makes property access a bit complicated.
6579 */
6580
6581#if !defined(DUK_HOBJECT_H_INCLUDED)
6582#define DUK_HOBJECT_H_INCLUDED
6583
6584/* Object flags. Make sure this stays in sync with debugger object
6585 * inspection code.
6586 */
6587
6588/* XXX: some flags are object subtype specific (e.g. common to all function
6589 * subtypes, duk_harray, etc) and could be reused for different subtypes.
6590 */
6591#define DUK_HOBJECT_FLAG_EXTENSIBLE DUK_HEAPHDR_USER_FLAG(0) /* object is extensible */
6592#define DUK_HOBJECT_FLAG_CONSTRUCTABLE DUK_HEAPHDR_USER_FLAG(1) /* object is constructable */
6593#define DUK_HOBJECT_FLAG_CALLABLE DUK_HEAPHDR_USER_FLAG(2) /* object is callable */
6594#define DUK_HOBJECT_FLAG_BOUNDFUNC DUK_HEAPHDR_USER_FLAG(3) /* object established using Function.prototype.bind() */
6595#define DUK_HOBJECT_FLAG_COMPFUNC DUK_HEAPHDR_USER_FLAG(4) /* object is a compiled function (duk_hcompfunc) */
6596#define DUK_HOBJECT_FLAG_NATFUNC DUK_HEAPHDR_USER_FLAG(5) /* object is a native function (duk_hnatfunc) */
6597#define DUK_HOBJECT_FLAG_BUFOBJ DUK_HEAPHDR_USER_FLAG(6) /* object is a buffer object (duk_hbufobj) (always exotic) */
6598#define DUK_HOBJECT_FLAG_FASTREFS \
6599 DUK_HEAPHDR_USER_FLAG(7) /* object has no fields needing DECREF/marking beyond base duk_hobject header */
6600#define DUK_HOBJECT_FLAG_ARRAY_PART DUK_HEAPHDR_USER_FLAG(8) /* object has an array part (a_size may still be 0) */
6601#define DUK_HOBJECT_FLAG_STRICT DUK_HEAPHDR_USER_FLAG(9) /* function: function object is strict */
6602#define DUK_HOBJECT_FLAG_NOTAIL DUK_HEAPHDR_USER_FLAG(10) /* function: function must not be tail called */
6603#define DUK_HOBJECT_FLAG_NEWENV DUK_HEAPHDR_USER_FLAG(11) /* function: create new environment when called (see duk_hcompfunc) */
6604#define DUK_HOBJECT_FLAG_NAMEBINDING \
6605 DUK_HEAPHDR_USER_FLAG( \
6606 12) /* function: create binding for func name (function templates only, used for named function expressions) */
6607#define DUK_HOBJECT_FLAG_CREATEARGS DUK_HEAPHDR_USER_FLAG(13) /* function: create an arguments object on function call */
6608#define DUK_HOBJECT_FLAG_HAVE_FINALIZER DUK_HEAPHDR_USER_FLAG(14) /* object has a callable (own) finalizer property */
6609#define DUK_HOBJECT_FLAG_EXOTIC_ARRAY DUK_HEAPHDR_USER_FLAG(15) /* 'Array' object, array length and index exotic behavior */
6610#define DUK_HOBJECT_FLAG_EXOTIC_STRINGOBJ DUK_HEAPHDR_USER_FLAG(16) /* 'String' object, array index exotic behavior */
6611#define DUK_HOBJECT_FLAG_EXOTIC_ARGUMENTS \
6612 DUK_HEAPHDR_USER_FLAG(17) /* 'Arguments' object and has arguments exotic behavior (non-strict callee) */
6613#define DUK_HOBJECT_FLAG_EXOTIC_PROXYOBJ DUK_HEAPHDR_USER_FLAG(18) /* 'Proxy' object */
6614#define DUK_HOBJECT_FLAG_SPECIAL_CALL DUK_HEAPHDR_USER_FLAG(19) /* special casing in call behavior, for .call(), .apply(), etc. */
6615
6616#define DUK_HOBJECT_FLAG_CLASS_BASE DUK_HEAPHDR_USER_FLAG_NUMBER(20)
6617#define DUK_HOBJECT_FLAG_CLASS_BITS 5
6618
6619#define DUK_HOBJECT_GET_CLASS_NUMBER(h) \
6620 DUK_HEAPHDR_GET_FLAG_RANGE(&(h)->hdr, DUK_HOBJECT_FLAG_CLASS_BASE, DUK_HOBJECT_FLAG_CLASS_BITS)
6621#define DUK_HOBJECT_SET_CLASS_NUMBER(h, v) \
6622 DUK_HEAPHDR_SET_FLAG_RANGE(&(h)->hdr, DUK_HOBJECT_FLAG_CLASS_BASE, DUK_HOBJECT_FLAG_CLASS_BITS, (v))
6623
6624#define DUK_HOBJECT_GET_CLASS_MASK(h) \
6625 (1UL << DUK_HEAPHDR_GET_FLAG_RANGE(&(h)->hdr, DUK_HOBJECT_FLAG_CLASS_BASE, DUK_HOBJECT_FLAG_CLASS_BITS))
6626
6627/* Macro for creating flag initializer from a class number.
6628 * Unsigned type cast is needed to avoid warnings about coercing
6629 * a signed integer to an unsigned one; the largest class values
6630 * have the highest bit (bit 31) set which causes this.
6631 */
6632#define DUK_HOBJECT_CLASS_AS_FLAGS(v) (((duk_uint_t) (v)) << DUK_HOBJECT_FLAG_CLASS_BASE)
6633
6634/* E5 Section 8.6.2 + custom classes */
6635#define DUK_HOBJECT_CLASS_NONE 0
6636#define DUK_HOBJECT_CLASS_OBJECT 1
6637#define DUK_HOBJECT_CLASS_ARRAY 2
6638#define DUK_HOBJECT_CLASS_FUNCTION 3
6639#define DUK_HOBJECT_CLASS_ARGUMENTS 4
6640#define DUK_HOBJECT_CLASS_BOOLEAN 5
6641#define DUK_HOBJECT_CLASS_DATE 6
6642#define DUK_HOBJECT_CLASS_ERROR 7
6643#define DUK_HOBJECT_CLASS_JSON 8
6644#define DUK_HOBJECT_CLASS_MATH 9
6645#define DUK_HOBJECT_CLASS_NUMBER 10
6646#define DUK_HOBJECT_CLASS_REGEXP 11
6647#define DUK_HOBJECT_CLASS_STRING 12
6648#define DUK_HOBJECT_CLASS_GLOBAL 13
6649#define DUK_HOBJECT_CLASS_SYMBOL 14
6650#define DUK_HOBJECT_CLASS_OBJENV 15 /* custom */
6651#define DUK_HOBJECT_CLASS_DECENV 16 /* custom */
6652#define DUK_HOBJECT_CLASS_POINTER 17 /* custom */
6653#define DUK_HOBJECT_CLASS_THREAD 18 /* custom; implies DUK_HOBJECT_IS_THREAD */
6654#define DUK_HOBJECT_CLASS_BUFOBJ_MIN 19
6655#define DUK_HOBJECT_CLASS_ARRAYBUFFER 19 /* implies DUK_HOBJECT_IS_BUFOBJ */
6656#define DUK_HOBJECT_CLASS_DATAVIEW 20
6657#define DUK_HOBJECT_CLASS_INT8ARRAY 21
6658#define DUK_HOBJECT_CLASS_UINT8ARRAY 22
6659#define DUK_HOBJECT_CLASS_UINT8CLAMPEDARRAY 23
6660#define DUK_HOBJECT_CLASS_INT16ARRAY 24
6661#define DUK_HOBJECT_CLASS_UINT16ARRAY 25
6662#define DUK_HOBJECT_CLASS_INT32ARRAY 26
6663#define DUK_HOBJECT_CLASS_UINT32ARRAY 27
6664#define DUK_HOBJECT_CLASS_FLOAT32ARRAY 28
6665#define DUK_HOBJECT_CLASS_FLOAT64ARRAY 29
6666#define DUK_HOBJECT_CLASS_BUFOBJ_MAX 29
6667#define DUK_HOBJECT_CLASS_MAX 29
6668
6669/* Class masks. */
6670#define DUK_HOBJECT_CMASK_ALL ((1UL << (DUK_HOBJECT_CLASS_MAX + 1)) - 1UL)
6671#define DUK_HOBJECT_CMASK_NONE (1UL << DUK_HOBJECT_CLASS_NONE)
6672#define DUK_HOBJECT_CMASK_ARGUMENTS (1UL << DUK_HOBJECT_CLASS_ARGUMENTS)
6673#define DUK_HOBJECT_CMASK_ARRAY (1UL << DUK_HOBJECT_CLASS_ARRAY)
6674#define DUK_HOBJECT_CMASK_BOOLEAN (1UL << DUK_HOBJECT_CLASS_BOOLEAN)
6675#define DUK_HOBJECT_CMASK_DATE (1UL << DUK_HOBJECT_CLASS_DATE)
6676#define DUK_HOBJECT_CMASK_ERROR (1UL << DUK_HOBJECT_CLASS_ERROR)
6677#define DUK_HOBJECT_CMASK_FUNCTION (1UL << DUK_HOBJECT_CLASS_FUNCTION)
6678#define DUK_HOBJECT_CMASK_JSON (1UL << DUK_HOBJECT_CLASS_JSON)
6679#define DUK_HOBJECT_CMASK_MATH (1UL << DUK_HOBJECT_CLASS_MATH)
6680#define DUK_HOBJECT_CMASK_NUMBER (1UL << DUK_HOBJECT_CLASS_NUMBER)
6681#define DUK_HOBJECT_CMASK_OBJECT (1UL << DUK_HOBJECT_CLASS_OBJECT)
6682#define DUK_HOBJECT_CMASK_REGEXP (1UL << DUK_HOBJECT_CLASS_REGEXP)
6683#define DUK_HOBJECT_CMASK_STRING (1UL << DUK_HOBJECT_CLASS_STRING)
6684#define DUK_HOBJECT_CMASK_GLOBAL (1UL << DUK_HOBJECT_CLASS_GLOBAL)
6685#define DUK_HOBJECT_CMASK_SYMBOL (1UL << DUK_HOBJECT_CLASS_SYMBOL)
6686#define DUK_HOBJECT_CMASK_OBJENV (1UL << DUK_HOBJECT_CLASS_OBJENV)
6687#define DUK_HOBJECT_CMASK_DECENV (1UL << DUK_HOBJECT_CLASS_DECENV)
6688#define DUK_HOBJECT_CMASK_POINTER (1UL << DUK_HOBJECT_CLASS_POINTER)
6689#define DUK_HOBJECT_CMASK_ARRAYBUFFER (1UL << DUK_HOBJECT_CLASS_ARRAYBUFFER)
6690#define DUK_HOBJECT_CMASK_DATAVIEW (1UL << DUK_HOBJECT_CLASS_DATAVIEW)
6691#define DUK_HOBJECT_CMASK_INT8ARRAY (1UL << DUK_HOBJECT_CLASS_INT8ARRAY)
6692#define DUK_HOBJECT_CMASK_UINT8ARRAY (1UL << DUK_HOBJECT_CLASS_UINT8ARRAY)
6693#define DUK_HOBJECT_CMASK_UINT8CLAMPEDARRAY (1UL << DUK_HOBJECT_CLASS_UINT8CLAMPEDARRAY)
6694#define DUK_HOBJECT_CMASK_INT16ARRAY (1UL << DUK_HOBJECT_CLASS_INT16ARRAY)
6695#define DUK_HOBJECT_CMASK_UINT16ARRAY (1UL << DUK_HOBJECT_CLASS_UINT16ARRAY)
6696#define DUK_HOBJECT_CMASK_INT32ARRAY (1UL << DUK_HOBJECT_CLASS_INT32ARRAY)
6697#define DUK_HOBJECT_CMASK_UINT32ARRAY (1UL << DUK_HOBJECT_CLASS_UINT32ARRAY)
6698#define DUK_HOBJECT_CMASK_FLOAT32ARRAY (1UL << DUK_HOBJECT_CLASS_FLOAT32ARRAY)
6699#define DUK_HOBJECT_CMASK_FLOAT64ARRAY (1UL << DUK_HOBJECT_CLASS_FLOAT64ARRAY)
6700
6701#define DUK_HOBJECT_CMASK_ALL_BUFOBJS \
6702 (DUK_HOBJECT_CMASK_ARRAYBUFFER | DUK_HOBJECT_CMASK_DATAVIEW | DUK_HOBJECT_CMASK_INT8ARRAY | DUK_HOBJECT_CMASK_UINT8ARRAY | \
6703 DUK_HOBJECT_CMASK_UINT8CLAMPEDARRAY | DUK_HOBJECT_CMASK_INT16ARRAY | DUK_HOBJECT_CMASK_UINT16ARRAY | \
6704 DUK_HOBJECT_CMASK_INT32ARRAY | DUK_HOBJECT_CMASK_UINT32ARRAY | DUK_HOBJECT_CMASK_FLOAT32ARRAY | \
6705 DUK_HOBJECT_CMASK_FLOAT64ARRAY)
6706
6707#define DUK_HOBJECT_IS_OBJENV(h) (DUK_HOBJECT_GET_CLASS_NUMBER((h)) == DUK_HOBJECT_CLASS_OBJENV)
6708#define DUK_HOBJECT_IS_DECENV(h) (DUK_HOBJECT_GET_CLASS_NUMBER((h)) == DUK_HOBJECT_CLASS_DECENV)
6709#define DUK_HOBJECT_IS_ENV(h) (DUK_HOBJECT_IS_OBJENV((h)) || DUK_HOBJECT_IS_DECENV((h)))
6710#define DUK_HOBJECT_IS_ARRAY(h) DUK_HOBJECT_HAS_EXOTIC_ARRAY((h)) /* Rely on class Array <=> exotic Array */
6711#define DUK_HOBJECT_IS_BOUNDFUNC(h) DUK_HEAPHDR_CHECK_FLAG_BITS(&(h)->hdr, DUK_HOBJECT_FLAG_BOUNDFUNC)
6712#define DUK_HOBJECT_IS_COMPFUNC(h) DUK_HEAPHDR_CHECK_FLAG_BITS(&(h)->hdr, DUK_HOBJECT_FLAG_COMPFUNC)
6713#define DUK_HOBJECT_IS_NATFUNC(h) DUK_HEAPHDR_CHECK_FLAG_BITS(&(h)->hdr, DUK_HOBJECT_FLAG_NATFUNC)
6714#if defined(DUK_USE_BUFFEROBJECT_SUPPORT)
6715#define DUK_HOBJECT_IS_BUFOBJ(h) DUK_HEAPHDR_CHECK_FLAG_BITS(&(h)->hdr, DUK_HOBJECT_FLAG_BUFOBJ)
6716#else
6717#define DUK_HOBJECT_IS_BUFOBJ(h) 0
6718#endif
6719#define DUK_HOBJECT_IS_THREAD(h) (DUK_HOBJECT_GET_CLASS_NUMBER((h)) == DUK_HOBJECT_CLASS_THREAD)
6720#if defined(DUK_USE_ES6_PROXY)
6721#define DUK_HOBJECT_IS_PROXY(h) DUK_HOBJECT_HAS_EXOTIC_PROXYOBJ((h))
6722#else
6723#define DUK_HOBJECT_IS_PROXY(h) 0
6724#endif
6725
6726#define DUK_HOBJECT_IS_NONBOUND_FUNCTION(h) \
6727 DUK_HEAPHDR_CHECK_FLAG_BITS(&(h)->hdr, DUK_HOBJECT_FLAG_COMPFUNC | DUK_HOBJECT_FLAG_NATFUNC)
6728
6729#define DUK_HOBJECT_IS_FUNCTION(h) \
6730 DUK_HEAPHDR_CHECK_FLAG_BITS(&(h)->hdr, DUK_HOBJECT_FLAG_BOUNDFUNC | DUK_HOBJECT_FLAG_COMPFUNC | DUK_HOBJECT_FLAG_NATFUNC)
6731
6732#define DUK_HOBJECT_IS_CALLABLE(h) DUK_HOBJECT_HAS_CALLABLE((h))
6733
6734/* Object has any exotic behavior(s). */
6735#define DUK_HOBJECT_EXOTIC_BEHAVIOR_FLAGS \
6736 (DUK_HOBJECT_FLAG_EXOTIC_ARRAY | DUK_HOBJECT_FLAG_EXOTIC_ARGUMENTS | DUK_HOBJECT_FLAG_EXOTIC_STRINGOBJ | \
6737 DUK_HOBJECT_FLAG_BUFOBJ | DUK_HOBJECT_FLAG_EXOTIC_PROXYOBJ)
6738#define DUK_HOBJECT_HAS_EXOTIC_BEHAVIOR(h) DUK_HEAPHDR_CHECK_FLAG_BITS(&(h)->hdr, DUK_HOBJECT_EXOTIC_BEHAVIOR_FLAGS)
6739
6740/* Object has any virtual properties (not counting Proxy behavior). */
6741#define DUK_HOBJECT_VIRTUAL_PROPERTY_FLAGS \
6742 (DUK_HOBJECT_FLAG_EXOTIC_ARRAY | DUK_HOBJECT_FLAG_EXOTIC_STRINGOBJ | DUK_HOBJECT_FLAG_BUFOBJ)
6743#define DUK_HOBJECT_HAS_VIRTUAL_PROPERTIES(h) DUK_HEAPHDR_CHECK_FLAG_BITS(&(h)->hdr, DUK_HOBJECT_VIRTUAL_PROPERTY_FLAGS)
6744
6745#define DUK_HOBJECT_HAS_EXTENSIBLE(h) DUK_HEAPHDR_CHECK_FLAG_BITS(&(h)->hdr, DUK_HOBJECT_FLAG_EXTENSIBLE)
6746#define DUK_HOBJECT_HAS_CONSTRUCTABLE(h) DUK_HEAPHDR_CHECK_FLAG_BITS(&(h)->hdr, DUK_HOBJECT_FLAG_CONSTRUCTABLE)
6747#define DUK_HOBJECT_HAS_CALLABLE(h) DUK_HEAPHDR_CHECK_FLAG_BITS(&(h)->hdr, DUK_HOBJECT_FLAG_CALLABLE)
6748#define DUK_HOBJECT_HAS_BOUNDFUNC(h) DUK_HEAPHDR_CHECK_FLAG_BITS(&(h)->hdr, DUK_HOBJECT_FLAG_BOUNDFUNC)
6749#define DUK_HOBJECT_HAS_COMPFUNC(h) DUK_HEAPHDR_CHECK_FLAG_BITS(&(h)->hdr, DUK_HOBJECT_FLAG_COMPFUNC)
6750#define DUK_HOBJECT_HAS_NATFUNC(h) DUK_HEAPHDR_CHECK_FLAG_BITS(&(h)->hdr, DUK_HOBJECT_FLAG_NATFUNC)
6751#if defined(DUK_USE_BUFFEROBJECT_SUPPORT)
6752#define DUK_HOBJECT_HAS_BUFOBJ(h) DUK_HEAPHDR_CHECK_FLAG_BITS(&(h)->hdr, DUK_HOBJECT_FLAG_BUFOBJ)
6753#else
6754#define DUK_HOBJECT_HAS_BUFOBJ(h) 0
6755#endif
6756#define DUK_HOBJECT_HAS_FASTREFS(h) DUK_HEAPHDR_CHECK_FLAG_BITS(&(h)->hdr, DUK_HOBJECT_FLAG_FASTREFS)
6757#define DUK_HOBJECT_HAS_ARRAY_PART(h) DUK_HEAPHDR_CHECK_FLAG_BITS(&(h)->hdr, DUK_HOBJECT_FLAG_ARRAY_PART)
6758#define DUK_HOBJECT_HAS_STRICT(h) DUK_HEAPHDR_CHECK_FLAG_BITS(&(h)->hdr, DUK_HOBJECT_FLAG_STRICT)
6759#define DUK_HOBJECT_HAS_NOTAIL(h) DUK_HEAPHDR_CHECK_FLAG_BITS(&(h)->hdr, DUK_HOBJECT_FLAG_NOTAIL)
6760#define DUK_HOBJECT_HAS_NEWENV(h) DUK_HEAPHDR_CHECK_FLAG_BITS(&(h)->hdr, DUK_HOBJECT_FLAG_NEWENV)
6761#define DUK_HOBJECT_HAS_NAMEBINDING(h) DUK_HEAPHDR_CHECK_FLAG_BITS(&(h)->hdr, DUK_HOBJECT_FLAG_NAMEBINDING)
6762#define DUK_HOBJECT_HAS_CREATEARGS(h) DUK_HEAPHDR_CHECK_FLAG_BITS(&(h)->hdr, DUK_HOBJECT_FLAG_CREATEARGS)
6763#define DUK_HOBJECT_HAS_HAVE_FINALIZER(h) DUK_HEAPHDR_CHECK_FLAG_BITS(&(h)->hdr, DUK_HOBJECT_FLAG_HAVE_FINALIZER)
6764#define DUK_HOBJECT_HAS_EXOTIC_ARRAY(h) DUK_HEAPHDR_CHECK_FLAG_BITS(&(h)->hdr, DUK_HOBJECT_FLAG_EXOTIC_ARRAY)
6765#define DUK_HOBJECT_HAS_EXOTIC_STRINGOBJ(h) DUK_HEAPHDR_CHECK_FLAG_BITS(&(h)->hdr, DUK_HOBJECT_FLAG_EXOTIC_STRINGOBJ)
6766#define DUK_HOBJECT_HAS_EXOTIC_ARGUMENTS(h) DUK_HEAPHDR_CHECK_FLAG_BITS(&(h)->hdr, DUK_HOBJECT_FLAG_EXOTIC_ARGUMENTS)
6767#if defined(DUK_USE_ES6_PROXY)
6768#define DUK_HOBJECT_HAS_EXOTIC_PROXYOBJ(h) DUK_HEAPHDR_CHECK_FLAG_BITS(&(h)->hdr, DUK_HOBJECT_FLAG_EXOTIC_PROXYOBJ)
6769#else
6770#define DUK_HOBJECT_HAS_EXOTIC_PROXYOBJ(h) 0
6771#endif
6772#define DUK_HOBJECT_HAS_SPECIAL_CALL(h) DUK_HEAPHDR_CHECK_FLAG_BITS(&(h)->hdr, DUK_HOBJECT_FLAG_SPECIAL_CALL)
6773
6774#define DUK_HOBJECT_SET_EXTENSIBLE(h) DUK_HEAPHDR_SET_FLAG_BITS(&(h)->hdr, DUK_HOBJECT_FLAG_EXTENSIBLE)
6775#define DUK_HOBJECT_SET_CONSTRUCTABLE(h) DUK_HEAPHDR_SET_FLAG_BITS(&(h)->hdr, DUK_HOBJECT_FLAG_CONSTRUCTABLE)
6776#define DUK_HOBJECT_SET_CALLABLE(h) DUK_HEAPHDR_SET_FLAG_BITS(&(h)->hdr, DUK_HOBJECT_FLAG_CALLABLE)
6777#define DUK_HOBJECT_SET_BOUNDFUNC(h) DUK_HEAPHDR_SET_FLAG_BITS(&(h)->hdr, DUK_HOBJECT_FLAG_BOUNDFUNC)
6778#define DUK_HOBJECT_SET_COMPFUNC(h) DUK_HEAPHDR_SET_FLAG_BITS(&(h)->hdr, DUK_HOBJECT_FLAG_COMPFUNC)
6779#define DUK_HOBJECT_SET_NATFUNC(h) DUK_HEAPHDR_SET_FLAG_BITS(&(h)->hdr, DUK_HOBJECT_FLAG_NATFUNC)
6780#if defined(DUK_USE_BUFFEROBJECT_SUPPORT)
6781#define DUK_HOBJECT_SET_BUFOBJ(h) DUK_HEAPHDR_SET_FLAG_BITS(&(h)->hdr, DUK_HOBJECT_FLAG_BUFOBJ)
6782#endif
6783#define DUK_HOBJECT_SET_FASTREFS(h) DUK_HEAPHDR_SET_FLAG_BITS(&(h)->hdr, DUK_HOBJECT_FLAG_FASTREFS)
6784#define DUK_HOBJECT_SET_ARRAY_PART(h) DUK_HEAPHDR_SET_FLAG_BITS(&(h)->hdr, DUK_HOBJECT_FLAG_ARRAY_PART)
6785#define DUK_HOBJECT_SET_STRICT(h) DUK_HEAPHDR_SET_FLAG_BITS(&(h)->hdr, DUK_HOBJECT_FLAG_STRICT)
6786#define DUK_HOBJECT_SET_NOTAIL(h) DUK_HEAPHDR_SET_FLAG_BITS(&(h)->hdr, DUK_HOBJECT_FLAG_NOTAIL)
6787#define DUK_HOBJECT_SET_NEWENV(h) DUK_HEAPHDR_SET_FLAG_BITS(&(h)->hdr, DUK_HOBJECT_FLAG_NEWENV)
6788#define DUK_HOBJECT_SET_NAMEBINDING(h) DUK_HEAPHDR_SET_FLAG_BITS(&(h)->hdr, DUK_HOBJECT_FLAG_NAMEBINDING)
6789#define DUK_HOBJECT_SET_CREATEARGS(h) DUK_HEAPHDR_SET_FLAG_BITS(&(h)->hdr, DUK_HOBJECT_FLAG_CREATEARGS)
6790#define DUK_HOBJECT_SET_HAVE_FINALIZER(h) DUK_HEAPHDR_SET_FLAG_BITS(&(h)->hdr, DUK_HOBJECT_FLAG_HAVE_FINALIZER)
6791#define DUK_HOBJECT_SET_EXOTIC_ARRAY(h) DUK_HEAPHDR_SET_FLAG_BITS(&(h)->hdr, DUK_HOBJECT_FLAG_EXOTIC_ARRAY)
6792#define DUK_HOBJECT_SET_EXOTIC_STRINGOBJ(h) DUK_HEAPHDR_SET_FLAG_BITS(&(h)->hdr, DUK_HOBJECT_FLAG_EXOTIC_STRINGOBJ)
6793#define DUK_HOBJECT_SET_EXOTIC_ARGUMENTS(h) DUK_HEAPHDR_SET_FLAG_BITS(&(h)->hdr, DUK_HOBJECT_FLAG_EXOTIC_ARGUMENTS)
6794#if defined(DUK_USE_ES6_PROXY)
6795#define DUK_HOBJECT_SET_EXOTIC_PROXYOBJ(h) DUK_HEAPHDR_SET_FLAG_BITS(&(h)->hdr, DUK_HOBJECT_FLAG_EXOTIC_PROXYOBJ)
6796#endif
6797#define DUK_HOBJECT_SET_SPECIAL_CALL(h) DUK_HEAPHDR_SET_FLAG_BITS(&(h)->hdr, DUK_HOBJECT_FLAG_SPECIAL_CALL)
6798
6799#define DUK_HOBJECT_CLEAR_EXTENSIBLE(h) DUK_HEAPHDR_CLEAR_FLAG_BITS(&(h)->hdr, DUK_HOBJECT_FLAG_EXTENSIBLE)
6800#define DUK_HOBJECT_CLEAR_CONSTRUCTABLE(h) DUK_HEAPHDR_CLEAR_FLAG_BITS(&(h)->hdr, DUK_HOBJECT_FLAG_CONSTRUCTABLE)
6801#define DUK_HOBJECT_CLEAR_CALLABLE(h) DUK_HEAPHDR_CLEAR_FLAG_BITS(&(h)->hdr, DUK_HOBJECT_FLAG_CALLABLE)
6802#define DUK_HOBJECT_CLEAR_BOUNDFUNC(h) DUK_HEAPHDR_CLEAR_FLAG_BITS(&(h)->hdr, DUK_HOBJECT_FLAG_BOUNDFUNC)
6803#define DUK_HOBJECT_CLEAR_COMPFUNC(h) DUK_HEAPHDR_CLEAR_FLAG_BITS(&(h)->hdr, DUK_HOBJECT_FLAG_COMPFUNC)
6804#define DUK_HOBJECT_CLEAR_NATFUNC(h) DUK_HEAPHDR_CLEAR_FLAG_BITS(&(h)->hdr, DUK_HOBJECT_FLAG_NATFUNC)
6805#if defined(DUK_USE_BUFFEROBJECT_SUPPORT)
6806#define DUK_HOBJECT_CLEAR_BUFOBJ(h) DUK_HEAPHDR_CLEAR_FLAG_BITS(&(h)->hdr, DUK_HOBJECT_FLAG_BUFOBJ)
6807#endif
6808#define DUK_HOBJECT_CLEAR_FASTREFS(h) DUK_HEAPHDR_CLEAR_FLAG_BITS(&(h)->hdr, DUK_HOBJECT_FLAG_FASTREFS)
6809#define DUK_HOBJECT_CLEAR_ARRAY_PART(h) DUK_HEAPHDR_CLEAR_FLAG_BITS(&(h)->hdr, DUK_HOBJECT_FLAG_ARRAY_PART)
6810#define DUK_HOBJECT_CLEAR_STRICT(h) DUK_HEAPHDR_CLEAR_FLAG_BITS(&(h)->hdr, DUK_HOBJECT_FLAG_STRICT)
6811#define DUK_HOBJECT_CLEAR_NOTAIL(h) DUK_HEAPHDR_CLEAR_FLAG_BITS(&(h)->hdr, DUK_HOBJECT_FLAG_NOTAIL)
6812#define DUK_HOBJECT_CLEAR_NEWENV(h) DUK_HEAPHDR_CLEAR_FLAG_BITS(&(h)->hdr, DUK_HOBJECT_FLAG_NEWENV)
6813#define DUK_HOBJECT_CLEAR_NAMEBINDING(h) DUK_HEAPHDR_CLEAR_FLAG_BITS(&(h)->hdr, DUK_HOBJECT_FLAG_NAMEBINDING)
6814#define DUK_HOBJECT_CLEAR_CREATEARGS(h) DUK_HEAPHDR_CLEAR_FLAG_BITS(&(h)->hdr, DUK_HOBJECT_FLAG_CREATEARGS)
6815#define DUK_HOBJECT_CLEAR_HAVE_FINALIZER(h) DUK_HEAPHDR_CLEAR_FLAG_BITS(&(h)->hdr, DUK_HOBJECT_FLAG_HAVE_FINALIZER)
6816#define DUK_HOBJECT_CLEAR_EXOTIC_ARRAY(h) DUK_HEAPHDR_CLEAR_FLAG_BITS(&(h)->hdr, DUK_HOBJECT_FLAG_EXOTIC_ARRAY)
6817#define DUK_HOBJECT_CLEAR_EXOTIC_STRINGOBJ(h) DUK_HEAPHDR_CLEAR_FLAG_BITS(&(h)->hdr, DUK_HOBJECT_FLAG_EXOTIC_STRINGOBJ)
6818#define DUK_HOBJECT_CLEAR_EXOTIC_ARGUMENTS(h) DUK_HEAPHDR_CLEAR_FLAG_BITS(&(h)->hdr, DUK_HOBJECT_FLAG_EXOTIC_ARGUMENTS)
6819#if defined(DUK_USE_ES6_PROXY)
6820#define DUK_HOBJECT_CLEAR_EXOTIC_PROXYOBJ(h) DUK_HEAPHDR_CLEAR_FLAG_BITS(&(h)->hdr, DUK_HOBJECT_FLAG_EXOTIC_PROXYOBJ)
6821#endif
6822#define DUK_HOBJECT_CLEAR_SPECIAL_CALL(h) DUK_HEAPHDR_CLEAR_FLAG_BITS(&(h)->hdr, DUK_HOBJECT_FLAG_SPECIAL_CALL)
6823
6824/* Object can/cannot use FASTREFS, i.e. has no strong reference fields beyond
6825 * duk_hobject base header. This is used just for asserts so doesn't need to
6826 * be optimized.
6827 */
6828#define DUK_HOBJECT_PROHIBITS_FASTREFS(h) \
6829 (DUK_HOBJECT_IS_COMPFUNC((h)) || DUK_HOBJECT_IS_DECENV((h)) || DUK_HOBJECT_IS_OBJENV((h)) || DUK_HOBJECT_IS_BUFOBJ((h)) || \
6830 DUK_HOBJECT_IS_THREAD((h)) || DUK_HOBJECT_IS_PROXY((h)) || DUK_HOBJECT_IS_BOUNDFUNC((h)))
6831#define DUK_HOBJECT_ALLOWS_FASTREFS(h) (!DUK_HOBJECT_PROHIBITS_FASTREFS((h)))
6832
6833/* Flags used for property attributes in duk_propdesc and packed flags.
6834 * Must fit into 8 bits.
6835 */
6836#define DUK_PROPDESC_FLAG_WRITABLE (1U << 0) /* E5 Section 8.6.1 */
6837#define DUK_PROPDESC_FLAG_ENUMERABLE (1U << 1) /* E5 Section 8.6.1 */
6838#define DUK_PROPDESC_FLAG_CONFIGURABLE (1U << 2) /* E5 Section 8.6.1 */
6839#define DUK_PROPDESC_FLAG_ACCESSOR (1U << 3) /* accessor */
6840#define DUK_PROPDESC_FLAG_VIRTUAL \
6841 (1U << 4) /* property is virtual: used in duk_propdesc, never stored \
6842 * (used by e.g. buffer virtual properties) \
6843 */
6844#define DUK_PROPDESC_FLAGS_MASK \
6845 (DUK_PROPDESC_FLAG_WRITABLE | DUK_PROPDESC_FLAG_ENUMERABLE | DUK_PROPDESC_FLAG_CONFIGURABLE | DUK_PROPDESC_FLAG_ACCESSOR)
6846
6847/* Additional flags which are passed in the same flags argument as property
6848 * flags but are not stored in object properties.
6849 */
6850#define DUK_PROPDESC_FLAG_NO_OVERWRITE (1U << 4) /* internal define property: skip write silently if exists */
6852/* Convenience defines for property attributes. */
6853#define DUK_PROPDESC_FLAGS_NONE 0
6854#define DUK_PROPDESC_FLAGS_W (DUK_PROPDESC_FLAG_WRITABLE)
6855#define DUK_PROPDESC_FLAGS_E (DUK_PROPDESC_FLAG_ENUMERABLE)
6856#define DUK_PROPDESC_FLAGS_C (DUK_PROPDESC_FLAG_CONFIGURABLE)
6857#define DUK_PROPDESC_FLAGS_WE (DUK_PROPDESC_FLAG_WRITABLE | DUK_PROPDESC_FLAG_ENUMERABLE)
6858#define DUK_PROPDESC_FLAGS_WC (DUK_PROPDESC_FLAG_WRITABLE | DUK_PROPDESC_FLAG_CONFIGURABLE)
6859#define DUK_PROPDESC_FLAGS_EC (DUK_PROPDESC_FLAG_ENUMERABLE | DUK_PROPDESC_FLAG_CONFIGURABLE)
6860#define DUK_PROPDESC_FLAGS_WEC (DUK_PROPDESC_FLAG_WRITABLE | DUK_PROPDESC_FLAG_ENUMERABLE | DUK_PROPDESC_FLAG_CONFIGURABLE)
6862/* Flags for duk_hobject_get_own_propdesc() and variants. */
6863#define DUK_GETDESC_FLAG_PUSH_VALUE (1U << 0) /* push value to stack */
6864#define DUK_GETDESC_FLAG_IGNORE_PROTOLOOP (1U << 1) /* don't throw for prototype loop */
6865
6866/*
6867 * Macro for object validity check
6868 *
6869 * Assert for currently guaranteed relations between flags, for instance.
6870 */
6871
6872#if defined(DUK_USE_ASSERTIONS)
6873DUK_INTERNAL_DECL void duk_hobject_assert_valid(duk_hobject *h);
6874#define DUK_HOBJECT_ASSERT_VALID(h) \
6875 do { \
6876 duk_hobject_assert_valid((h)); \
6877 } while (0)
6878#else
6879#define DUK_HOBJECT_ASSERT_VALID(h) \
6880 do { \
6881 } while (0)
6882#endif
6883
6884/*
6885 * Macros to access the 'props' allocation.
6886 */
6887
6888#if defined(DUK_USE_HEAPPTR16)
6889#define DUK_HOBJECT_GET_PROPS(heap, h) ((duk_uint8_t *) DUK_USE_HEAPPTR_DEC16((heap)->heap_udata, ((duk_heaphdr *) (h))->h_extra16))
6890#define DUK_HOBJECT_SET_PROPS(heap, h, x) \
6891 do { \
6892 ((duk_heaphdr *) (h))->h_extra16 = DUK_USE_HEAPPTR_ENC16((heap)->heap_udata, (void *) (x)); \
6893 } while (0)
6894#else
6895#define DUK_HOBJECT_GET_PROPS(heap, h) ((h)->props)
6896#define DUK_HOBJECT_SET_PROPS(heap, h, x) \
6897 do { \
6898 (h)->props = (duk_uint8_t *) (x); \
6899 } while (0)
6900#endif
6901
6902#if defined(DUK_USE_HOBJECT_LAYOUT_1)
6903/* LAYOUT 1 */
6904#define DUK_HOBJECT_E_GET_KEY_BASE(heap, h) ((duk_hstring **) (void *) (DUK_HOBJECT_GET_PROPS((heap), (h))))
6905#define DUK_HOBJECT_E_GET_VALUE_BASE(heap, h) \
6906 ((duk_propvalue *) (void *) (DUK_HOBJECT_GET_PROPS((heap), (h)) + DUK_HOBJECT_GET_ESIZE((h)) * sizeof(duk_hstring *)))
6907#define DUK_HOBJECT_E_GET_FLAGS_BASE(heap, h) \
6908 ((duk_uint8_t *) (void *) (DUK_HOBJECT_GET_PROPS((heap), (h)) + \
6909 DUK_HOBJECT_GET_ESIZE((h)) * (sizeof(duk_hstring *) + sizeof(duk_propvalue))))
6910#define DUK_HOBJECT_A_GET_BASE(heap, h) \
6911 ((duk_tval *) (void *) (DUK_HOBJECT_GET_PROPS((heap), (h)) + \
6912 DUK_HOBJECT_GET_ESIZE((h)) * \
6913 (sizeof(duk_hstring *) + sizeof(duk_propvalue) + sizeof(duk_uint8_t))))
6914#define DUK_HOBJECT_H_GET_BASE(heap, h) \
6915 ((duk_uint32_t *) (void *) (DUK_HOBJECT_GET_PROPS((heap), (h)) + \
6916 DUK_HOBJECT_GET_ESIZE((h)) * \
6917 (sizeof(duk_hstring *) + sizeof(duk_propvalue) + sizeof(duk_uint8_t)) + \
6918 DUK_HOBJECT_GET_ASIZE((h)) * sizeof(duk_tval)))
6919#define DUK_HOBJECT_P_COMPUTE_SIZE(n_ent, n_arr, n_hash) \
6920 ((n_ent) * (sizeof(duk_hstring *) + sizeof(duk_propvalue) + sizeof(duk_uint8_t)) + (n_arr) * sizeof(duk_tval) + \
6921 (n_hash) * sizeof(duk_uint32_t))
6922#define DUK_HOBJECT_P_SET_REALLOC_PTRS(p_base, set_e_k, set_e_pv, set_e_f, set_a, set_h, n_ent, n_arr, n_hash) \
6923 do { \
6924 (set_e_k) = (duk_hstring **) (void *) (p_base); \
6925 (set_e_pv) = (duk_propvalue *) (void *) ((set_e_k) + (n_ent)); \
6926 (set_e_f) = (duk_uint8_t *) (void *) ((set_e_pv) + (n_ent)); \
6927 (set_a) = (duk_tval *) (void *) ((set_e_f) + (n_ent)); \
6928 (set_h) = (duk_uint32_t *) (void *) ((set_a) + (n_arr)); \
6929 } while (0)
6930#elif defined(DUK_USE_HOBJECT_LAYOUT_2)
6931/* LAYOUT 2 */
6932#if (DUK_USE_ALIGN_BY == 4)
6933#define DUK_HOBJECT_E_FLAG_PADDING(e_sz) ((4 - (e_sz)) & 0x03)
6934#elif (DUK_USE_ALIGN_BY == 8)
6935#define DUK_HOBJECT_E_FLAG_PADDING(e_sz) ((8 - (e_sz)) & 0x07)
6936#elif (DUK_USE_ALIGN_BY == 1)
6937#define DUK_HOBJECT_E_FLAG_PADDING(e_sz) 0
6938#else
6939#error invalid DUK_USE_ALIGN_BY
6940#endif
6941#define DUK_HOBJECT_E_GET_KEY_BASE(heap, h) \
6942 ((duk_hstring **) (void *) (DUK_HOBJECT_GET_PROPS((heap), (h)) + DUK_HOBJECT_GET_ESIZE((h)) * sizeof(duk_propvalue)))
6943#define DUK_HOBJECT_E_GET_VALUE_BASE(heap, h) ((duk_propvalue *) (void *) (DUK_HOBJECT_GET_PROPS((heap), (h))))
6944#define DUK_HOBJECT_E_GET_FLAGS_BASE(heap, h) \
6945 ((duk_uint8_t *) (void *) (DUK_HOBJECT_GET_PROPS((heap), (h)) + \
6946 DUK_HOBJECT_GET_ESIZE((h)) * (sizeof(duk_hstring *) + sizeof(duk_propvalue))))
6947#define DUK_HOBJECT_A_GET_BASE(heap, h) \
6948 ((duk_tval *) (void *) (DUK_HOBJECT_GET_PROPS((heap), (h)) + \
6949 DUK_HOBJECT_GET_ESIZE((h)) * \
6950 (sizeof(duk_hstring *) + sizeof(duk_propvalue) + sizeof(duk_uint8_t)) + \
6951 DUK_HOBJECT_E_FLAG_PADDING(DUK_HOBJECT_GET_ESIZE((h)))))
6952#define DUK_HOBJECT_H_GET_BASE(heap, h) \
6953 ((duk_uint32_t *) (void *) (DUK_HOBJECT_GET_PROPS((heap), (h)) + \
6954 DUK_HOBJECT_GET_ESIZE((h)) * \
6955 (sizeof(duk_hstring *) + sizeof(duk_propvalue) + sizeof(duk_uint8_t)) + \
6956 DUK_HOBJECT_E_FLAG_PADDING(DUK_HOBJECT_GET_ESIZE((h))) + \
6957 DUK_HOBJECT_GET_ASIZE((h)) * sizeof(duk_tval)))
6958#define DUK_HOBJECT_P_COMPUTE_SIZE(n_ent, n_arr, n_hash) \
6959 ((n_ent) * (sizeof(duk_hstring *) + sizeof(duk_propvalue) + sizeof(duk_uint8_t)) + DUK_HOBJECT_E_FLAG_PADDING((n_ent)) + \
6960 (n_arr) * sizeof(duk_tval) + (n_hash) * sizeof(duk_uint32_t))
6961#define DUK_HOBJECT_P_SET_REALLOC_PTRS(p_base, set_e_k, set_e_pv, set_e_f, set_a, set_h, n_ent, n_arr, n_hash) \
6962 do { \
6963 (set_e_pv) = (duk_propvalue *) (void *) (p_base); \
6964 (set_e_k) = (duk_hstring **) (void *) ((set_e_pv) + (n_ent)); \
6965 (set_e_f) = (duk_uint8_t *) (void *) ((set_e_k) + (n_ent)); \
6966 (set_a) = (duk_tval *) (void *) (((duk_uint8_t *) (set_e_f)) + sizeof(duk_uint8_t) * (n_ent) + \
6967 DUK_HOBJECT_E_FLAG_PADDING((n_ent))); \
6968 (set_h) = (duk_uint32_t *) (void *) ((set_a) + (n_arr)); \
6969 } while (0)
6970#elif defined(DUK_USE_HOBJECT_LAYOUT_3)
6971/* LAYOUT 3 */
6972#define DUK_HOBJECT_E_GET_KEY_BASE(heap, h) \
6973 ((duk_hstring **) (void *) (DUK_HOBJECT_GET_PROPS((heap), (h)) + DUK_HOBJECT_GET_ESIZE((h)) * sizeof(duk_propvalue) + \
6974 DUK_HOBJECT_GET_ASIZE((h)) * sizeof(duk_tval)))
6975#define DUK_HOBJECT_E_GET_VALUE_BASE(heap, h) ((duk_propvalue *) (void *) (DUK_HOBJECT_GET_PROPS((heap), (h))))
6976#define DUK_HOBJECT_E_GET_FLAGS_BASE(heap, h) \
6977 ((duk_uint8_t *) (void *) (DUK_HOBJECT_GET_PROPS((heap), (h)) + \
6978 DUK_HOBJECT_GET_ESIZE((h)) * (sizeof(duk_propvalue) + sizeof(duk_hstring *)) + \
6979 DUK_HOBJECT_GET_ASIZE((h)) * sizeof(duk_tval) + \
6980 DUK_HOBJECT_GET_HSIZE((h)) * sizeof(duk_uint32_t)))
6981#define DUK_HOBJECT_A_GET_BASE(heap, h) \
6982 ((duk_tval *) (void *) (DUK_HOBJECT_GET_PROPS((heap), (h)) + DUK_HOBJECT_GET_ESIZE((h)) * sizeof(duk_propvalue)))
6983#define DUK_HOBJECT_H_GET_BASE(heap, h) \
6984 ((duk_uint32_t *) (void *) (DUK_HOBJECT_GET_PROPS((heap), (h)) + \
6985 DUK_HOBJECT_GET_ESIZE((h)) * (sizeof(duk_propvalue) + sizeof(duk_hstring *)) + \
6986 DUK_HOBJECT_GET_ASIZE((h)) * sizeof(duk_tval)))
6987#define DUK_HOBJECT_P_COMPUTE_SIZE(n_ent, n_arr, n_hash) \
6988 ((n_ent) * (sizeof(duk_propvalue) + sizeof(duk_hstring *) + sizeof(duk_uint8_t)) + (n_arr) * sizeof(duk_tval) + \
6989 (n_hash) * sizeof(duk_uint32_t))
6990#define DUK_HOBJECT_P_SET_REALLOC_PTRS(p_base, set_e_k, set_e_pv, set_e_f, set_a, set_h, n_ent, n_arr, n_hash) \
6991 do { \
6992 (set_e_pv) = (duk_propvalue *) (void *) (p_base); \
6993 (set_a) = (duk_tval *) (void *) ((set_e_pv) + (n_ent)); \
6994 (set_e_k) = (duk_hstring **) (void *) ((set_a) + (n_arr)); \
6995 (set_h) = (duk_uint32_t *) (void *) ((set_e_k) + (n_ent)); \
6996 (set_e_f) = (duk_uint8_t *) (void *) ((set_h) + (n_hash)); \
6997 } while (0)
6998#else
6999#error invalid hobject layout defines
7000#endif /* hobject property layout */
7001
7002#define DUK_HOBJECT_P_ALLOC_SIZE(h) \
7003 DUK_HOBJECT_P_COMPUTE_SIZE(DUK_HOBJECT_GET_ESIZE((h)), DUK_HOBJECT_GET_ASIZE((h)), DUK_HOBJECT_GET_HSIZE((h)))
7005#define DUK_HOBJECT_E_GET_KEY(heap, h, i) (DUK_HOBJECT_E_GET_KEY_BASE((heap), (h))[(i)])
7006#define DUK_HOBJECT_E_GET_KEY_PTR(heap, h, i) (&DUK_HOBJECT_E_GET_KEY_BASE((heap), (h))[(i)])
7007#define DUK_HOBJECT_E_GET_VALUE(heap, h, i) (DUK_HOBJECT_E_GET_VALUE_BASE((heap), (h))[(i)])
7008#define DUK_HOBJECT_E_GET_VALUE_PTR(heap, h, i) (&DUK_HOBJECT_E_GET_VALUE_BASE((heap), (h))[(i)])
7009#define DUK_HOBJECT_E_GET_VALUE_TVAL(heap, h, i) (DUK_HOBJECT_E_GET_VALUE((heap), (h), (i)).v)
7010#define DUK_HOBJECT_E_GET_VALUE_TVAL_PTR(heap, h, i) (&DUK_HOBJECT_E_GET_VALUE((heap), (h), (i)).v)
7011#define DUK_HOBJECT_E_GET_VALUE_GETTER(heap, h, i) (DUK_HOBJECT_E_GET_VALUE((heap), (h), (i)).a.get)
7012#define DUK_HOBJECT_E_GET_VALUE_GETTER_PTR(heap, h, i) (&DUK_HOBJECT_E_GET_VALUE((heap), (h), (i)).a.get)
7013#define DUK_HOBJECT_E_GET_VALUE_SETTER(heap, h, i) (DUK_HOBJECT_E_GET_VALUE((heap), (h), (i)).a.set)
7014#define DUK_HOBJECT_E_GET_VALUE_SETTER_PTR(heap, h, i) (&DUK_HOBJECT_E_GET_VALUE((heap), (h), (i)).a.set)
7015#define DUK_HOBJECT_E_GET_FLAGS(heap, h, i) (DUK_HOBJECT_E_GET_FLAGS_BASE((heap), (h))[(i)])
7016#define DUK_HOBJECT_E_GET_FLAGS_PTR(heap, h, i) (&DUK_HOBJECT_E_GET_FLAGS_BASE((heap), (h))[(i)])
7017#define DUK_HOBJECT_A_GET_VALUE(heap, h, i) (DUK_HOBJECT_A_GET_BASE((heap), (h))[(i)])
7018#define DUK_HOBJECT_A_GET_VALUE_PTR(heap, h, i) (&DUK_HOBJECT_A_GET_BASE((heap), (h))[(i)])
7019#define DUK_HOBJECT_H_GET_INDEX(heap, h, i) (DUK_HOBJECT_H_GET_BASE((heap), (h))[(i)])
7020#define DUK_HOBJECT_H_GET_INDEX_PTR(heap, h, i) (&DUK_HOBJECT_H_GET_BASE((heap), (h))[(i)])
7021
7022#define DUK_HOBJECT_E_SET_KEY(heap, h, i, k) \
7023 do { \
7024 DUK_HOBJECT_E_GET_KEY((heap), (h), (i)) = (k); \
7025 } while (0)
7026#define DUK_HOBJECT_E_SET_VALUE(heap, h, i, v) \
7027 do { \
7028 DUK_HOBJECT_E_GET_VALUE((heap), (h), (i)) = (v); \
7029 } while (0)
7030#define DUK_HOBJECT_E_SET_VALUE_TVAL(heap, h, i, v) \
7031 do { \
7032 DUK_HOBJECT_E_GET_VALUE((heap), (h), (i)).v = (v); \
7033 } while (0)
7034#define DUK_HOBJECT_E_SET_VALUE_GETTER(heap, h, i, v) \
7035 do { \
7036 DUK_HOBJECT_E_GET_VALUE((heap), (h), (i)).a.get = (v); \
7037 } while (0)
7038#define DUK_HOBJECT_E_SET_VALUE_SETTER(heap, h, i, v) \
7039 do { \
7040 DUK_HOBJECT_E_GET_VALUE((heap), (h), (i)).a.set = (v); \
7041 } while (0)
7042#define DUK_HOBJECT_E_SET_FLAGS(heap, h, i, f) \
7043 do { \
7044 DUK_HOBJECT_E_GET_FLAGS((heap), (h), (i)) = (duk_uint8_t) (f); \
7045 } while (0)
7046#define DUK_HOBJECT_A_SET_VALUE(heap, h, i, v) \
7047 do { \
7048 DUK_HOBJECT_A_GET_VALUE((heap), (h), (i)) = (v); \
7049 } while (0)
7050#define DUK_HOBJECT_A_SET_VALUE_TVAL(heap, h, i, v) DUK_HOBJECT_A_SET_VALUE((heap), (h), (i), (v)) /* alias for above */
7051#define DUK_HOBJECT_H_SET_INDEX(heap, h, i, v) \
7052 do { \
7053 DUK_HOBJECT_H_GET_INDEX((heap), (h), (i)) = (v); \
7054 } while (0)
7055
7056#define DUK_HOBJECT_E_SET_FLAG_BITS(heap, h, i, mask) \
7057 do { \
7058 DUK_HOBJECT_E_GET_FLAGS_BASE((heap), (h))[(i)] |= (mask); \
7059 } while (0)
7060
7061#define DUK_HOBJECT_E_CLEAR_FLAG_BITS(heap, h, i, mask) \
7062 do { \
7063 DUK_HOBJECT_E_GET_FLAGS_BASE((heap), (h))[(i)] &= ~(mask); \
7064 } while (0)
7066#define DUK_HOBJECT_E_SLOT_IS_WRITABLE(heap, h, i) ((DUK_HOBJECT_E_GET_FLAGS((heap), (h), (i)) & DUK_PROPDESC_FLAG_WRITABLE) != 0)
7067#define DUK_HOBJECT_E_SLOT_IS_ENUMERABLE(heap, h, i) \
7068 ((DUK_HOBJECT_E_GET_FLAGS((heap), (h), (i)) & DUK_PROPDESC_FLAG_ENUMERABLE) != 0)
7069#define DUK_HOBJECT_E_SLOT_IS_CONFIGURABLE(heap, h, i) \
7070 ((DUK_HOBJECT_E_GET_FLAGS((heap), (h), (i)) & DUK_PROPDESC_FLAG_CONFIGURABLE) != 0)
7071#define DUK_HOBJECT_E_SLOT_IS_ACCESSOR(heap, h, i) ((DUK_HOBJECT_E_GET_FLAGS((heap), (h), (i)) & DUK_PROPDESC_FLAG_ACCESSOR) != 0)
7073#define DUK_HOBJECT_E_SLOT_SET_WRITABLE(heap, h, i) DUK_HOBJECT_E_SET_FLAG_BITS((heap), (h), (i), DUK_PROPDESC_FLAG_WRITABLE)
7074#define DUK_HOBJECT_E_SLOT_SET_ENUMERABLE(heap, h, i) DUK_HOBJECT_E_SET_FLAG_BITS((heap), (h), (i), DUK_PROPDESC_FLAG_ENUMERABLE)
7075#define DUK_HOBJECT_E_SLOT_SET_CONFIGURABLE(heap, h, i) \
7076 DUK_HOBJECT_E_SET_FLAG_BITS((heap), (h), (i), DUK_PROPDESC_FLAG_CONFIGURABLE)
7077#define DUK_HOBJECT_E_SLOT_SET_ACCESSOR(heap, h, i) DUK_HOBJECT_E_SET_FLAG_BITS((heap), (h), (i), DUK_PROPDESC_FLAG_ACCESSOR)
7079#define DUK_HOBJECT_E_SLOT_CLEAR_WRITABLE(heap, h, i) DUK_HOBJECT_E_CLEAR_FLAG_BITS((heap), (h), (i), DUK_PROPDESC_FLAG_WRITABLE)
7080#define DUK_HOBJECT_E_SLOT_CLEAR_ENUMERABLE(heap, h, i) \
7081 DUK_HOBJECT_E_CLEAR_FLAG_BITS((heap), (h), (i), DUK_PROPDESC_FLAG_ENUMERABLE)
7082#define DUK_HOBJECT_E_SLOT_CLEAR_CONFIGURABLE(heap, h, i) \
7083 DUK_HOBJECT_E_CLEAR_FLAG_BITS((heap), (h), (i), DUK_PROPDESC_FLAG_CONFIGURABLE)
7084#define DUK_HOBJECT_E_SLOT_CLEAR_ACCESSOR(heap, h, i) DUK_HOBJECT_E_CLEAR_FLAG_BITS((heap), (h), (i), DUK_PROPDESC_FLAG_ACCESSOR)
7086#define DUK_PROPDESC_IS_WRITABLE(p) (((p)->flags & DUK_PROPDESC_FLAG_WRITABLE) != 0)
7087#define DUK_PROPDESC_IS_ENUMERABLE(p) (((p)->flags & DUK_PROPDESC_FLAG_ENUMERABLE) != 0)
7088#define DUK_PROPDESC_IS_CONFIGURABLE(p) (((p)->flags & DUK_PROPDESC_FLAG_CONFIGURABLE) != 0)
7089#define DUK_PROPDESC_IS_ACCESSOR(p) (((p)->flags & DUK_PROPDESC_FLAG_ACCESSOR) != 0)
7091#define DUK_HOBJECT_HASHIDX_UNUSED 0xffffffffUL
7092#define DUK_HOBJECT_HASHIDX_DELETED 0xfffffffeUL
7093
7094/*
7095 * Macros for accessing size fields
7096 */
7097
7098#if defined(DUK_USE_OBJSIZES16)
7099#define DUK_HOBJECT_GET_ESIZE(h) ((h)->e_size16)
7100#define DUK_HOBJECT_SET_ESIZE(h, v) \
7101 do { \
7102 (h)->e_size16 = (v); \
7103 } while (0)
7104#define DUK_HOBJECT_GET_ENEXT(h) ((h)->e_next16)
7105#define DUK_HOBJECT_SET_ENEXT(h, v) \
7106 do { \
7107 (h)->e_next16 = (v); \
7108 } while (0)
7109#define DUK_HOBJECT_POSTINC_ENEXT(h) ((h)->e_next16++)
7110#define DUK_HOBJECT_GET_ASIZE(h) ((h)->a_size16)
7111#define DUK_HOBJECT_SET_ASIZE(h, v) \
7112 do { \
7113 (h)->a_size16 = (v); \
7114 } while (0)
7115#if defined(DUK_USE_HOBJECT_HASH_PART)
7116#define DUK_HOBJECT_GET_HSIZE(h) ((h)->h_size16)
7117#define DUK_HOBJECT_SET_HSIZE(h, v) \
7118 do { \
7119 (h)->h_size16 = (v); \
7120 } while (0)
7121#else
7122#define DUK_HOBJECT_GET_HSIZE(h) 0
7123#define DUK_HOBJECT_SET_HSIZE(h, v) \
7124 do { \
7125 DUK_ASSERT((v) == 0); \
7126 } while (0)
7127#endif
7128#else
7129#define DUK_HOBJECT_GET_ESIZE(h) ((h)->e_size)
7130#define DUK_HOBJECT_SET_ESIZE(h, v) \
7131 do { \
7132 (h)->e_size = (v); \
7133 } while (0)
7134#define DUK_HOBJECT_GET_ENEXT(h) ((h)->e_next)
7135#define DUK_HOBJECT_SET_ENEXT(h, v) \
7136 do { \
7137 (h)->e_next = (v); \
7138 } while (0)
7139#define DUK_HOBJECT_POSTINC_ENEXT(h) ((h)->e_next++)
7140#define DUK_HOBJECT_GET_ASIZE(h) ((h)->a_size)
7141#define DUK_HOBJECT_SET_ASIZE(h, v) \
7142 do { \
7143 (h)->a_size = (v); \
7144 } while (0)
7145#if defined(DUK_USE_HOBJECT_HASH_PART)
7146#define DUK_HOBJECT_GET_HSIZE(h) ((h)->h_size)
7147#define DUK_HOBJECT_SET_HSIZE(h, v) \
7148 do { \
7149 (h)->h_size = (v); \
7150 } while (0)
7151#else
7152#define DUK_HOBJECT_GET_HSIZE(h) 0
7153#define DUK_HOBJECT_SET_HSIZE(h, v) \
7154 do { \
7155 DUK_ASSERT((v) == 0); \
7156 } while (0)
7157#endif
7158#endif
7159
7160/*
7161 * Misc
7162 */
7163
7164/* Maximum prototype traversal depth. Sanity limit which handles e.g.
7165 * prototype loops (even complex ones like 1->2->3->4->2->3->4->2->3->4).
7166 */
7167#define DUK_HOBJECT_PROTOTYPE_CHAIN_SANITY 10000L
7168
7169/*
7170 * ECMAScript [[Class]]
7171 */
7173/* range check not necessary because all 4-bit values are mapped */
7174#define DUK_HOBJECT_CLASS_NUMBER_TO_STRIDX(n) duk_class_number_to_stridx[(n)]
7175
7176#define DUK_HOBJECT_GET_CLASS_STRING(heap, h) \
7177 DUK_HEAP_GET_STRING((heap), DUK_HOBJECT_CLASS_NUMBER_TO_STRIDX(DUK_HOBJECT_GET_CLASS_NUMBER((h))))
7178
7179/*
7180 * Macros for property handling
7181 */
7182
7183#if defined(DUK_USE_HEAPPTR16)
7184#define DUK_HOBJECT_GET_PROTOTYPE(heap, h) ((duk_hobject *) DUK_USE_HEAPPTR_DEC16((heap)->heap_udata, (h)->prototype16))
7185#define DUK_HOBJECT_SET_PROTOTYPE(heap, h, x) \
7186 do { \
7187 (h)->prototype16 = DUK_USE_HEAPPTR_ENC16((heap)->heap_udata, (void *) (x)); \
7188 } while (0)
7189#else
7190#define DUK_HOBJECT_GET_PROTOTYPE(heap, h) ((h)->prototype)
7191#define DUK_HOBJECT_SET_PROTOTYPE(heap, h, x) \
7192 do { \
7193 (h)->prototype = (x); \
7194 } while (0)
7195#endif
7197/* Set prototype, DECREF earlier value, INCREF new value (tolerating NULLs). */
7198#define DUK_HOBJECT_SET_PROTOTYPE_UPDREF(thr, h, p) duk_hobject_set_prototype_updref((thr), (h), (p))
7199
7200/* Set initial prototype, assume NULL previous prototype, INCREF new value,
7201 * tolerate NULL.
7202 */
7203#define DUK_HOBJECT_SET_PROTOTYPE_INIT_INCREF(thr, h, proto) \
7204 do { \
7205 duk_hthread *duk__thr = (thr); \
7206 duk_hobject *duk__obj = (h); \
7207 duk_hobject *duk__proto = (proto); \
7208 DUK_UNREF(duk__thr); \
7209 DUK_ASSERT(DUK_HOBJECT_GET_PROTOTYPE(duk__thr->heap, duk__obj) == NULL); \
7210 DUK_HOBJECT_SET_PROTOTYPE(duk__thr->heap, duk__obj, duk__proto); \
7211 DUK_HOBJECT_INCREF_ALLOWNULL(duk__thr, duk__proto); \
7212 } while (0)
7213
7214/*
7215 * Finalizer check
7216 */
7217
7218#if defined(DUK_USE_HEAPPTR16)
7219#define DUK_HOBJECT_HAS_FINALIZER_FAST(heap, h) duk_hobject_has_finalizer_fast_raw((heap), (h))
7220#else
7221#define DUK_HOBJECT_HAS_FINALIZER_FAST(heap, h) duk_hobject_has_finalizer_fast_raw((h))
7222#endif
7223
7224/*
7225 * Resizing and hash behavior
7226 */
7227
7228/* Sanity limit on max number of properties (allocated, not necessarily used).
7229 * This is somewhat arbitrary, but if we're close to 2**32 properties some
7230 * algorithms will fail (e.g. hash size selection, next prime selection).
7231 * Also, we use negative array/entry table indices to indicate 'not found',
7232 * so anything above 0x80000000 will cause trouble now.
7233 */
7234#if defined(DUK_USE_OBJSIZES16)
7235#define DUK_HOBJECT_MAX_PROPERTIES 0x0000ffffUL
7236#else
7237#define DUK_HOBJECT_MAX_PROPERTIES 0x3fffffffUL /* 2**30-1 ~= 1G properties */
7238#endif
7239
7240/* internal align target for props allocation, must be 2*n for some n */
7241#if (DUK_USE_ALIGN_BY == 4)
7242#define DUK_HOBJECT_ALIGN_TARGET 4
7243#elif (DUK_USE_ALIGN_BY == 8)
7244#define DUK_HOBJECT_ALIGN_TARGET 8
7245#elif (DUK_USE_ALIGN_BY == 1)
7246#define DUK_HOBJECT_ALIGN_TARGET 1
7247#else
7248#error invalid DUK_USE_ALIGN_BY
7249#endif
7250
7251/*
7252 * PC-to-line constants
7254
7255#define DUK_PC2LINE_SKIP 64
7257/* maximum length for a SKIP-1 diffstream: 35 bits per entry, rounded up to bytes */
7258#define DUK_PC2LINE_MAX_DIFF_LENGTH (((DUK_PC2LINE_SKIP - 1) * 35 + 7) / 8)
7259
7260/*
7261 * Struct defs
7268
7269union duk_propvalue {
7270 /* The get/set pointers could be 16-bit pointer compressed but it
7271 * would make no difference on 32-bit platforms because duk_tval is
7272 * 8 bytes or more anyway.
7274 duk_tval v;
7277
7279 /* read-only values 'lifted' for ease of use */
7284 /* for updating (all are set to < 0 for virtual properties) */
7285 duk_int_t e_idx; /* prop index in 'entry part', < 0 if not there */
7286 duk_int_t h_idx; /* prop index in 'hash part', < 0 if not there */
7287 duk_int_t a_idx; /* prop index in 'array part', < 0 if not there */
7290struct duk_hobject {
7292
7293 /*
7294 * 'props' contains {key,value,flags} entries, optional array entries, and
7295 * an optional hash lookup table for non-array entries in a single 'sliced'
7296 * allocation. There are several layout options, which differ slightly in
7297 * generated code size/speed and alignment/padding; duk_features.h selects
7298 * the layout used.
7299 *
7300 * Layout 1 (DUK_USE_HOBJECT_LAYOUT_1):
7301 *
7302 * e_size * sizeof(duk_hstring *) bytes of entry keys (e_next gc reachable)
7303 * e_size * sizeof(duk_propvalue) bytes of entry values (e_next gc reachable)
7304 * e_size * sizeof(duk_uint8_t) bytes of entry flags (e_next gc reachable)
7305 * a_size * sizeof(duk_tval) bytes of (opt) array values (plain only) (all gc reachable)
7306 * h_size * sizeof(duk_uint32_t) bytes of (opt) hash indexes to entries (e_size),
7307 * 0xffffffffUL = unused, 0xfffffffeUL = deleted
7308 *
7309 * Layout 2 (DUK_USE_HOBJECT_LAYOUT_2):
7310 *
7311 * e_size * sizeof(duk_propvalue) bytes of entry values (e_next gc reachable)
7312 * e_size * sizeof(duk_hstring *) bytes of entry keys (e_next gc reachable)
7313 * e_size * sizeof(duk_uint8_t) + pad bytes of entry flags (e_next gc reachable)
7314 * a_size * sizeof(duk_tval) bytes of (opt) array values (plain only) (all gc reachable)
7315 * h_size * sizeof(duk_uint32_t) bytes of (opt) hash indexes to entries (e_size),
7316 * 0xffffffffUL = unused, 0xfffffffeUL = deleted
7317 *
7318 * Layout 3 (DUK_USE_HOBJECT_LAYOUT_3):
7319 *
7320 * e_size * sizeof(duk_propvalue) bytes of entry values (e_next gc reachable)
7321 * a_size * sizeof(duk_tval) bytes of (opt) array values (plain only) (all gc reachable)
7322 * e_size * sizeof(duk_hstring *) bytes of entry keys (e_next gc reachable)
7323 * h_size * sizeof(duk_uint32_t) bytes of (opt) hash indexes to entries (e_size),
7324 * 0xffffffffUL = unused, 0xfffffffeUL = deleted
7325 * e_size * sizeof(duk_uint8_t) bytes of entry flags (e_next gc reachable)
7326 *
7327 * In layout 1, the 'e_next' count is rounded to 4 or 8 on platforms
7328 * requiring 4 or 8 byte alignment. This ensures proper alignment
7329 * for the entries, at the cost of memory footprint. However, it's
7330 * probably preferable to use another layout on such platforms instead.
7331 *
7332 * In layout 2, the key and value parts are swapped to avoid padding
7333 * the key array on platforms requiring alignment by 8. The flags part
7334 * is padded to get alignment for array entries. The 'e_next' count does
7335 * not need to be rounded as in layout 1.
7336 *
7337 * In layout 3, entry values and array values are always aligned properly,
7338 * and assuming pointers are at most 8 bytes, so are the entry keys. Hash
7339 * indices will be properly aligned (assuming pointers are at least 4 bytes).
7340 * Finally, flags don't need additional alignment. This layout provides
7341 * compact allocations without padding (even on platforms with alignment
7342 * requirements) at the cost of a bit slower lookups.
7343 *
7344 * Objects with few keys don't have a hash index; keys are looked up linearly,
7345 * which is cache efficient because the keys are consecutive. Larger objects
7346 * have a hash index part which contains integer indexes to the entries part.
7347 *
7348 * A single allocation reduces memory allocation overhead but requires more
7349 * work when any part needs to be resized. A sliced allocation for entries
7350 * makes linear key matching faster on most platforms (more locality) and
7351 * skimps on flags size (which would be followed by 3 bytes of padding in
7352 * most architectures if entries were placed in a struct).
7353 *
7354 * 'props' also contains internal properties distinguished with a non-BMP
7355 * prefix. Often used properties should be placed early in 'props' whenever
7356 * possible to make accessing them as fast a possible.
7357 */
7358
7359#if defined(DUK_USE_HEAPPTR16)
7360 /* Located in duk_heaphdr h_extra16. Subclasses of duk_hobject (like
7361 * duk_hcompfunc) are not free to use h_extra16 for this reason.
7363#else
7364 duk_uint8_t *props;
7365#endif
7366
7367 /* prototype: the only internal property lifted outside 'e' as it is so central */
7368#if defined(DUK_USE_HEAPPTR16)
7369 duk_uint16_t prototype16;
7370#else
7372#endif
7373
7374#if defined(DUK_USE_OBJSIZES16)
7375 duk_uint16_t e_size16;
7376 duk_uint16_t e_next16;
7377 duk_uint16_t a_size16;
7378#if defined(DUK_USE_HOBJECT_HASH_PART)
7379 duk_uint16_t h_size16;
7380#endif
7381#else
7382 duk_uint32_t e_size; /* entry part size */
7383 duk_uint32_t e_next; /* index for next new key ([0,e_next[ are gc reachable) */
7384 duk_uint32_t a_size; /* array part size (entirely gc reachable) */
7385#if defined(DUK_USE_HOBJECT_HASH_PART)
7386 duk_uint32_t h_size; /* hash part size or 0 if unused */
7387#endif
7388#endif
7389};
7390
7391/*
7392 * Exposed data
7393 */
7394
7395#if !defined(DUK_SINGLE_FILE)
7397#endif /* !DUK_SINGLE_FILE */
7398
7399/*
7400 * Prototypes
7401 */
7402
7403/* alloc and init */
7410#if defined(DUK_USE_BUFFEROBJECT_SUPPORT)
7412#endif
7418
7419/* resize */
7421 duk_hobject *obj,
7422 duk_uint32_t new_e_size,
7423 duk_uint32_t new_a_size,
7424 duk_uint32_t new_h_size,
7425 duk_bool_t abandon_array);
7426DUK_INTERNAL_DECL void duk_hobject_resize_entrypart(duk_hthread *thr, duk_hobject *obj, duk_uint32_t new_e_size);
7427#if 0 /*unused*/
7428DUK_INTERNAL_DECL void duk_hobject_resize_arraypart(duk_hthread *thr,
7429 duk_hobject *obj,
7430 duk_uint32_t new_a_size);
7431#endif
7432
7433/* low-level property functions */
7439 duk_hobject *obj,
7440 duk_hstring *key,
7441 duk_uint_t *out_attrs);
7445
7446/* core property functions */
7449duk_hobject_putprop(duk_hthread *thr, duk_tval *tv_obj, duk_tval *tv_key, duk_tval *tv_val, duk_bool_t throw_flag);
7453/* internal property functions */
7454#define DUK_DELPROP_FLAG_THROW (1U << 0)
7455#define DUK_DELPROP_FLAG_FORCE (1U << 1)
7459 duk_hobject *obj,
7460 duk_hstring *key,
7461 duk_small_uint_t flags);
7463 duk_hobject *obj,
7464 duk_uarridx_t arr_idx,
7465 duk_small_uint_t flags);
7467#if defined(DUK_USE_HEAPPTR16)
7469#else
7471#endif
7472
7473/* helpers for defineProperty() and defineProperties() */
7475 duk_idx_t idx_in,
7476 duk_uint_t *out_defprop_flags,
7477 duk_idx_t *out_idx_value,
7478 duk_hobject **out_getter,
7479 duk_hobject **out_setter);
7481 duk_uint_t defprop_flags,
7482 duk_hobject *obj,
7483 duk_hstring *key,
7484 duk_idx_t idx_value,
7485 duk_hobject *get,
7486 duk_hobject *set,
7487 duk_bool_t throw_flag);
7488
7489/* Object built-in methods */
7494
7495/* internal properties */
7500
7501/* hobject management functions */
7503
7504/* ES2015 proxy */
7505#if defined(DUK_USE_ES6_PROXY)
7508#endif
7509
7510/* enumeration */
7514
7515/* macros */
7517
7518/* pc2line */
7519#if defined(DUK_USE_PC2LINE)
7522#endif
7523
7524/* misc */
7526 duk_hobject *h,
7527 duk_hobject *p,
7528 duk_bool_t ignore_loop);
7529
7530#if !defined(DUK_USE_OBJECT_BUILTIN)
7531/* These declarations are needed when related built-in is disabled and
7532 * genbuiltins.py won't automatically emit the declerations.
7533 */
7536#endif
7537
7538#endif /* DUK_HOBJECT_H_INCLUDED */
7539/* #include duk_hcompfunc.h */
7540/*
7541 * Heap compiled function (ECMAScript function) representation.
7542 *
7543 * There is a single data buffer containing the ECMAScript function's
7544 * bytecode, constants, and inner functions.
7545 */
7547#if !defined(DUK_HCOMPFUNC_H_INCLUDED)
7548#define DUK_HCOMPFUNC_H_INCLUDED
7549
7550/*
7551 * Field accessor macros
7552 */
7553
7554/* XXX: casts could be improved, especially for GET/SET DATA */
7555
7556#if defined(DUK_USE_HEAPPTR16)
7557#define DUK_HCOMPFUNC_GET_DATA(heap, h) ((duk_hbuffer_fixed *) (void *) DUK_USE_HEAPPTR_DEC16((heap)->heap_udata, (h)->data16))
7558#define DUK_HCOMPFUNC_SET_DATA(heap, h, v) \
7559 do { \
7560 (h)->data16 = DUK_USE_HEAPPTR_ENC16((heap)->heap_udata, (void *) (v)); \
7561 } while (0)
7562#define DUK_HCOMPFUNC_GET_FUNCS(heap, h) ((duk_hobject **) (void *) (DUK_USE_HEAPPTR_DEC16((heap)->heap_udata, (h)->funcs16)))
7563#define DUK_HCOMPFUNC_SET_FUNCS(heap, h, v) \
7564 do { \
7565 (h)->funcs16 = DUK_USE_HEAPPTR_ENC16((heap)->heap_udata, (void *) (v)); \
7566 } while (0)
7567#define DUK_HCOMPFUNC_GET_BYTECODE(heap, h) ((duk_instr_t *) (void *) (DUK_USE_HEAPPTR_DEC16((heap)->heap_udata, (h)->bytecode16)))
7568#define DUK_HCOMPFUNC_SET_BYTECODE(heap, h, v) \
7569 do { \
7570 (h)->bytecode16 = DUK_USE_HEAPPTR_ENC16((heap)->heap_udata, (void *) (v)); \
7571 } while (0)
7572#define DUK_HCOMPFUNC_GET_LEXENV(heap, h) ((duk_hobject *) (void *) (DUK_USE_HEAPPTR_DEC16((heap)->heap_udata, (h)->lex_env16)))
7573#define DUK_HCOMPFUNC_SET_LEXENV(heap, h, v) \
7574 do { \
7575 (h)->lex_env16 = DUK_USE_HEAPPTR_ENC16((heap)->heap_udata, (void *) (v)); \
7576 } while (0)
7577#define DUK_HCOMPFUNC_GET_VARENV(heap, h) ((duk_hobject *) (void *) (DUK_USE_HEAPPTR_DEC16((heap)->heap_udata, (h)->var_env16)))
7578#define DUK_HCOMPFUNC_SET_VARENV(heap, h, v) \
7579 do { \
7580 (h)->var_env16 = DUK_USE_HEAPPTR_ENC16((heap)->heap_udata, (void *) (v)); \
7581 } while (0)
7582#else
7583#define DUK_HCOMPFUNC_GET_DATA(heap, h) ((duk_hbuffer_fixed *) (void *) (h)->data)
7584#define DUK_HCOMPFUNC_SET_DATA(heap, h, v) \
7585 do { \
7586 (h)->data = (duk_hbuffer *) (v); \
7587 } while (0)
7588#define DUK_HCOMPFUNC_GET_FUNCS(heap, h) ((h)->funcs)
7589#define DUK_HCOMPFUNC_SET_FUNCS(heap, h, v) \
7590 do { \
7591 (h)->funcs = (v); \
7592 } while (0)
7593#define DUK_HCOMPFUNC_GET_BYTECODE(heap, h) ((h)->bytecode)
7594#define DUK_HCOMPFUNC_SET_BYTECODE(heap, h, v) \
7595 do { \
7596 (h)->bytecode = (v); \
7597 } while (0)
7598#define DUK_HCOMPFUNC_GET_LEXENV(heap, h) ((h)->lex_env)
7599#define DUK_HCOMPFUNC_SET_LEXENV(heap, h, v) \
7600 do { \
7601 (h)->lex_env = (v); \
7602 } while (0)
7603#define DUK_HCOMPFUNC_GET_VARENV(heap, h) ((h)->var_env)
7604#define DUK_HCOMPFUNC_SET_VARENV(heap, h, v) \
7605 do { \
7606 (h)->var_env = (v); \
7607 } while (0)
7608#endif
7609
7610/*
7611 * Accessor macros for function specific data areas
7612 */
7614/* Note: assumes 'data' is always a fixed buffer */
7615#define DUK_HCOMPFUNC_GET_BUFFER_BASE(heap, h) DUK_HBUFFER_FIXED_GET_DATA_PTR((heap), DUK_HCOMPFUNC_GET_DATA((heap), (h)))
7616
7617#define DUK_HCOMPFUNC_GET_CONSTS_BASE(heap, h) ((duk_tval *) (void *) DUK_HCOMPFUNC_GET_BUFFER_BASE((heap), (h)))
7618
7619#define DUK_HCOMPFUNC_GET_FUNCS_BASE(heap, h) DUK_HCOMPFUNC_GET_FUNCS((heap), (h))
7620
7621#define DUK_HCOMPFUNC_GET_CODE_BASE(heap, h) DUK_HCOMPFUNC_GET_BYTECODE((heap), (h))
7622
7623#define DUK_HCOMPFUNC_GET_CONSTS_END(heap, h) ((duk_tval *) (void *) DUK_HCOMPFUNC_GET_FUNCS((heap), (h)))
7624
7625#define DUK_HCOMPFUNC_GET_FUNCS_END(heap, h) ((duk_hobject **) (void *) DUK_HCOMPFUNC_GET_BYTECODE((heap), (h)))
7627/* XXX: double evaluation of DUK_HCOMPFUNC_GET_DATA() */
7628#define DUK_HCOMPFUNC_GET_CODE_END(heap, h) \
7629 ((duk_instr_t *) (void *) (DUK_HBUFFER_FIXED_GET_DATA_PTR((heap), DUK_HCOMPFUNC_GET_DATA((heap), (h))) + \
7630 DUK_HBUFFER_GET_SIZE((duk_hbuffer *) DUK_HCOMPFUNC_GET_DATA((heap), h))))
7631
7632#define DUK_HCOMPFUNC_GET_CONSTS_SIZE(heap, h) \
7633 ((duk_size_t) (((const duk_uint8_t *) DUK_HCOMPFUNC_GET_CONSTS_END((heap), (h))) - \
7634 ((const duk_uint8_t *) DUK_HCOMPFUNC_GET_CONSTS_BASE((heap), (h)))))
7635
7636#define DUK_HCOMPFUNC_GET_FUNCS_SIZE(heap, h) \
7637 ((duk_size_t) (((const duk_uint8_t *) DUK_HCOMPFUNC_GET_FUNCS_END((heap), (h))) - \
7638 ((const duk_uint8_t *) DUK_HCOMPFUNC_GET_FUNCS_BASE((heap), (h)))))
7639
7640#define DUK_HCOMPFUNC_GET_CODE_SIZE(heap, h) \
7641 ((duk_size_t) (((const duk_uint8_t *) DUK_HCOMPFUNC_GET_CODE_END((heap), (h))) - \
7642 ((const duk_uint8_t *) DUK_HCOMPFUNC_GET_CODE_BASE((heap), (h)))))
7643
7644#define DUK_HCOMPFUNC_GET_CONSTS_COUNT(heap, h) ((duk_size_t) (DUK_HCOMPFUNC_GET_CONSTS_SIZE((heap), (h)) / sizeof(duk_tval)))
7645
7646#define DUK_HCOMPFUNC_GET_FUNCS_COUNT(heap, h) ((duk_size_t) (DUK_HCOMPFUNC_GET_FUNCS_SIZE((heap), (h)) / sizeof(duk_hobject *)))
7647
7648#define DUK_HCOMPFUNC_GET_CODE_COUNT(heap, h) ((duk_size_t) (DUK_HCOMPFUNC_GET_CODE_SIZE((heap), (h)) / sizeof(duk_instr_t)))
7649
7650/*
7651 * Validity assert
7652 */
7653
7654#if defined(DUK_USE_ASSERTIONS)
7655DUK_INTERNAL_DECL void duk_hcompfunc_assert_valid(duk_hcompfunc *h);
7656#define DUK_HCOMPFUNC_ASSERT_VALID(h) \
7657 do { \
7658 duk_hcompfunc_assert_valid((h)); \
7659 } while (0)
7660#else
7661#define DUK_HCOMPFUNC_ASSERT_VALID(h) \
7662 do { \
7663 } while (0)
7664#endif
7665
7666/*
7667 * Main struct
7669
7671 /* shared object part */
7673
7674 /*
7675 * Pointers to function data area for faster access. Function
7676 * data is a buffer shared between all closures of the same
7677 * "template" function. The data buffer is always fixed (non-
7678 * dynamic, hence stable), with a layout as follows:
7679 *
7680 * constants (duk_tval)
7681 * inner functions (duk_hobject *)
7682 * bytecode (duk_instr_t)
7683 *
7684 * Note: bytecode end address can be computed from 'data' buffer
7685 * size. It is not strictly necessary functionally, assuming
7686 * bytecode never jumps outside its allocated area. However,
7687 * it's a safety/robustness feature for avoiding the chance of
7688 * executing random data as bytecode due to a compiler error.
7689 *
7690 * Note: values in the data buffer must be incref'd (they will
7691 * be decref'd on release) for every compiledfunction referring
7692 * to the 'data' element.
7693 */
7694
7695 /* Data area, fixed allocation, stable data ptrs. */
7696#if defined(DUK_USE_HEAPPTR16)
7697 duk_uint16_t data16;
7698#else
7700#endif
7701
7702 /* No need for constants pointer (= same as data).
7703 *
7704 * When using 16-bit packing alignment to 4 is nice. 'funcs' will be
7705 * 4-byte aligned because 'constants' are duk_tvals. For now the
7706 * inner function pointers are not compressed, so that 'bytecode' will
7707 * also be 4-byte aligned.
7708 */
7709#if defined(DUK_USE_HEAPPTR16)
7710 duk_uint16_t funcs16;
7711 duk_uint16_t bytecode16;
7712#else
7715#endif
7716
7717 /* Lexenv: lexical environment of closure, NULL for templates.
7718 * Varenv: variable environment of closure, NULL for templates.
7719 */
7720#if defined(DUK_USE_HEAPPTR16)
7721 duk_uint16_t lex_env16;
7722 duk_uint16_t var_env16;
7723#else
7726#endif
7727
7728 /*
7729 * 'nregs' registers are allocated on function entry, at most 'nargs'
7730 * are initialized to arguments, and the rest to undefined. Arguments
7731 * above 'nregs' are not mapped to registers. All registers in the
7732 * active stack range must be initialized because they are GC reachable.
7733 * 'nargs' is needed so that if the function is given more than 'nargs'
7734 * arguments, the additional arguments do not 'clobber' registers
7735 * beyond 'nregs' which must be consistently initialized to undefined.
7736 *
7737 * Usually there is no need to know which registers are mapped to
7738 * local variables. Registers may be allocated to variable in any
7739 * way (even including gaps). However, a register-variable mapping
7740 * must be the same for the duration of the function execution and
7741 * the register cannot be used for anything else.
7742 *
7743 * When looking up variables by name, the '_Varmap' map is used.
7744 * When an activation closes, registers mapped to arguments are
7745 * copied into the environment record based on the same map. The
7746 * reverse map (from register to variable) is not currently needed
7747 * at run time, except for debugging, so it is not maintained.
7750 duk_uint16_t nregs; /* regs to allocate */
7751 duk_uint16_t nargs; /* number of arguments allocated to regs */
7752
7753 /*
7754 * Additional control information is placed into the object itself
7755 * as internal properties to avoid unnecessary fields for the
7756 * majority of functions. The compiler tries to omit internal
7757 * control fields when possible.
7758 *
7759 * Function templates:
7760 *
7761 * {
7762 * name: "func", // declaration, named function expressions
7763 * fileName: <debug info for creating nice errors>
7764 * _Varmap: { "arg1": 0, "arg2": 1, "varname": 2 },
7765 * _Formals: [ "arg1", "arg2" ],
7766 * _Source: "function func(arg1, arg2) { ... }",
7767 * _Pc2line: <debug info for pc-to-line mapping>,
7768 * }
7769 *
7770 * Function instances:
7771 *
7772 * {
7773 * length: 2,
7774 * prototype: { constructor: <func> },
7775 * caller: <thrower>,
7776 * arguments: <thrower>,
7777 * name: "func", // declaration, named function expressions
7778 * fileName: <debug info for creating nice errors>
7779 * _Varmap: { "arg1": 0, "arg2": 1, "varname": 2 },
7780 * _Formals: [ "arg1", "arg2" ],
7781 * _Source: "function func(arg1, arg2) { ... }",
7782 * _Pc2line: <debug info for pc-to-line mapping>,
7783 * }
7784 *
7785 * More detailed description of these properties can be found
7786 * in the documentation.
7787 */
7788
7789#if defined(DUK_USE_DEBUGGER_SUPPORT)
7790 /* Line number range for function. Needed during debugging to
7791 * determine active breakpoints.
7792 */
7793 duk_uint32_t start_line;
7794 duk_uint32_t end_line;
7795#endif
7796};
7797
7798#endif /* DUK_HCOMPFUNC_H_INCLUDED */
7799/* #include duk_hnatfunc.h */
7800/*
7801 * Heap native function representation.
7802 */
7804#if !defined(DUK_HNATFUNC_H_INCLUDED)
7805#define DUK_HNATFUNC_H_INCLUDED
7806
7807#if defined(DUK_USE_ASSERTIONS)
7808DUK_INTERNAL_DECL void duk_hnatfunc_assert_valid(duk_hnatfunc *h);
7809#define DUK_HNATFUNC_ASSERT_VALID(h) \
7810 do { \
7811 duk_hnatfunc_assert_valid((h)); \
7812 } while (0)
7813#else
7814#define DUK_HNATFUNC_ASSERT_VALID(h) \
7815 do { \
7816 } while (0)
7817#endif
7819#define DUK_HNATFUNC_NARGS_VARARGS ((duk_int16_t) -1)
7820#define DUK_HNATFUNC_NARGS_MAX ((duk_int16_t) 0x7fff)
7821
7823 /* shared object part */
7827 duk_int16_t nargs;
7828 duk_int16_t magic;
7829
7830 /* The 'magic' field allows an opaque 16-bit field to be accessed by the
7831 * Duktape/C function. This allows, for instance, the same native function
7832 * to be used for a set of very similar functions, with the 'magic' field
7833 * providing the necessary non-argument flags / values to guide the behavior
7834 * of the native function. The value is signed on purpose: it is easier to
7835 * convert a signed value to unsigned (simply AND with 0xffff) than vice
7836 * versa.
7837 *
7838 * Note: cannot place nargs/magic into the heaphdr flags, because
7839 * duk_hobject takes almost all flags already.
7840 */
7841};
7842
7843#endif /* DUK_HNATFUNC_H_INCLUDED */
7844/* #include duk_hboundfunc.h */
7845/*
7846 * Bound function representation.
7847 */
7849#if !defined(DUK_HBOUNDFUNC_H_INCLUDED)
7850#define DUK_HBOUNDFUNC_H_INCLUDED
7851
7852/* Artificial limit for args length. Ensures arithmetic won't overflow
7853 * 32 bits when combining bound functions.
7854 */
7855#define DUK_HBOUNDFUNC_MAX_ARGS 0x20000000UL
7856
7857#if defined(DUK_USE_ASSERTIONS)
7858DUK_INTERNAL_DECL void duk_hboundfunc_assert_valid(duk_hboundfunc *h);
7859#define DUK_HBOUNDFUNC_ASSERT_VALID(h) \
7860 do { \
7861 duk_hboundfunc_assert_valid((h)); \
7862 } while (0)
7863#else
7864#define DUK_HBOUNDFUNC_ASSERT_VALID(h) \
7865 do { \
7866 } while (0)
7867#endif
7868
7870 /* Shared object part. */
7872
7873 /* Final target function, stored as duk_tval so that lightfunc can be
7874 * represented too.
7875 */
7878 /* This binding. */
7881 /* Arguments to prepend. */
7882 duk_tval *args; /* Separate allocation. */
7884};
7885
7886#endif /* DUK_HBOUNDFUNC_H_INCLUDED */
7887/* #include duk_hbufobj.h */
7888/*
7889 * Heap Buffer object representation. Used for all Buffer variants.
7890 */
7892#if !defined(DUK_HBUFOBJ_H_INCLUDED)
7893#define DUK_HBUFOBJ_H_INCLUDED
7894
7895#if defined(DUK_USE_BUFFEROBJECT_SUPPORT)
7897/* All element accessors are host endian now (driven by TypedArray spec). */
7898#define DUK_HBUFOBJ_ELEM_UINT8 0
7899#define DUK_HBUFOBJ_ELEM_UINT8CLAMPED 1
7900#define DUK_HBUFOBJ_ELEM_INT8 2
7901#define DUK_HBUFOBJ_ELEM_UINT16 3
7902#define DUK_HBUFOBJ_ELEM_INT16 4
7903#define DUK_HBUFOBJ_ELEM_UINT32 5
7904#define DUK_HBUFOBJ_ELEM_INT32 6
7905#define DUK_HBUFOBJ_ELEM_FLOAT32 7
7906#define DUK_HBUFOBJ_ELEM_FLOAT64 8
7907#define DUK_HBUFOBJ_ELEM_MAX 8
7908
7909#if defined(DUK_USE_ASSERTIONS)
7910DUK_INTERNAL_DECL void duk_hbufobj_assert_valid(duk_hbufobj *h);
7911#define DUK_HBUFOBJ_ASSERT_VALID(h) \
7912 do { \
7913 duk_hbufobj_assert_valid((h)); \
7914 } while (0)
7915#else
7916#define DUK_HBUFOBJ_ASSERT_VALID(h) \
7917 do { \
7918 } while (0)
7919#endif
7920
7921/* Get the current data pointer (caller must ensure buf != NULL) as a
7922 * duk_uint8_t ptr. Note that the result may be NULL if the underlying
7923 * buffer has zero size and is not a fixed buffer.
7924 */
7925#define DUK_HBUFOBJ_GET_SLICE_BASE(heap, h) \
7926 (DUK_ASSERT_EXPR((h) != NULL), \
7927 DUK_ASSERT_EXPR((h)->buf != NULL), \
7928 (((duk_uint8_t *) DUK_HBUFFER_GET_DATA_PTR((heap), (h)->buf)) + (h)->offset))
7929
7930/* True if slice is full, i.e. offset is zero and length covers the entire
7931 * buffer. This status may change independently of the duk_hbufobj if
7932 * the underlying buffer is dynamic and changes without the hbufobj
7933 * being changed.
7934 */
7935#define DUK_HBUFOBJ_FULL_SLICE(h) \
7936 (DUK_ASSERT_EXPR((h) != NULL), \
7937 DUK_ASSERT_EXPR((h)->buf != NULL), \
7938 ((h)->offset == 0 && (h)->length == DUK_HBUFFER_GET_SIZE((h)->buf)))
7939
7940/* Validate that the whole slice [0,length[ is contained in the underlying
7941 * buffer. Caller must ensure 'buf' != NULL.
7942 */
7943#define DUK_HBUFOBJ_VALID_SLICE(h) \
7944 (DUK_ASSERT_EXPR((h) != NULL), \
7945 DUK_ASSERT_EXPR((h)->buf != NULL), \
7946 ((h)->offset + (h)->length <= DUK_HBUFFER_GET_SIZE((h)->buf)))
7947
7948/* Validate byte read/write for virtual 'offset', i.e. check that the
7949 * offset, taking into account h->offset, is within the underlying
7950 * buffer size. This is a safety check which is needed to ensure
7951 * that even a misconfigured duk_hbufobj never causes memory unsafe
7952 * behavior (e.g. if an underlying dynamic buffer changes after being
7953 * setup). Caller must ensure 'buf' != NULL.
7954 */
7955#define DUK_HBUFOBJ_VALID_BYTEOFFSET_INCL(h, off) \
7956 (DUK_ASSERT_EXPR((h) != NULL), DUK_ASSERT_EXPR((h)->buf != NULL), ((h)->offset + (off) < DUK_HBUFFER_GET_SIZE((h)->buf)))
7957
7958#define DUK_HBUFOBJ_VALID_BYTEOFFSET_EXCL(h, off) \
7959 (DUK_ASSERT_EXPR((h) != NULL), DUK_ASSERT_EXPR((h)->buf != NULL), ((h)->offset + (off) <= DUK_HBUFFER_GET_SIZE((h)->buf)))
7960
7961/* Clamp an input byte length (already assumed to be within the nominal
7962 * duk_hbufobj 'length') to the current dynamic buffer limits to yield
7963 * a byte length limit that's safe for memory accesses. This value can
7964 * be invalidated by any side effect because it may trigger a user
7965 * callback that resizes the underlying buffer.
7966 */
7967#define DUK_HBUFOBJ_CLAMP_BYTELENGTH(h, len) (DUK_ASSERT_EXPR((h) != NULL), duk_hbufobj_clamp_bytelength((h), (len)))
7969/* Typed arrays have virtual indices, ArrayBuffer and DataView do not. */
7970#define DUK_HBUFOBJ_HAS_VIRTUAL_INDICES(h) ((h)->is_typedarray)
7971
7973 /* Shared object part. */
7976 /* Underlying buffer (refcounted), may be NULL. */
7979 /* .buffer reference to an ArrayBuffer, may be NULL. */
7981
7982 /* Slice and accessor information.
7983 *
7984 * Because the underlying buffer may be dynamic, these may be
7985 * invalidated by the buffer being modified so that both offset
7986 * and length should be validated before every access. Behavior
7987 * when the underlying buffer has changed doesn't need to be clean:
7988 * virtual 'length' doesn't need to be affected, reads can return
7989 * zero/NaN, and writes can be ignored.
7990 *
7991 * Note that a data pointer cannot be precomputed because 'buf' may
7992 * be dynamic and its pointer unstable.
7995 duk_uint_t offset; /* byte offset to buf */
7996 duk_uint_t length; /* byte index limit for element access, exclusive */
7997 duk_uint8_t shift; /* element size shift:
7998 * 0 = u8/i8
7999 * 1 = u16/i16
8000 * 2 = u32/i32/float
8001 * 3 = double
8003 duk_uint8_t elem_type; /* element type */
8004 duk_uint8_t is_typedarray;
8005};
8006
8010 duk_hbufobj *h_bufobj,
8011 duk_uint8_t *p,
8012 duk_small_uint_t elem_size);
8014 duk_hbufobj *h_bufobj,
8015 duk_uint8_t *p,
8016 duk_small_uint_t elem_size);
8018
8019#else /* DUK_USE_BUFFEROBJECT_SUPPORT */
8020
8021/* nothing */
8022
8023#endif /* DUK_USE_BUFFEROBJECT_SUPPORT */
8024#endif /* DUK_HBUFOBJ_H_INCLUDED */
8025/* #include duk_hthread.h */
8026/*
8027 * Heap thread object representation.
8028 *
8029 * duk_hthread is also the 'context' for public API functions via a
8030 * different typedef. Most API calls operate on the topmost frame
8031 * of the value stack only.
8032 */
8034#if !defined(DUK_HTHREAD_H_INCLUDED)
8035#define DUK_HTHREAD_H_INCLUDED
8036
8037/*
8038 * Stack constants
8039 */
8041/* Initial valstack size, roughly 0.7kiB. */
8042#define DUK_VALSTACK_INITIAL_SIZE 96U
8043
8044/* Internal extra elements assumed on function entry, always added to
8045 * user-defined 'extra' for e.g. the duk_check_stack() call.
8046 */
8047#define DUK_VALSTACK_INTERNAL_EXTRA 32U
8048
8049/* Number of elements guaranteed to be user accessible (in addition to call
8050 * arguments) on Duktape/C function entry. This is the major public API
8051 * commitment.
8052 */
8053#define DUK_VALSTACK_API_ENTRY_MINIMUM DUK_API_ENTRY_STACK
8054
8055/*
8056 * Activation defines
8059#define DUK_ACT_FLAG_STRICT (1U << 0) /* function executes in strict mode */
8060#define DUK_ACT_FLAG_TAILCALLED (1U << 1) /* activation has tail called one or more times */
8061#define DUK_ACT_FLAG_CONSTRUCT (1U << 2) /* function executes as a constructor (called via "new") */
8062#define DUK_ACT_FLAG_PREVENT_YIELD (1U << 3) /* activation prevents yield (native call or "new") */
8063#define DUK_ACT_FLAG_DIRECT_EVAL (1U << 4) /* activation is a direct eval call */
8064#define DUK_ACT_FLAG_CONSTRUCT_PROXY (1U << 5) /* activation is for Proxy 'construct' call, special return value handling */
8065#define DUK_ACT_FLAG_BREAKPOINT_ACTIVE (1U << 6) /* activation has active breakpoint(s) */
8066
8067#define DUK_ACT_GET_FUNC(act) ((act)->func)
8068
8069/*
8070 * Flags for __FILE__ / __LINE__ registered into tracedata
8072
8073#define DUK_TB_FLAG_NOBLAME_FILELINE (1U << 0) /* don't report __FILE__ / __LINE__ as fileName/lineNumber */
8074
8075/*
8076 * Catcher defines
8077 */
8078
8079/* XXX: remove catcher type entirely */
8081/* flags field: LLLLLLFT, L = label (24 bits), F = flags (4 bits), T = type (4 bits) */
8082#define DUK_CAT_TYPE_MASK 0x0000000fUL
8083#define DUK_CAT_TYPE_BITS 4
8084#define DUK_CAT_LABEL_MASK 0xffffff00UL
8085#define DUK_CAT_LABEL_BITS 24
8086#define DUK_CAT_LABEL_SHIFT 8
8088#define DUK_CAT_FLAG_CATCH_ENABLED (1U << 4) /* catch part will catch */
8089#define DUK_CAT_FLAG_FINALLY_ENABLED (1U << 5) /* finally part will catch */
8090#define DUK_CAT_FLAG_CATCH_BINDING_ENABLED (1U << 6) /* request to create catch binding */
8091#define DUK_CAT_FLAG_LEXENV_ACTIVE (1U << 7) /* catch or with binding is currently active */
8093#define DUK_CAT_TYPE_UNKNOWN 0
8094#define DUK_CAT_TYPE_TCF 1
8095#define DUK_CAT_TYPE_LABEL 2
8097#define DUK_CAT_GET_TYPE(c) ((c)->flags & DUK_CAT_TYPE_MASK)
8098#define DUK_CAT_GET_LABEL(c) (((c)->flags & DUK_CAT_LABEL_MASK) >> DUK_CAT_LABEL_SHIFT)
8100#define DUK_CAT_HAS_CATCH_ENABLED(c) ((c)->flags & DUK_CAT_FLAG_CATCH_ENABLED)
8101#define DUK_CAT_HAS_FINALLY_ENABLED(c) ((c)->flags & DUK_CAT_FLAG_FINALLY_ENABLED)
8102#define DUK_CAT_HAS_CATCH_BINDING_ENABLED(c) ((c)->flags & DUK_CAT_FLAG_CATCH_BINDING_ENABLED)
8103#define DUK_CAT_HAS_LEXENV_ACTIVE(c) ((c)->flags & DUK_CAT_FLAG_LEXENV_ACTIVE)
8104
8105#define DUK_CAT_SET_CATCH_ENABLED(c) \
8106 do { \
8107 (c)->flags |= DUK_CAT_FLAG_CATCH_ENABLED; \
8108 } while (0)
8109#define DUK_CAT_SET_FINALLY_ENABLED(c) \
8110 do { \
8111 (c)->flags |= DUK_CAT_FLAG_FINALLY_ENABLED; \
8112 } while (0)
8113#define DUK_CAT_SET_CATCH_BINDING_ENABLED(c) \
8114 do { \
8115 (c)->flags |= DUK_CAT_FLAG_CATCH_BINDING_ENABLED; \
8116 } while (0)
8117#define DUK_CAT_SET_LEXENV_ACTIVE(c) \
8118 do { \
8119 (c)->flags |= DUK_CAT_FLAG_LEXENV_ACTIVE; \
8120 } while (0)
8121
8122#define DUK_CAT_CLEAR_CATCH_ENABLED(c) \
8123 do { \
8124 (c)->flags &= ~DUK_CAT_FLAG_CATCH_ENABLED; \
8125 } while (0)
8126#define DUK_CAT_CLEAR_FINALLY_ENABLED(c) \
8127 do { \
8128 (c)->flags &= ~DUK_CAT_FLAG_FINALLY_ENABLED; \
8129 } while (0)
8130#define DUK_CAT_CLEAR_CATCH_BINDING_ENABLED(c) \
8131 do { \
8132 (c)->flags &= ~DUK_CAT_FLAG_CATCH_BINDING_ENABLED; \
8133 } while (0)
8134#define DUK_CAT_CLEAR_LEXENV_ACTIVE(c) \
8135 do { \
8136 (c)->flags &= ~DUK_CAT_FLAG_LEXENV_ACTIVE; \
8137 } while (0)
8138
8139/*
8140 * Thread defines
8141 */
8142
8143#if defined(DUK_USE_ROM_STRINGS)
8144#define DUK_HTHREAD_GET_STRING(thr, idx) ((duk_hstring *) DUK_LOSE_CONST(duk_rom_strings_stridx[(idx)]))
8145#else /* DUK_USE_ROM_STRINGS */
8146#if defined(DUK_USE_HEAPPTR16)
8147#define DUK_HTHREAD_GET_STRING(thr, idx) ((duk_hstring *) DUK_USE_HEAPPTR_DEC16((thr)->heap->heap_udata, (thr)->strs16[(idx)]))
8148#else
8149#define DUK_HTHREAD_GET_STRING(thr, idx) ((thr)->strs[(idx)])
8150#endif
8151#endif /* DUK_USE_ROM_STRINGS */
8153/* values for the state field */
8154#define DUK_HTHREAD_STATE_INACTIVE 1 /* thread not currently running */
8155#define DUK_HTHREAD_STATE_RUNNING 2 /* thread currently running (only one at a time) */
8156#define DUK_HTHREAD_STATE_RESUMED 3 /* thread resumed another thread (active but not running) */
8157#define DUK_HTHREAD_STATE_YIELDED 4 /* thread has yielded */
8158#define DUK_HTHREAD_STATE_TERMINATED 5 /* thread has terminated */
8159
8160/* Executor interrupt default interval when nothing else requires a
8161 * smaller value. The default interval must be small enough to allow
8162 * for reasonable execution timeout checking but large enough to keep
8163 * impact on execution performance low.
8165#if defined(DUK_USE_INTERRUPT_COUNTER)
8166#define DUK_HTHREAD_INTCTR_DEFAULT (256L * 1024L)
8167#endif
8168
8169/*
8170 * Assert context is valid: non-NULL pointer, fields look sane.
8171 *
8172 * This is used by public API call entrypoints to catch invalid 'ctx' pointers
8173 * as early as possible; invalid 'ctx' pointers cause very odd and difficult to
8174 * diagnose behavior so it's worth checking even when the check is not 100%.
8175 */
8176
8177#if defined(DUK_USE_ASSERTIONS)
8178/* Assertions for internals. */
8179DUK_INTERNAL_DECL void duk_hthread_assert_valid(duk_hthread *thr);
8180#define DUK_HTHREAD_ASSERT_VALID(thr) \
8181 do { \
8182 duk_hthread_assert_valid((thr)); \
8183 } while (0)
8184
8185/* Assertions for public API calls; a bit stronger. */
8186DUK_INTERNAL_DECL void duk_ctx_assert_valid(duk_hthread *thr);
8187#define DUK_CTX_ASSERT_VALID(thr) \
8188 do { \
8189 duk_ctx_assert_valid((thr)); \
8190 } while (0)
8191#else
8192#define DUK_HTHREAD_ASSERT_VALID(thr) \
8193 do { \
8194 } while (0)
8195#define DUK_CTX_ASSERT_VALID(thr) \
8196 do { \
8197 } while (0)
8198#endif
8199
8200/* Assertions for API call entry specifically. Checks 'ctx' but also may
8201 * check internal state (e.g. not in a debugger transport callback).
8202 */
8203#define DUK_ASSERT_API_ENTRY(thr) \
8204 do { \
8205 DUK_CTX_ASSERT_VALID((thr)); \
8206 DUK_ASSERT((thr)->heap != NULL); \
8207 DUK_ASSERT((thr)->heap->dbg_calling_transport == 0); \
8208 } while (0)
8209
8210/*
8211 * Assertion helpers.
8213
8214#define DUK_ASSERT_STRIDX_VALID(val) DUK_ASSERT((duk_uint_t) (val) < DUK_HEAP_NUM_STRINGS)
8215
8216#define DUK_ASSERT_BIDX_VALID(val) DUK_ASSERT((duk_uint_t) (val) < DUK_NUM_BUILTINS)
8217
8218/*
8219 * Misc
8220 */
8222/* Fast access to 'this' binding. Assumes there's a call in progress. */
8223#define DUK_HTHREAD_THIS_PTR(thr) \
8224 (DUK_ASSERT_EXPR((thr) != NULL), DUK_ASSERT_EXPR((thr)->valstack_bottom > (thr)->valstack), (thr)->valstack_bottom - 1)
8225
8226/*
8227 * Struct defines
8228 */
8230/* Fields are ordered for alignment/packing. */
8232 duk_tval tv_func; /* borrowed: full duk_tval for function being executed; for lightfuncs */
8233 duk_hobject *func; /* borrowed: function being executed; for bound function calls, this is the final, real function, NULL
8234 for lightfuncs */
8235 duk_activation *parent; /* previous (parent) activation (or NULL if none) */
8236 duk_hobject *var_env; /* current variable environment (may be NULL if delayed) */
8237 duk_hobject *lex_env; /* current lexical environment (may be NULL if delayed) */
8238 duk_catcher *cat; /* current catcher (or NULL) */
8239
8240#if defined(DUK_USE_NONSTD_FUNC_CALLER_PROPERTY)
8241 /* Previous value of 'func' caller, restored when unwound. Only in use
8242 * when 'func' is non-strict.
8243 */
8244 duk_hobject *prev_caller;
8245#endif
8246
8247 duk_instr_t *curr_pc; /* next instruction to execute (points to 'func' bytecode, stable pointer), NULL for native calls */
8248
8249 /* bottom_byteoff and retval_byteoff are only used for book-keeping
8250 * of ECMAScript-initiated calls, to allow returning to an ECMAScript
8251 * function properly.
8252 */
8253
8254 /* Bottom of valstack for this activation, used to reset
8255 * valstack_bottom on return; offset is absolute. There's
8256 * no need to track 'top' because native call handling deals
8257 * with that using locals, and for ECMAScript returns 'nregs'
8258 * indicates the necessary top.
8259 */
8261
8262 /* Return value when returning to this activation (points to caller
8263 * reg, not callee reg); offset is absolute (only set if activation is
8264 * not topmost).
8265 *
8266 * Note: bottom_byteoff is always set, while retval_byteoff is only
8267 * applicable for activations below the topmost one. Currently
8268 * retval_byteoff for the topmost activation is considered garbage
8269 * (and it not initialized on entry or cleared on return; may contain
8270 * previous or garbage values).
8271 */
8273
8274 /* Current 'this' binding is the value just below bottom.
8275 * Previously, 'this' binding was handled with an index to the
8276 * (calling) valstack. This works for everything except tail
8277 * calls, which must not "accumulate" valstack temps.
8278 */
8279
8280 /* Value stack reserve (valstack_end) byte offset to be restored
8281 * when returning to this activation. Only used by the bytecode
8282 * executor.
8283 */
8285
8286#if defined(DUK_USE_DEBUGGER_SUPPORT)
8287 duk_uint32_t prev_line; /* needed for stepping */
8288#endif
8289
8294 duk_catcher *parent; /* previous (parent) catcher (or NULL if none) */
8295 duk_hstring *h_varname; /* borrowed reference to catch variable name (or NULL if none) */
8296 /* (reference is valid as long activation exists) */
8297 duk_instr_t *pc_base; /* resume execution from pc_base or pc_base+1 (points to 'func' bytecode, stable pointer) */
8298 duk_size_t idx_base; /* idx_base and idx_base+1 get completion value and type */
8299 duk_uint32_t flags; /* type and control flags, label number */
8300 /* XXX: could pack 'flags' and 'idx_base' to same value in practice,
8301 * on 32-bit targets this would make duk_catcher 16 bytes.
8302 */
8304
8306 /* Shared object part */
8308
8309 /* Pointer to bytecode executor's 'curr_pc' variable. Used to copy
8310 * the current PC back into the topmost activation when activation
8311 * state is about to change (or "syncing" is otherwise needed). This
8312 * is rather awkward but important for performance, see execution.rst.
8313 */
8316 /* Backpointers. */
8317 duk_heap *heap;
8319 /* Current strictness flag: affects API calls. */
8320 duk_uint8_t strict;
8322 /* Thread state. */
8323 duk_uint8_t state;
8324 duk_uint8_t unused1;
8325 duk_uint8_t unused2;
8326
8327 /* XXX: Valstack and callstack are currently assumed to have non-NULL
8328 * pointers. Relaxing this would not lead to big benefits (except
8329 * perhaps for terminated threads).
8330 */
8331
8332 /* Value stack: these are expressed as pointers for faster stack
8333 * manipulation. [valstack,valstack_top[ is GC-reachable,
8334 * [valstack_top,valstack_alloc_end[ is not GC-reachable but kept
8335 * initialized as 'undefined'. [valstack,valstack_end[ is the
8336 * guaranteed/reserved space and the valstack cannot be resized to
8337 * a smaller size. [valstack_end,valstack_alloc_end[ is currently
8338 * allocated slack that can be used to grow the current guaranteed
8339 * space but may be shrunk away without notice.
8340 *
8341 *
8342 * <----------------------- guaranteed --->
8343 * <---- slack --->
8344 * <--- frame --->
8345 * .-------------+=============+----------+--------------.
8346 * |xxxxxxxxxxxxx|yyyyyyyyyyyyy|uuuuuuuuuu|uuuuuuuuuuuuuu|
8347 * `-------------+=============+----------+--------------'
8348 *
8349 * ^ ^ ^ ^ ^
8350 * | | | | |
8351 * valstack bottom top end alloc_end
8352 *
8353 * xxx = arbitrary values, below current frame
8354 * yyy = arbitrary values, inside current frame
8355 * uuu = outside active value stack, initialized to 'undefined'
8357 duk_tval *valstack; /* start of valstack allocation */
8358 duk_tval *valstack_end; /* end of valstack reservation/guarantee (exclusive) */
8359 duk_tval *valstack_alloc_end; /* end of valstack allocation */
8360 duk_tval *valstack_bottom; /* bottom of current frame */
8361 duk_tval *valstack_top; /* top of current frame (exclusive) */
8362
8363 /* Call stack, represented as a linked list starting from the current
8364 * activation (or NULL if nothing is active).
8366 duk_activation *callstack_curr; /* current activation (or NULL if none) */
8367 duk_size_t callstack_top; /* number of activation records in callstack (0 if none) */
8368 duk_size_t callstack_preventcount; /* number of activation records in callstack preventing a yield */
8370 /* Yield/resume book-keeping. */
8371 duk_hthread *resumer; /* who resumed us (if any) */
8373 /* Current compiler state (if any), used for augmenting SyntaxErrors. */
8375
8376#if defined(DUK_USE_INTERRUPT_COUNTER)
8377 /* Interrupt counter for triggering a slow path check for execution
8378 * timeout, debugger interaction such as breakpoints, etc. The value
8379 * is valid for the current running thread, and both the init and
8380 * counter values are copied whenever a thread switch occurs. It's
8381 * important for the counter to be conveniently accessible for the
8382 * bytecode executor inner loop for performance reasons.
8384 duk_int_t interrupt_counter; /* countdown state */
8385 duk_int_t interrupt_init; /* start value for current countdown */
8386#endif
8387
8388 /* Builtin-objects; may or may not be shared with other threads,
8389 * threads existing in different "compartments" will have different
8390 * built-ins. Must be stored on a per-thread basis because there
8391 * is no intermediate structure for a thread group / compartment.
8392 * This takes quite a lot of space, currently 43x4 = 172 bytes on
8393 * 32-bit platforms.
8394 *
8395 * In some cases the builtins array could be ROM based, but it's
8396 * sometimes edited (e.g. for sandboxing) so it's better to keep
8397 * this array in RAM.
8398 */
8400
8401 /* Convenience copies from heap/vm for faster access. */
8402#if defined(DUK_USE_ROM_STRINGS)
8403 /* No field needed when strings are in ROM. */
8404#else
8405#if defined(DUK_USE_HEAPPTR16)
8406 duk_uint16_t *strs16;
8407#else
8408 duk_hstring **strs;
8409#endif
8410#endif
8411};
8412
8413/*
8414 * Prototypes
8415 */
8416
8421
8427
8432
8433#if defined(DUK_USE_FINALIZER_TORTURE)
8434DUK_INTERNAL_DECL void duk_hthread_valstack_torture_realloc(duk_hthread *thr);
8435#endif
8436
8437DUK_INTERNAL_DECL void *duk_hthread_get_valstack_ptr(duk_heap *heap, void *ud); /* indirect allocs */
8438
8439#if defined(DUK_USE_DEBUGGER_SUPPORT)
8440DUK_INTERNAL_DECL duk_uint_fast32_t duk_hthread_get_act_curr_pc(duk_hthread *thr, duk_activation *act);
8441#endif
8445
8446#endif /* DUK_HTHREAD_H_INCLUDED */
8447/* #include duk_harray.h */
8448/*
8449 * Array object representation, used for actual Array instances.
8450 *
8451 * All objects with the exotic array behavior (which must coincide with having
8452 * internal class array) MUST be duk_harrays. No other object can be a
8453 * duk_harray. However, duk_harrays may not always have an array part.
8454 */
8456#if !defined(DUK_HARRAY_H_INCLUDED)
8457#define DUK_HARRAY_H_INCLUDED
8458
8459#if defined(DUK_USE_ASSERTIONS)
8460DUK_INTERNAL_DECL void duk_harray_assert_valid(duk_harray *h);
8461#define DUK_HARRAY_ASSERT_VALID(h) \
8462 do { \
8463 duk_harray_assert_valid((h)); \
8464 } while (0)
8465#else
8466#define DUK_HARRAY_ASSERT_VALID(h) \
8467 do { \
8468 } while (0)
8469#endif
8471#define DUK_HARRAY_LENGTH_WRITABLE(h) (!(h)->length_nonwritable)
8472#define DUK_HARRAY_LENGTH_NONWRITABLE(h) ((h)->length_nonwritable)
8473#define DUK_HARRAY_SET_LENGTH_WRITABLE(h) \
8474 do { \
8475 (h)->length_nonwritable = 0; \
8476 } while (0)
8477#define DUK_HARRAY_SET_LENGTH_NONWRITABLE(h) \
8478 do { \
8479 (h)->length_nonwritable = 1; \
8480 } while (0)
8481
8483 /* Shared object part. */
8485
8486 /* Array .length.
8487 *
8488 * At present Array .length may be smaller, equal, or even larger
8489 * than the allocated underlying array part. Fast path code must
8490 * always take this into account carefully.
8491 */
8492 duk_uint32_t length;
8493
8494 /* Array .length property attributes. The property is always
8495 * non-enumerable and non-configurable. It's initially writable
8496 * but per Object.defineProperty() rules it can be made non-writable
8497 * even if it is non-configurable. Thus we need to track the
8498 * writability explicitly.
8499 *
8500 * XXX: this field to be eliminated and moved into duk_hobject
8501 * flags field to save space.
8502 */
8504};
8505
8506#endif /* DUK_HARRAY_H_INCLUDED */
8507/* #include duk_henv.h */
8508/*
8509 * Environment object representation.
8510 */
8512#if !defined(DUK_HENV_H_INCLUDED)
8513#define DUK_HENV_H_INCLUDED
8514
8515#if defined(DUK_USE_ASSERTIONS)
8516DUK_INTERNAL_DECL void duk_hdecenv_assert_valid(duk_hdecenv *h);
8517DUK_INTERNAL_DECL void duk_hobjenv_assert_valid(duk_hobjenv *h);
8518#define DUK_HDECENV_ASSERT_VALID(h) \
8519 do { \
8520 duk_hdecenv_assert_valid((h)); \
8521 } while (0)
8522#define DUK_HOBJENV_ASSERT_VALID(h) \
8523 do { \
8524 duk_hobjenv_assert_valid((h)); \
8525 } while (0)
8526#else
8527#define DUK_HDECENV_ASSERT_VALID(h) \
8528 do { \
8529 } while (0)
8530#define DUK_HOBJENV_ASSERT_VALID(h) \
8531 do { \
8532 } while (0)
8533#endif
8534
8536 /* Shared object part. */
8538
8539 /* These control variables provide enough information to access live
8540 * variables for a closure that is still open. If thread == NULL,
8541 * the record is closed and the identifiers are in the property table.
8547
8549 /* Shared object part. */
8552 /* Target object and 'this' binding for object binding. */
8554
8555 /* The 'target' object is used as a this binding in only some object
8556 * environments. For example, the global environment does not provide
8557 * a this binding, but a with statement does.
8558 */
8560};
8561
8562#endif /* DUK_HENV_H_INCLUDED */
8563/* #include duk_hbuffer.h */
8564/*
8565 * Heap buffer representation.
8566 *
8567 * Heap allocated user data buffer which is either:
8568 *
8569 * 1. A fixed size buffer (data follows header statically)
8570 * 2. A dynamic size buffer (data pointer follows header)
8571 *
8572 * The data pointer for a variable size buffer of zero size may be NULL.
8573 */
8575#if !defined(DUK_HBUFFER_H_INCLUDED)
8576#define DUK_HBUFFER_H_INCLUDED
8577
8578/*
8579 * Flags
8580 *
8581 * Fixed buffer: 0
8582 * Dynamic buffer: DUK_HBUFFER_FLAG_DYNAMIC
8583 * External buffer: DUK_HBUFFER_FLAG_DYNAMIC | DUK_HBUFFER_FLAG_EXTERNAL
8586#define DUK_HBUFFER_FLAG_DYNAMIC DUK_HEAPHDR_USER_FLAG(0) /* buffer is behind a pointer, dynamic or external */
8587#define DUK_HBUFFER_FLAG_EXTERNAL DUK_HEAPHDR_USER_FLAG(1) /* buffer pointer is to an externally allocated buffer */
8589#define DUK_HBUFFER_HAS_DYNAMIC(x) DUK_HEAPHDR_CHECK_FLAG_BITS(&(x)->hdr, DUK_HBUFFER_FLAG_DYNAMIC)
8590#define DUK_HBUFFER_HAS_EXTERNAL(x) DUK_HEAPHDR_CHECK_FLAG_BITS(&(x)->hdr, DUK_HBUFFER_FLAG_EXTERNAL)
8592#define DUK_HBUFFER_SET_DYNAMIC(x) DUK_HEAPHDR_SET_FLAG_BITS(&(x)->hdr, DUK_HBUFFER_FLAG_DYNAMIC)
8593#define DUK_HBUFFER_SET_EXTERNAL(x) DUK_HEAPHDR_SET_FLAG_BITS(&(x)->hdr, DUK_HBUFFER_FLAG_EXTERNAL)
8595#define DUK_HBUFFER_CLEAR_DYNAMIC(x) DUK_HEAPHDR_CLEAR_FLAG_BITS(&(x)->hdr, DUK_HBUFFER_FLAG_DYNAMIC)
8596#define DUK_HBUFFER_CLEAR_EXTERNAL(x) DUK_HEAPHDR_CLEAR_FLAG_BITS(&(x)->hdr, DUK_HBUFFER_FLAG_EXTERNAL)
8597
8598/*
8599 * Misc defines
8600 */
8601
8602/* Impose a maximum buffer length for now. Restricted artificially to
8603 * ensure resize computations or adding a heap header length won't
8604 * overflow size_t and that a signed duk_int_t can hold a buffer
8605 * length. The limit should be synchronized with DUK_HSTRING_MAX_BYTELEN.
8606 */
8607
8608#if defined(DUK_USE_BUFLEN16)
8609#define DUK_HBUFFER_MAX_BYTELEN (0x0000ffffUL)
8610#else
8611/* Intentionally not 0x7fffffffUL; at least JSON code expects that
8612 * 2*len + 2 fits in 32 bits.
8613 */
8614#define DUK_HBUFFER_MAX_BYTELEN (0x7ffffffeUL)
8615#endif
8616
8617/*
8618 * Field access
8619 */
8620
8621#if defined(DUK_USE_BUFLEN16)
8622/* size stored in duk_heaphdr unused flag bits */
8623#define DUK_HBUFFER_GET_SIZE(x) ((x)->hdr.h_flags >> 16)
8624#define DUK_HBUFFER_SET_SIZE(x, v) \
8625 do { \
8626 duk_size_t duk__v; \
8627 duk__v = (v); \
8628 DUK_ASSERT(duk__v <= 0xffffUL); \
8629 (x)->hdr.h_flags = ((x)->hdr.h_flags & 0x0000ffffUL) | (((duk_uint32_t) duk__v) << 16); \
8630 } while (0)
8631#define DUK_HBUFFER_ADD_SIZE(x, dv) \
8632 do { \
8633 (x)->hdr.h_flags += ((dv) << 16); \
8634 } while (0)
8635#define DUK_HBUFFER_SUB_SIZE(x, dv) \
8636 do { \
8637 (x)->hdr.h_flags -= ((dv) << 16); \
8638 } while (0)
8639#else
8640#define DUK_HBUFFER_GET_SIZE(x) (((duk_hbuffer *) (x))->size)
8641#define DUK_HBUFFER_SET_SIZE(x, v) \
8642 do { \
8643 ((duk_hbuffer *) (x))->size = (v); \
8644 } while (0)
8645#define DUK_HBUFFER_ADD_SIZE(x, dv) \
8646 do { \
8647 (x)->size += (dv); \
8648 } while (0)
8649#define DUK_HBUFFER_SUB_SIZE(x, dv) \
8650 do { \
8651 (x)->size -= (dv); \
8652 } while (0)
8653#endif
8655#define DUK_HBUFFER_FIXED_GET_SIZE(x) DUK_HBUFFER_GET_SIZE((duk_hbuffer *) (x))
8656#define DUK_HBUFFER_FIXED_SET_SIZE(x, v) DUK_HBUFFER_SET_SIZE((duk_hbuffer *) (x))
8658#define DUK_HBUFFER_DYNAMIC_GET_SIZE(x) DUK_HBUFFER_GET_SIZE((duk_hbuffer *) (x))
8659#define DUK_HBUFFER_DYNAMIC_SET_SIZE(x, v) DUK_HBUFFER_SET_SIZE((duk_hbuffer *) (x), (v))
8660#define DUK_HBUFFER_DYNAMIC_ADD_SIZE(x, dv) DUK_HBUFFER_ADD_SIZE((duk_hbuffer *) (x), (dv))
8661#define DUK_HBUFFER_DYNAMIC_SUB_SIZE(x, dv) DUK_HBUFFER_SUB_SIZE((duk_hbuffer *) (x), (dv))
8663#define DUK_HBUFFER_EXTERNAL_GET_SIZE(x) DUK_HBUFFER_GET_SIZE((duk_hbuffer *) (x))
8664#define DUK_HBUFFER_EXTERNAL_SET_SIZE(x, v) DUK_HBUFFER_SET_SIZE((duk_hbuffer *) (x), (v))
8665
8666#define DUK_HBUFFER_FIXED_GET_DATA_PTR(heap, x) ((duk_uint8_t *) (((duk_hbuffer_fixed *) (void *) (x)) + 1))
8667
8668#if defined(DUK_USE_HEAPPTR16)
8669#define DUK_HBUFFER_DYNAMIC_GET_DATA_PTR(heap, x) \
8670 ((void *) DUK_USE_HEAPPTR_DEC16((heap)->heap_udata, ((duk_heaphdr *) (x))->h_extra16))
8671#define DUK_HBUFFER_DYNAMIC_SET_DATA_PTR(heap, x, v) \
8672 do { \
8673 ((duk_heaphdr *) (x))->h_extra16 = DUK_USE_HEAPPTR_ENC16((heap)->heap_udata, (void *) (v)); \
8674 } while (0)
8675#define DUK_HBUFFER_DYNAMIC_SET_DATA_PTR_NULL(heap, x) \
8676 do { \
8677 ((duk_heaphdr *) (x))->h_extra16 = 0; /* assume 0 <=> NULL */ \
8678 } while (0)
8679#else
8680#define DUK_HBUFFER_DYNAMIC_GET_DATA_PTR(heap, x) ((x)->curr_alloc)
8681#define DUK_HBUFFER_DYNAMIC_SET_DATA_PTR(heap, x, v) \
8682 do { \
8683 (x)->curr_alloc = (void *) (v); \
8684 } while (0)
8685#define DUK_HBUFFER_DYNAMIC_SET_DATA_PTR_NULL(heap, x) \
8686 do { \
8687 (x)->curr_alloc = (void *) NULL; \
8688 } while (0)
8689#endif
8690
8691/* No pointer compression because pointer is potentially outside of
8692 * Duktape heap.
8693 */
8694#if defined(DUK_USE_HEAPPTR16)
8695#define DUK_HBUFFER_EXTERNAL_GET_DATA_PTR(heap, x) ((void *) (x)->curr_alloc)
8696#define DUK_HBUFFER_EXTERNAL_SET_DATA_PTR(heap, x, v) \
8697 do { \
8698 (x)->curr_alloc = (void *) (v); \
8699 } while (0)
8700#define DUK_HBUFFER_EXTERNAL_SET_DATA_PTR_NULL(heap, x) \
8701 do { \
8702 (x)->curr_alloc = (void *) NULL; \
8703 } while (0)
8704#else
8705#define DUK_HBUFFER_EXTERNAL_GET_DATA_PTR(heap, x) ((void *) (x)->curr_alloc)
8706#define DUK_HBUFFER_EXTERNAL_SET_DATA_PTR(heap, x, v) \
8707 do { \
8708 (x)->curr_alloc = (void *) (v); \
8709 } while (0)
8710#define DUK_HBUFFER_EXTERNAL_SET_DATA_PTR_NULL(heap, x) \
8711 do { \
8712 (x)->curr_alloc = (void *) NULL; \
8713 } while (0)
8714#endif
8715
8716/* Get a pointer to the current buffer contents (matching current allocation
8717 * size). May be NULL for zero size dynamic/external buffer.
8718 */
8719#if defined(DUK_USE_HEAPPTR16)
8720#define DUK_HBUFFER_GET_DATA_PTR(heap, x) \
8721 (DUK_HBUFFER_HAS_DYNAMIC((x)) ? \
8722 (DUK_HBUFFER_HAS_EXTERNAL((x)) ? DUK_HBUFFER_EXTERNAL_GET_DATA_PTR((heap), (duk_hbuffer_external *) (x)) : \
8723 DUK_HBUFFER_DYNAMIC_GET_DATA_PTR((heap), (duk_hbuffer_dynamic *) (x))) : \
8724 DUK_HBUFFER_FIXED_GET_DATA_PTR((heap), (duk_hbuffer_fixed *) (void *) (x)))
8725#else
8726/* Without heap pointer compression duk_hbuffer_dynamic and duk_hbuffer_external
8727 * have the same layout so checking for fixed vs. dynamic (or external) is enough.
8728 */
8729#define DUK_HBUFFER_GET_DATA_PTR(heap, x) \
8730 (DUK_HBUFFER_HAS_DYNAMIC((x)) ? DUK_HBUFFER_DYNAMIC_GET_DATA_PTR((heap), (duk_hbuffer_dynamic *) (x)) : \
8731 DUK_HBUFFER_FIXED_GET_DATA_PTR((heap), (duk_hbuffer_fixed *) (void *) (x)))
8732#endif
8733
8734/* Validity assert. */
8735#if defined(DUK_USE_ASSERTIONS)
8736DUK_INTERNAL_DECL void duk_hbuffer_assert_valid(duk_hbuffer *h);
8737#define DUK_HBUFFER_ASSERT_VALID(h) \
8738 do { \
8739 duk_hbuffer_assert_valid((h)); \
8740 } while (0)
8741#else
8742#define DUK_HBUFFER_ASSERT_VALID(h) \
8743 do { \
8744 } while (0)
8745#endif
8746
8747/*
8748 * Structs
8749 */
8751/* Shared prefix for all buffer types. */
8752struct duk_hbuffer {
8754
8755 /* It's not strictly necessary to track the current size, but
8756 * it is useful for writing robust native code.
8757 */
8758
8759 /* Current size. */
8760#if defined(DUK_USE_BUFLEN16)
8761 /* Stored in duk_heaphdr unused flags. */
8762#else
8764#endif
8765
8766 /*
8767 * Data following the header depends on the DUK_HBUFFER_FLAG_DYNAMIC
8768 * flag.
8769 *
8770 * If the flag is clear (the buffer is a fixed size one), the buffer
8771 * data follows the header directly, consisting of 'size' bytes.
8772 *
8773 * If the flag is set, the actual buffer is allocated separately, and
8774 * a few control fields follow the header. Specifically:
8775 *
8776 * - a "void *" pointing to the current allocation
8777 * - a duk_size_t indicating the full allocated size (always >= 'size')
8778 *
8779 * If DUK_HBUFFER_FLAG_EXTERNAL is set, the buffer has been allocated
8780 * by user code, so that Duktape won't be able to resize it and won't
8781 * free it. This allows buffers to point to e.g. an externally
8782 * allocated structure such as a frame buffer.
8783 *
8784 * Unlike strings, no terminator byte (NUL) is guaranteed after the
8785 * data. This would be convenient, but would pad aligned user buffers
8786 * unnecessarily upwards in size. For instance, if user code requested
8787 * a 64-byte dynamic buffer, 65 bytes would actually be allocated which
8788 * would then potentially round upwards to perhaps 68 or 72 bytes.
8789 */
8790};
8791
8792/* Fixed buffer; data follows struct, with proper alignment guaranteed by
8793 * struct size.
8794 */
8795#if (DUK_USE_ALIGN_BY == 8) && defined(DUK_USE_PACK_MSVC_PRAGMA)
8796#pragma pack(push, 8)
8797#endif
8798struct duk_hbuffer_fixed {
8799 /* A union is used here as a portable struct size / alignment trick:
8800 * by adding a 32-bit or a 64-bit (unused) union member, the size of
8801 * the struct is effectively forced to be a multiple of 4 or 8 bytes
8802 * (respectively) without increasing the size of the struct unless
8803 * necessary.
8804 */
8805 union {
8806 struct {
8808#if defined(DUK_USE_BUFLEN16)
8809 /* Stored in duk_heaphdr unused flags. */
8810#else
8812#endif
8813 } s;
8814#if (DUK_USE_ALIGN_BY == 4)
8815 duk_uint32_t dummy_for_align4;
8816#elif (DUK_USE_ALIGN_BY == 8)
8818#if defined(DUK_USE_64BIT_OPS)
8819 duk_uint64_t dummy_for_align8_2;
8820#endif
8821#elif (DUK_USE_ALIGN_BY == 1)
8822 /* no extra padding */
8823#else
8824#error invalid DUK_USE_ALIGN_BY
8825#endif
8826 } u;
8827
8828 /*
8829 * Data follows the struct header. The struct size is padded by the
8830 * compiler based on the struct members. This guarantees that the
8831 * buffer data will be aligned-by-4 but not necessarily aligned-by-8.
8832 *
8833 * On platforms where alignment does not matter, the struct padding
8834 * could be removed (if there is any). On platforms where alignment
8835 * by 8 is required, the struct size must be forced to be a multiple
8836 * of 8 by some means. Without it, some user code may break, and also
8837 * Duktape itself breaks (e.g. the compiler stores duk_tvals in a
8838 * dynamic buffer).
8839 */
8840}
8841#if (DUK_USE_ALIGN_BY == 8) && defined(DUK_USE_PACK_GCC_ATTR)
8842__attribute__((aligned(8)))
8843#elif (DUK_USE_ALIGN_BY == 8) && defined(DUK_USE_PACK_CLANG_ATTR)
8844__attribute__((aligned(8)))
8845#endif
8846;
8847#if (DUK_USE_ALIGN_BY == 8) && defined(DUK_USE_PACK_MSVC_PRAGMA)
8848#pragma pack(pop)
8849#endif
8850
8851/* Dynamic buffer with 'curr_alloc' pointing to a dynamic area allocated using
8852 * heap allocation primitives. Also used for external buffers when low memory
8853 * options are not used.
8855struct duk_hbuffer_dynamic {
8857
8858#if defined(DUK_USE_BUFLEN16)
8859 /* Stored in duk_heaphdr unused flags. */
8860#else
8862#endif
8863
8864#if defined(DUK_USE_HEAPPTR16)
8865 /* Stored in duk_heaphdr h_extra16. */
8866#else
8867 void *curr_alloc; /* may be NULL if alloc_size == 0 */
8868#endif
8869
8870 /*
8871 * Allocation size for 'curr_alloc' is alloc_size. There is no
8872 * automatic NUL terminator for buffers (see above for rationale).
8873 *
8874 * 'curr_alloc' is explicitly allocated with heap allocation
8875 * primitives and will thus always have alignment suitable for
8876 * e.g. duk_tval and an IEEE double.
8877 */
8878};
8879
8880/* External buffer with 'curr_alloc' managed by user code and pointing to an
8881 * arbitrary address. When heap pointer compression is not used, this struct
8882 * has the same layout as duk_hbuffer_dynamic.
8884struct duk_hbuffer_external {
8886
8887#if defined(DUK_USE_BUFLEN16)
8888 /* Stored in duk_heaphdr unused flags. */
8889#else
8891#endif
8892
8893 /* Cannot be compressed as a heap pointer because may point to
8894 * an arbitrary address.
8895 */
8896 void *curr_alloc; /* may be NULL if alloc_size == 0 */
8897};
8898
8899/*
8900 * Prototypes
8901 */
8902
8904DUK_INTERNAL_DECL void *duk_hbuffer_get_dynalloc_ptr(duk_heap *heap, void *ud); /* indirect allocs */
8905
8906/* dynamic buffer ops */
8909
8910#endif /* DUK_HBUFFER_H_INCLUDED */
8911/* #include duk_hproxy.h */
8912/*
8913 * Proxy object representation.
8914 */
8916#if !defined(DUK_HPROXY_H_INCLUDED)
8917#define DUK_HPROXY_H_INCLUDED
8918
8919#if defined(DUK_USE_ASSERTIONS)
8920DUK_INTERNAL_DECL void duk_hproxy_assert_valid(duk_hproxy *h);
8921#define DUK_HPROXY_ASSERT_VALID(h) \
8922 do { \
8923 duk_hproxy_assert_valid((h)); \
8924 } while (0)
8925#else
8926#define DUK_HPROXY_ASSERT_VALID(h) \
8927 do { \
8928 } while (0)
8929#endif
8930
8932 /* Shared object part. */
8935 /* Proxy target object. */
8938 /* Proxy handlers (traps). */
8940};
8941
8942#endif /* DUK_HPROXY_H_INCLUDED */
8943/* #include duk_heap.h */
8944/*
8945 * Heap structure.
8946 *
8947 * Heap contains allocated heap objects, interned strings, and built-in
8948 * strings for one or more threads.
8949 */
8951#if !defined(DUK_HEAP_H_INCLUDED)
8952#define DUK_HEAP_H_INCLUDED
8953
8954/* alloc function typedefs in duktape.h */
8955
8956/*
8957 * Heap flags
8959
8960#define DUK_HEAP_FLAG_MARKANDSWEEP_RECLIMIT_REACHED \
8961 (1U << 0) /* mark-and-sweep marking reached a recursion limit and must use multi-pass marking */
8962#define DUK_HEAP_FLAG_INTERRUPT_RUNNING (1U << 1) /* executor interrupt running (used to avoid nested interrupts) */
8963#define DUK_HEAP_FLAG_FINALIZER_NORESCUE (1U << 2) /* heap destruction ongoing, finalizer rescue no longer possible */
8964#define DUK_HEAP_FLAG_DEBUGGER_PAUSED (1U << 3) /* debugger is paused: talk with debug client until step/resume */
8966#define DUK__HEAP_HAS_FLAGS(heap, bits) ((heap)->flags & (bits))
8967#define DUK__HEAP_SET_FLAGS(heap, bits) \
8968 do { \
8969 (heap)->flags |= (bits); \
8970 } while (0)
8971#define DUK__HEAP_CLEAR_FLAGS(heap, bits) \
8972 do { \
8973 (heap)->flags &= ~(bits); \
8974 } while (0)
8976#define DUK_HEAP_HAS_MARKANDSWEEP_RECLIMIT_REACHED(heap) DUK__HEAP_HAS_FLAGS((heap), DUK_HEAP_FLAG_MARKANDSWEEP_RECLIMIT_REACHED)
8977#define DUK_HEAP_HAS_INTERRUPT_RUNNING(heap) DUK__HEAP_HAS_FLAGS((heap), DUK_HEAP_FLAG_INTERRUPT_RUNNING)
8978#define DUK_HEAP_HAS_FINALIZER_NORESCUE(heap) DUK__HEAP_HAS_FLAGS((heap), DUK_HEAP_FLAG_FINALIZER_NORESCUE)
8979#define DUK_HEAP_HAS_DEBUGGER_PAUSED(heap) DUK__HEAP_HAS_FLAGS((heap), DUK_HEAP_FLAG_DEBUGGER_PAUSED)
8981#define DUK_HEAP_SET_MARKANDSWEEP_RECLIMIT_REACHED(heap) DUK__HEAP_SET_FLAGS((heap), DUK_HEAP_FLAG_MARKANDSWEEP_RECLIMIT_REACHED)
8982#define DUK_HEAP_SET_INTERRUPT_RUNNING(heap) DUK__HEAP_SET_FLAGS((heap), DUK_HEAP_FLAG_INTERRUPT_RUNNING)
8983#define DUK_HEAP_SET_FINALIZER_NORESCUE(heap) DUK__HEAP_SET_FLAGS((heap), DUK_HEAP_FLAG_FINALIZER_NORESCUE)
8984#define DUK_HEAP_SET_DEBUGGER_PAUSED(heap) DUK__HEAP_SET_FLAGS((heap), DUK_HEAP_FLAG_DEBUGGER_PAUSED)
8985
8986#define DUK_HEAP_CLEAR_MARKANDSWEEP_RECLIMIT_REACHED(heap) \
8987 DUK__HEAP_CLEAR_FLAGS((heap), DUK_HEAP_FLAG_MARKANDSWEEP_RECLIMIT_REACHED)
8988#define DUK_HEAP_CLEAR_INTERRUPT_RUNNING(heap) DUK__HEAP_CLEAR_FLAGS((heap), DUK_HEAP_FLAG_INTERRUPT_RUNNING)
8989#define DUK_HEAP_CLEAR_FINALIZER_NORESCUE(heap) DUK__HEAP_CLEAR_FLAGS((heap), DUK_HEAP_FLAG_FINALIZER_NORESCUE)
8990#define DUK_HEAP_CLEAR_DEBUGGER_PAUSED(heap) DUK__HEAP_CLEAR_FLAGS((heap), DUK_HEAP_FLAG_DEBUGGER_PAUSED)
8991
8992/*
8993 * Longjmp types, also double as identifying continuation type for a rethrow (in 'finally')
8996#define DUK_LJ_TYPE_UNKNOWN 0 /* unused */
8997#define DUK_LJ_TYPE_THROW 1 /* value1 -> error object */
8998#define DUK_LJ_TYPE_YIELD 2 /* value1 -> yield value, iserror -> error / normal */
8999#define DUK_LJ_TYPE_RESUME 3 /* value1 -> resume value, value2 -> resumee thread, iserror -> error/normal */
9000#define DUK_LJ_TYPE_BREAK 4 /* value1 -> label number, pseudo-type to indicate a break continuation (for ENDFIN) */
9001#define DUK_LJ_TYPE_CONTINUE 5 /* value1 -> label number, pseudo-type to indicate a continue continuation (for ENDFIN) */
9002#define DUK_LJ_TYPE_RETURN 6 /* value1 -> return value, pseudo-type to indicate a return continuation (for ENDFIN) */
9003#define DUK_LJ_TYPE_NORMAL 7 /* no value, pseudo-type to indicate a normal continuation (for ENDFIN) */
9004
9005/*
9006 * Mark-and-sweep flags
9007 *
9008 * These are separate from heap level flags now but could be merged.
9009 * The heap structure only contains a 'base mark-and-sweep flags'
9010 * field and the GC caller can impose further flags.
9011 */
9012
9013/* Emergency mark-and-sweep: try extra hard, even at the cost of
9014 * performance.
9015 */
9016#define DUK_MS_FLAG_EMERGENCY (1U << 0)
9017
9018/* Postpone rescue decisions for reachable objects with FINALIZED set.
9019 * Used during finalize_list processing to avoid incorrect rescue
9020 * decisions due to finalize_list being a reachability root.
9021 */
9022#define DUK_MS_FLAG_POSTPONE_RESCUE (1U << 1)
9023
9024/* Don't compact objects; needed during object property table resize
9025 * to prevent a recursive resize. It would suffice to protect only the
9026 * current object being resized, but this is not yet implemented.
9027 */
9028#define DUK_MS_FLAG_NO_OBJECT_COMPACTION (1U << 2)
9029
9030/*
9031 * Thread switching
9032 *
9033 * To switch heap->curr_thread, use the macro below so that interrupt counters
9034 * get updated correctly. The macro allows a NULL target thread because that
9035 * happens e.g. in call handling.
9036 */
9038#if defined(DUK_USE_INTERRUPT_COUNTER)
9039#define DUK_HEAP_SWITCH_THREAD(heap, newthr) duk_heap_switch_thread((heap), (newthr))
9040#else
9041#define DUK_HEAP_SWITCH_THREAD(heap, newthr) \
9042 do { \
9043 (heap)->curr_thread = (newthr); \
9044 } while (0)
9045#endif
9046
9047/*
9048 * Stats
9049 */
9050
9051#if defined(DUK_USE_DEBUG)
9052#define DUK_STATS_INC(heap, fieldname) \
9053 do { \
9054 (heap)->fieldname += 1; \
9055 } while (0)
9056#else
9057#define DUK_STATS_INC(heap, fieldname) \
9058 do { \
9059 } while (0)
9060#endif
9061
9062/*
9063 * Other heap related defines
9064 */
9065
9066/* Mark-and-sweep interval is relative to combined count of objects and
9067 * strings kept in the heap during the latest mark-and-sweep pass.
9068 * Fixed point .8 multiplier and .0 adder. Trigger count (interval) is
9069 * decreased by each (re)allocation attempt (regardless of size), and each
9070 * refzero processed object.
9071 *
9072 * 'SKIP' indicates how many (re)allocations to wait until a retry if
9073 * GC is skipped because there is no thread do it with yet (happens
9074 * only during init phases).
9076#if defined(DUK_USE_REFERENCE_COUNTING)
9077#define DUK_HEAP_MARK_AND_SWEEP_TRIGGER_MULT 12800L /* 50x heap size */
9078#define DUK_HEAP_MARK_AND_SWEEP_TRIGGER_ADD 1024L
9079#define DUK_HEAP_MARK_AND_SWEEP_TRIGGER_SKIP 256L
9080#else
9081#define DUK_HEAP_MARK_AND_SWEEP_TRIGGER_MULT 256L /* 1x heap size */
9082#define DUK_HEAP_MARK_AND_SWEEP_TRIGGER_ADD 1024L
9083#define DUK_HEAP_MARK_AND_SWEEP_TRIGGER_SKIP 256L
9084#endif
9085
9086/* GC torture. */
9087#if defined(DUK_USE_GC_TORTURE)
9088#define DUK_GC_TORTURE(heap) \
9089 do { \
9090 duk_heap_mark_and_sweep((heap), 0); \
9091 } while (0)
9092#else
9093#define DUK_GC_TORTURE(heap) \
9094 do { \
9095 } while (0)
9096#endif
9097
9098/* Stringcache is used for speeding up char-offset-to-byte-offset
9099 * translations for non-ASCII strings.
9101#define DUK_HEAP_STRCACHE_SIZE 4
9102#define DUK_HEAP_STRINGCACHE_NOCACHE_LIMIT 16 /* strings up to the this length are not cached */
9104/* Some list management macros. */
9105#define DUK_HEAP_INSERT_INTO_HEAP_ALLOCATED(heap, hdr) duk_heap_insert_into_heap_allocated((heap), (hdr))
9106#if defined(DUK_USE_REFERENCE_COUNTING)
9107#define DUK_HEAP_REMOVE_FROM_HEAP_ALLOCATED(heap, hdr) duk_heap_remove_from_heap_allocated((heap), (hdr))
9108#endif
9109#if defined(DUK_USE_FINALIZER_SUPPORT)
9110#define DUK_HEAP_INSERT_INTO_FINALIZE_LIST(heap, hdr) duk_heap_insert_into_finalize_list((heap), (hdr))
9111#define DUK_HEAP_REMOVE_FROM_FINALIZE_LIST(heap, hdr) duk_heap_remove_from_finalize_list((heap), (hdr))
9112#endif
9113
9114/*
9115 * Built-in strings
9116 */
9117
9118/* heap string indices are autogenerated in duk_strings.h */
9119#if defined(DUK_USE_ROM_STRINGS)
9120#define DUK_HEAP_GET_STRING(heap, idx) ((duk_hstring *) DUK_LOSE_CONST(duk_rom_strings_stridx[(idx)]))
9121#else /* DUK_USE_ROM_STRINGS */
9122#if defined(DUK_USE_HEAPPTR16)
9123#define DUK_HEAP_GET_STRING(heap, idx) ((duk_hstring *) DUK_USE_HEAPPTR_DEC16((heap)->heap_udata, (heap)->strs16[(idx)]))
9124#else
9125#define DUK_HEAP_GET_STRING(heap, idx) ((heap)->strs[(idx)])
9126#endif
9127#endif /* DUK_USE_ROM_STRINGS */
9128
9129/*
9130 * Raw memory calls: relative to heap, but no GC interaction
9132
9133#define DUK_ALLOC_RAW(heap, size) ((heap)->alloc_func((heap)->heap_udata, (size)))
9134
9135#define DUK_REALLOC_RAW(heap, ptr, newsize) ((heap)->realloc_func((heap)->heap_udata, (void *) (ptr), (newsize)))
9136
9137#define DUK_FREE_RAW(heap, ptr) ((heap)->free_func((heap)->heap_udata, (void *) (ptr)))
9138
9139/*
9140 * Memory calls: relative to heap, GC interaction, but no error throwing.
9141 *
9142 * XXX: Currently a mark-and-sweep triggered by memory allocation will run
9143 * using the heap->heap_thread. This thread is also used for running
9144 * mark-and-sweep finalization; this is not ideal because it breaks the
9145 * isolation between multiple global environments.
9146 *
9147 * Notes:
9148 *
9149 * - DUK_FREE() is required to ignore NULL and any other possible return
9150 * value of a zero-sized alloc/realloc (same as ANSI C free()).
9151 *
9152 * - There is no DUK_REALLOC_ZEROED because we don't assume to know the
9153 * old size. Caller must zero the reallocated memory.
9154 *
9155 * - DUK_REALLOC_INDIRECT() must be used when a mark-and-sweep triggered
9156 * by an allocation failure might invalidate the original 'ptr', thus
9157 * causing a realloc retry to use an invalid pointer. Example: we're
9158 * reallocating the value stack and a finalizer resizes the same value
9159 * stack during mark-and-sweep. The indirect variant requests for the
9160 * current location of the pointer being reallocated using a callback
9161 * right before every realloc attempt; this circuitous approach is used
9162 * to avoid strict aliasing issues in a more straightforward indirect
9163 * pointer (void **) approach. Note: the pointer in the storage
9164 * location is read but is NOT updated; the caller must do that.
9165 */
9167/* callback for indirect reallocs, request for current pointer */
9168typedef void *(*duk_mem_getptr)(duk_heap *heap, void *ud);
9170#define DUK_ALLOC(heap, size) duk_heap_mem_alloc((heap), (size))
9171#define DUK_ALLOC_ZEROED(heap, size) duk_heap_mem_alloc_zeroed((heap), (size))
9172#define DUK_REALLOC(heap, ptr, newsize) duk_heap_mem_realloc((heap), (ptr), (newsize))
9173#define DUK_REALLOC_INDIRECT(heap, cb, ud, newsize) duk_heap_mem_realloc_indirect((heap), (cb), (ud), (newsize))
9174#define DUK_FREE(heap, ptr) duk_heap_mem_free((heap), (ptr))
9175
9176/*
9177 * Checked allocation, relative to a thread
9178 *
9179 * DUK_FREE_CHECKED() doesn't actually throw, but accepts a 'thr' argument
9180 * for convenience.
9183#define DUK_ALLOC_CHECKED(thr, size) duk_heap_mem_alloc_checked((thr), (size))
9184#define DUK_ALLOC_CHECKED_ZEROED(thr, size) duk_heap_mem_alloc_checked_zeroed((thr), (size))
9185#define DUK_FREE_CHECKED(thr, ptr) duk_heap_mem_free((thr)->heap, (ptr))
9186
9187/*
9188 * Memory constants
9190
9191#define DUK_HEAP_ALLOC_FAIL_MARKANDSWEEP_LIMIT \
9192 10 /* Retry allocation after mark-and-sweep for this \
9193 * many times. A single mark-and-sweep round is \
9194 * not guaranteed to free all unreferenced memory \
9195 * because of finalization (in fact, ANY number of \
9196 * rounds is strictly not enough). \
9197 */
9198
9199#define DUK_HEAP_ALLOC_FAIL_MARKANDSWEEP_EMERGENCY_LIMIT \
9200 3 /* Starting from this round, use emergency mode \
9201 * for mark-and-sweep. \
9203
9204/*
9205 * Debugger support
9206 */
9207
9208/* Maximum number of breakpoints. Only breakpoints that are set are
9209 * consulted so increasing this has no performance impact.
9210 */
9211#define DUK_HEAP_MAX_BREAKPOINTS 16
9213/* Opcode interval for a Date-based status/peek rate limit check. Only
9214 * relevant when debugger is attached. Requesting a timestamp may be a
9215 * slow operation on some platforms so this shouldn't be too low. On the
9216 * other hand a high value makes Duktape react to a pause request slowly.
9218#define DUK_HEAP_DBG_RATELIMIT_OPCODES 4000
9220/* Milliseconds between status notify and transport peeks. */
9221#define DUK_HEAP_DBG_RATELIMIT_MILLISECS 200
9222
9223/* Debugger pause flags. */
9224#define DUK_PAUSE_FLAG_ONE_OPCODE (1U << 0) /* pause when a single opcode has been executed */
9225#define DUK_PAUSE_FLAG_ONE_OPCODE_ACTIVE (1U << 1) /* one opcode pause actually active; artifact of current implementation */
9226#define DUK_PAUSE_FLAG_LINE_CHANGE (1U << 2) /* pause when current line number changes */
9227#define DUK_PAUSE_FLAG_FUNC_ENTRY (1U << 3) /* pause when entering a function */
9228#define DUK_PAUSE_FLAG_FUNC_EXIT (1U << 4) /* pause when exiting current function */
9229#define DUK_PAUSE_FLAG_CAUGHT_ERROR (1U << 5) /* pause when about to throw an error that is caught */
9230#define DUK_PAUSE_FLAG_UNCAUGHT_ERROR (1U << 6) /* pause when about to throw an error that won't be caught */
9231
9232struct duk_breakpoint {
9234 duk_uint32_t line;
9235};
9236
9238 * String cache should ideally be at duk_hthread level, but that would
9239 * cause string finalization to slow down relative to the number of
9240 * threads; string finalization must check the string cache for "weak"
9241 * references to the string being finalized to avoid dead pointers.
9242 *
9243 * Thus, string caches are now at the heap level now.
9244 */
9245
9246struct duk_strcache_entry {
9247 duk_hstring *h;
9248 duk_uint32_t bidx;
9249 duk_uint32_t cidx;
9253 * Longjmp state, contains the information needed to perform a longjmp.
9254 * Longjmp related values are written to value1, value2, and iserror.
9255 */
9257struct duk_ljstate {
9258 duk_jmpbuf *jmpbuf_ptr; /* current setjmp() catchpoint */
9259 duk_small_uint_t type; /* longjmp type */
9260 duk_bool_t iserror; /* isError flag for yield */
9261 duk_tval value1; /* 1st related value (type specific) */
9262 duk_tval value2; /* 2nd related value (type specific) */
9263};
9265#define DUK_ASSERT_LJSTATE_UNSET(heap) \
9266 do { \
9267 DUK_ASSERT(heap != NULL); \
9268 DUK_ASSERT(heap->lj.type == DUK_LJ_TYPE_UNKNOWN); \
9269 DUK_ASSERT(heap->lj.iserror == 0); \
9270 DUK_ASSERT(DUK_TVAL_IS_UNDEFINED(&heap->lj.value1)); \
9271 DUK_ASSERT(DUK_TVAL_IS_UNDEFINED(&heap->lj.value2)); \
9272 } while (0)
9273#define DUK_ASSERT_LJSTATE_SET(heap) \
9274 do { \
9275 DUK_ASSERT(heap != NULL); \
9276 DUK_ASSERT(heap->lj.type != DUK_LJ_TYPE_UNKNOWN); \
9277 } while (0)
9278
9279/*
9280 * Literal intern cache
9281 */
9282
9283struct duk_litcache_entry {
9284 const duk_uint8_t *addr;
9285 duk_hstring *h;
9286};
9287
9288/*
9289 * Main heap structure
9291
9292#if defined(DUK_USE_ASSERTIONS)
9293DUK_INTERNAL_DECL void duk_heap_assert_valid(duk_heap *heap);
9294#define DUK_HEAP_ASSERT_VALID(heap) \
9295 do { \
9296 duk_heap_assert_valid((heap)); \
9297 } while (0)
9298#else
9299#define DUK_HEAP_ASSERT_VALID(heap) \
9300 do { \
9301 } while (0)
9302#endif
9303
9304struct duk_heap {
9307 /* Allocator functions. */
9311
9312 /* Heap udata, used for allocator functions but also for other heap
9313 * level callbacks like fatal function, pointer compression, etc.
9314 */
9315 void *heap_udata;
9316
9317 /* Fatal error handling, called e.g. when a longjmp() is needed but
9318 * lj.jmpbuf_ptr is NULL. fatal_func must never return; it's not
9319 * declared as "noreturn" because doing that for typedefs is a bit
9320 * challenging portability-wise.
9321 */
9323
9324 /* Main list of allocated heap objects. Objects are either here,
9325 * in finalize_list waiting for processing, or in refzero_list
9326 * temporarily while a DECREF refzero cascade finishes.
9327 */
9329
9330 /* Temporary work list for freeing a cascade of objects when a DECREF
9331 * (or DECREF_NORZ) encounters a zero refcount. Using a work list
9332 * allows fixed C stack size when refcounts go to zero for a chain of
9333 * objects. Outside of DECREF this is always a NULL because DECREF is
9334 * processed without side effects (only memory free calls).
9335 */
9336#if defined(DUK_USE_REFERENCE_COUNTING)
9338#endif
9339
9340#if defined(DUK_USE_FINALIZER_SUPPORT)
9341 /* Work list for objects to be finalized. */
9343#if defined(DUK_USE_ASSERTIONS)
9344 /* Object whose finalizer is executing right now (no nesting). */
9345 duk_heaphdr *currently_finalizing;
9346#endif
9347#endif
9348
9349 /* Freelist for duk_activations and duk_catchers. */
9350#if defined(DUK_USE_CACHE_ACTIVATION)
9352#endif
9353#if defined(DUK_USE_CACHE_CATCHER)
9355#endif
9356
9357 /* Voluntary mark-and-sweep trigger counter. Intentionally signed
9358 * because we continue decreasing the value when voluntary GC cannot
9359 * run.
9360 */
9361#if defined(DUK_USE_VOLUNTARY_GC)
9363#endif
9364
9365 /* Mark-and-sweep recursion control: too deep recursion causes
9366 * multi-pass processing to avoid growing C stack without bound.
9367 */
9369
9370 /* Mark-and-sweep flags automatically active (used for critical sections). */
9373 /* Mark-and-sweep running flag. Prevents re-entry, and also causes
9374 * refzero events to be ignored (= objects won't be queued to refzero_list).
9375 *
9376 * 0: mark-and-sweep not running
9377 * 1: mark-and-sweep is running
9378 * 2: heap destruction active or debugger active, prevent mark-and-sweep
9379 * and refzero processing (but mark-and-sweep not itself running)
9382
9383 /* Mark-and-sweep prevent count, stacking. Used to avoid M&S side
9384 * effects (besides finalizers which are controlled separately) such
9385 * as compacting the string table or object property tables. This
9386 * is also bumped when ms_running is set to prevent recursive re-entry.
9387 * Can also be bumped when mark-and-sweep is not running.
9388 */
9390
9391 /* Finalizer processing prevent count, stacking. Bumped when finalizers
9392 * are processed to prevent recursive finalizer processing (first call site
9393 * processing finalizers handles all finalizers until the list is empty).
9394 * Can also be bumped explicitly to prevent finalizer execution.
9395 */
9397
9398 /* When processing finalize_list, don't actually run finalizers but
9399 * queue finalizable objects back to heap_allocated as is. This is
9400 * used during heap destruction to deal with finalizers that keep
9401 * on creating more finalizable garbage.
9402 */
9404
9405#if defined(DUK_USE_ASSERTIONS)
9406 /* Set when we're in a critical path where an error throw would cause
9407 * e.g. sandboxing/protected call violations or state corruption. This
9408 * is just used for asserts.
9409 */
9410 duk_bool_t error_not_allowed;
9411#endif
9412
9413#if defined(DUK_USE_ASSERTIONS)
9414 /* Set when heap is still being initialized, helps with writing
9415 * some assertions.
9416 */
9417 duk_bool_t heap_initializing;
9418#endif
9419
9420 /* Marker for detecting internal "double faults", errors thrown when
9421 * we're trying to create an error object, see duk_error_throw.c.
9422 */
9424
9425 /* Marker for indicating we're calling a user error augmentation
9426 * (errCreate/errThrow) function. Errors created/thrown during
9427 * such a call are not augmented.
9429#if defined(DUK_USE_AUGMENT_ERROR_THROW) || defined(DUK_USE_AUGMENT_ERROR_CREATE)
9431#endif
9432
9433 /* Longjmp state. */
9435
9436 /* Heap thread, used internally and for finalization. */
9439 /* Current running thread. */
9442 /* Heap level "stash" object (e.g., various reachability roots). */
9444
9445 /* duk_handle_call / duk_handle_safe_call recursion depth limiting */
9448
9449 /* Mix-in value for computing string hashes; should be reasonably unpredictable. */
9450 duk_uint32_t hash_seed;
9451
9452 /* Random number state for duk_util_tinyrandom.c. */
9453#if !defined(DUK_USE_GET_RANDOM_DOUBLE)
9454#if defined(DUK_USE_PREFER_SIZE) || !defined(DUK_USE_64BIT_OPS)
9455 duk_uint32_t rnd_state; /* State for Shamir's three-op algorithm */
9456#else
9457 duk_uint64_t rnd_state[2]; /* State for xoroshiro128+ */
9458#endif
9459#endif
9460
9461 /* Counter for unique local symbol creation. */
9462 /* XXX: When 64-bit types are available, it would be more efficient to
9463 * use a duk_uint64_t at least for incrementing but maybe also for
9464 * string formatting in the Symbol constructor.
9465 */
9466 duk_uint32_t sym_counter[2];
9467
9468 /* For manual debugging: instruction count based on executor and
9469 * interrupt counter book-keeping. Inspect debug logs to see how
9470 * they match up.
9471 */
9472#if defined(DUK_USE_INTERRUPT_COUNTER) && defined(DUK_USE_DEBUG)
9473 duk_int_t inst_count_exec;
9474 duk_int_t inst_count_interrupt;
9475#endif
9476
9477 /* Debugger state. */
9478#if defined(DUK_USE_DEBUGGER_SUPPORT)
9479 /* Callbacks and udata; dbg_read_cb != NULL is used to indicate attached state. */
9480 duk_debug_read_function dbg_read_cb; /* required, NULL implies detached */
9481 duk_debug_write_function dbg_write_cb; /* required */
9482 duk_debug_peek_function dbg_peek_cb;
9483 duk_debug_read_flush_function dbg_read_flush_cb;
9484 duk_debug_write_flush_function dbg_write_flush_cb;
9485 duk_debug_request_function dbg_request_cb;
9486 duk_debug_detached_function dbg_detached_cb;
9487 void *dbg_udata;
9488
9489 /* The following are only relevant when debugger is attached. */
9490 duk_bool_t dbg_processing; /* currently processing messages or breakpoints: don't enter message processing recursively (e.g.
9491 no breakpoints when processing debugger eval) */
9492 duk_bool_t dbg_state_dirty; /* resend state next time executor is about to run */
9494 dbg_force_restart; /* force executor restart to recheck breakpoints; used to handle function returns (see GH-303) */
9495 duk_bool_t dbg_detaching; /* debugger detaching; used to avoid calling detach handler recursively */
9496 duk_small_uint_t dbg_pause_flags; /* flags for automatic pause behavior */
9497 duk_activation *dbg_pause_act; /* activation related to pause behavior (pause on line change, function entry/exit) */
9498 duk_uint32_t dbg_pause_startline; /* starting line number for line change related pause behavior */
9499 duk_breakpoint dbg_breakpoints[DUK_HEAP_MAX_BREAKPOINTS]; /* breakpoints: [0,breakpoint_count[ gc reachable */
9500 duk_small_uint_t dbg_breakpoint_count;
9502 *dbg_breakpoints_active[DUK_HEAP_MAX_BREAKPOINTS + 1]; /* currently active breakpoints: NULL term, borrowed pointers */
9503 /* XXX: make active breakpoints actual copies instead of pointers? */
9504
9505 /* These are for rate limiting Status notifications and transport peeking. */
9506 duk_uint_t dbg_exec_counter; /* cumulative opcode execution count (overflows are OK) */
9507 duk_uint_t dbg_last_counter; /* value of dbg_exec_counter when we last did a Date-based check */
9508 duk_double_t dbg_last_time; /* time when status/peek was last done (Date-based rate limit) */
9509
9510 /* Used to support single-byte stream lookahead. */
9511 duk_bool_t dbg_have_next_byte;
9512 duk_uint8_t dbg_next_byte;
9513#endif /* DUK_USE_DEBUGGER_SUPPORT */
9514#if defined(DUK_USE_ASSERTIONS)
9515 duk_bool_t dbg_calling_transport; /* transport call in progress, calling into Duktape forbidden */
9516#endif
9517
9518 /* String intern table (weak refs). */
9519#if defined(DUK_USE_STRTAB_PTRCOMP)
9520 duk_uint16_t *strtable16;
9521#else
9523#endif
9524 duk_uint32_t st_mask; /* mask for lookup, st_size - 1 */
9525 duk_uint32_t st_size; /* stringtable size */
9526#if (DUK_USE_STRTAB_MINSIZE != DUK_USE_STRTAB_MAXSIZE)
9527 duk_uint32_t st_count; /* string count for resize load factor checks */
9528#endif
9529 duk_bool_t st_resizing; /* string table is being resized; avoid recursive resize */
9530
9531 /* String access cache (codepoint offset -> byte offset) for fast string
9532 * character looping; 'weak' reference which needs special handling in GC.
9533 */
9535
9536#if defined(DUK_USE_LITCACHE_SIZE)
9537 /* Literal intern cache. When enabled, strings interned as literals
9538 * (e.g. duk_push_literal()) will be pinned and cached for the lifetime
9539 * of the heap.
9540 */
9542#endif
9543
9544 /* Built-in strings. */
9545#if defined(DUK_USE_ROM_STRINGS)
9546 /* No field needed when strings are in ROM. */
9547#else
9548#if defined(DUK_USE_HEAPPTR16)
9549 duk_uint16_t strs16[DUK_HEAP_NUM_STRINGS];
9550#else
9552#endif
9553#endif
9554
9555 /* Stats. */
9556#if defined(DUK_USE_DEBUG)
9557 duk_int_t stats_exec_opcodes;
9558 duk_int_t stats_exec_interrupt;
9559 duk_int_t stats_exec_throw;
9560 duk_int_t stats_call_all;
9561 duk_int_t stats_call_tailcall;
9562 duk_int_t stats_call_ecmatoecma;
9563 duk_int_t stats_safecall_all;
9564 duk_int_t stats_safecall_nothrow;
9565 duk_int_t stats_safecall_throw;
9566 duk_int_t stats_ms_try_count;
9567 duk_int_t stats_ms_skip_count;
9568 duk_int_t stats_ms_emergency_count;
9569 duk_int_t stats_strtab_intern_hit;
9570 duk_int_t stats_strtab_intern_miss;
9571 duk_int_t stats_strtab_resize_check;
9572 duk_int_t stats_strtab_resize_grow;
9573 duk_int_t stats_strtab_resize_shrink;
9574 duk_int_t stats_strtab_litcache_hit;
9575 duk_int_t stats_strtab_litcache_miss;
9576 duk_int_t stats_strtab_litcache_pin;
9577 duk_int_t stats_object_realloc_props;
9578 duk_int_t stats_object_abandon_array;
9579 duk_int_t stats_getownpropdesc_count;
9580 duk_int_t stats_getownpropdesc_hit;
9581 duk_int_t stats_getownpropdesc_miss;
9582 duk_int_t stats_getpropdesc_count;
9583 duk_int_t stats_getpropdesc_hit;
9584 duk_int_t stats_getpropdesc_miss;
9585 duk_int_t stats_getprop_all;
9586 duk_int_t stats_getprop_arrayidx;
9587 duk_int_t stats_getprop_bufobjidx;
9588 duk_int_t stats_getprop_bufferidx;
9589 duk_int_t stats_getprop_bufferlen;
9590 duk_int_t stats_getprop_stringidx;
9591 duk_int_t stats_getprop_stringlen;
9592 duk_int_t stats_getprop_proxy;
9593 duk_int_t stats_getprop_arguments;
9594 duk_int_t stats_putprop_all;
9595 duk_int_t stats_putprop_arrayidx;
9596 duk_int_t stats_putprop_bufobjidx;
9597 duk_int_t stats_putprop_bufferidx;
9598 duk_int_t stats_putprop_proxy;
9599 duk_int_t stats_getvar_all;
9600 duk_int_t stats_putvar_all;
9601 duk_int_t stats_envrec_delayedcreate;
9602 duk_int_t stats_envrec_create;
9603 duk_int_t stats_envrec_newenv;
9604 duk_int_t stats_envrec_oldenv;
9605 duk_int_t stats_envrec_pushclosure;
9606#endif
9607};
9608
9609/*
9610 * Prototypes
9611 */
9612
9615 duk_realloc_function realloc_func,
9616 duk_free_function free_func,
9617 void *heap_udata,
9618 duk_fatal_function fatal_func);
9624
9626#if defined(DUK_USE_REFERENCE_COUNTING)
9628#endif
9629#if defined(DUK_USE_FINALIZER_SUPPORT)
9632#endif
9633#if defined(DUK_USE_ASSERTIONS)
9634DUK_INTERNAL_DECL duk_bool_t duk_heap_in_heap_allocated(duk_heap *heap, duk_heaphdr *ptr);
9635#endif
9636#if defined(DUK_USE_INTERRUPT_COUNTER)
9638#endif
9639
9640DUK_INTERNAL_DECL duk_hstring *duk_heap_strtable_intern(duk_heap *heap, const duk_uint8_t *str, duk_uint32_t blen);
9641DUK_INTERNAL_DECL duk_hstring *duk_heap_strtable_intern_checked(duk_hthread *thr, const duk_uint8_t *str, duk_uint32_t len);
9642#if defined(DUK_USE_LITCACHE_SIZE)
9644 const duk_uint8_t *str,
9645 duk_uint32_t blen);
9646#endif
9649#if defined(DUK_USE_REFERENCE_COUNTING)
9651#endif
9655#if defined(DUK_USE_DEBUG)
9656DUK_INTERNAL void duk_heap_strtable_dump(duk_heap *heap);
9657#endif
9658
9661 duk_hstring *h,
9662 duk_uint_fast32_t char_offset);
9663
9664#if defined(DUK_USE_PROVIDE_DEFAULT_ALLOC_FUNCTIONS)
9666DUK_INTERNAL_DECL void *duk_default_realloc_function(void *udata, void *ptr, duk_size_t newsize);
9667DUK_INTERNAL_DECL void duk_default_free_function(void *udata, void *ptr);
9668#endif
9669
9674DUK_INTERNAL_DECL void *duk_heap_mem_realloc(duk_heap *heap, void *ptr, duk_size_t newsize);
9676DUK_INTERNAL_DECL void duk_heap_mem_free(duk_heap *heap, void *ptr);
9677
9679
9680#if defined(DUK_USE_FINALIZER_SUPPORT)
9683#endif /* DUK_USE_FINALIZER_SUPPORT */
9684
9686
9687DUK_INTERNAL_DECL duk_uint32_t duk_heap_hashstring(duk_heap *heap, const duk_uint8_t *str, duk_size_t len);
9689#endif /* DUK_HEAP_H_INCLUDED */
9690/* #include duk_debugger.h */
9691#if !defined(DUK_DEBUGGER_H_INCLUDED)
9692#define DUK_DEBUGGER_H_INCLUDED
9693
9694/* Debugger protocol version is defined in the public API header. */
9696/* Initial bytes for markers. */
9697#define DUK_DBG_IB_EOM 0x00
9698#define DUK_DBG_IB_REQUEST 0x01
9699#define DUK_DBG_IB_REPLY 0x02
9700#define DUK_DBG_IB_ERROR 0x03
9701#define DUK_DBG_IB_NOTIFY 0x04
9703/* Other initial bytes. */
9704#define DUK_DBG_IB_INT4 0x10
9705#define DUK_DBG_IB_STR4 0x11
9706#define DUK_DBG_IB_STR2 0x12
9707#define DUK_DBG_IB_BUF4 0x13
9708#define DUK_DBG_IB_BUF2 0x14
9709#define DUK_DBG_IB_UNUSED 0x15
9710#define DUK_DBG_IB_UNDEFINED 0x16
9711#define DUK_DBG_IB_NULL 0x17
9712#define DUK_DBG_IB_TRUE 0x18
9713#define DUK_DBG_IB_FALSE 0x19
9714#define DUK_DBG_IB_NUMBER 0x1a
9715#define DUK_DBG_IB_OBJECT 0x1b
9716#define DUK_DBG_IB_POINTER 0x1c
9717#define DUK_DBG_IB_LIGHTFUNC 0x1d
9718#define DUK_DBG_IB_HEAPPTR 0x1e
9719/* The short string/integer initial bytes starting from 0x60 don't have
9720 * defines now.
9721 */
9723/* Error codes. */
9724#define DUK_DBG_ERR_UNKNOWN 0x00
9725#define DUK_DBG_ERR_UNSUPPORTED 0x01
9726#define DUK_DBG_ERR_TOOMANY 0x02
9727#define DUK_DBG_ERR_NOTFOUND 0x03
9728#define DUK_DBG_ERR_APPLICATION 0x04
9729
9730/* Commands and notifys initiated by Duktape. */
9731#define DUK_DBG_CMD_STATUS 0x01
9732#define DUK_DBG_CMD_UNUSED_2 0x02 /* Duktape 1.x: print notify */
9733#define DUK_DBG_CMD_UNUSED_3 0x03 /* Duktape 1.x: alert notify */
9734#define DUK_DBG_CMD_UNUSED_4 0x04 /* Duktape 1.x: log notify */
9735#define DUK_DBG_CMD_THROW 0x05
9736#define DUK_DBG_CMD_DETACHING 0x06
9737#define DUK_DBG_CMD_APPNOTIFY 0x07
9739/* Commands initiated by debug client. */
9740#define DUK_DBG_CMD_BASICINFO 0x10
9741#define DUK_DBG_CMD_TRIGGERSTATUS 0x11
9742#define DUK_DBG_CMD_PAUSE 0x12
9743#define DUK_DBG_CMD_RESUME 0x13
9744#define DUK_DBG_CMD_STEPINTO 0x14
9745#define DUK_DBG_CMD_STEPOVER 0x15
9746#define DUK_DBG_CMD_STEPOUT 0x16
9747#define DUK_DBG_CMD_LISTBREAK 0x17
9748#define DUK_DBG_CMD_ADDBREAK 0x18
9749#define DUK_DBG_CMD_DELBREAK 0x19
9750#define DUK_DBG_CMD_GETVAR 0x1a
9751#define DUK_DBG_CMD_PUTVAR 0x1b
9752#define DUK_DBG_CMD_GETCALLSTACK 0x1c
9753#define DUK_DBG_CMD_GETLOCALS 0x1d
9754#define DUK_DBG_CMD_EVAL 0x1e
9755#define DUK_DBG_CMD_DETACH 0x1f
9756#define DUK_DBG_CMD_DUMPHEAP 0x20
9757#define DUK_DBG_CMD_GETBYTECODE 0x21
9758#define DUK_DBG_CMD_APPREQUEST 0x22
9759#define DUK_DBG_CMD_GETHEAPOBJINFO 0x23
9760#define DUK_DBG_CMD_GETOBJPROPDESC 0x24
9761#define DUK_DBG_CMD_GETOBJPROPDESCRANGE 0x25
9762
9763/* The low 8 bits map directly to duk_hobject.h DUK_PROPDESC_FLAG_xxx.
9764 * The remaining flags are specific to the debugger.
9765 */
9766#define DUK_DBG_PROPFLAG_SYMBOL (1U << 8)
9767#define DUK_DBG_PROPFLAG_HIDDEN (1U << 9)
9768
9769#if defined(DUK_USE_DEBUGGER_SUPPORT)
9770DUK_INTERNAL_DECL void duk_debug_do_detach(duk_heap *heap);
9771
9772DUK_INTERNAL_DECL duk_bool_t duk_debug_read_peek(duk_hthread *thr);
9773DUK_INTERNAL_DECL void duk_debug_write_flush(duk_hthread *thr);
9774
9775DUK_INTERNAL_DECL void duk_debug_skip_bytes(duk_hthread *thr, duk_size_t length);
9776DUK_INTERNAL_DECL void duk_debug_skip_byte(duk_hthread *thr);
9777
9778DUK_INTERNAL_DECL void duk_debug_read_bytes(duk_hthread *thr, duk_uint8_t *data, duk_size_t length);
9779DUK_INTERNAL_DECL duk_uint8_t duk_debug_read_byte(duk_hthread *thr);
9780DUK_INTERNAL_DECL duk_int32_t duk_debug_read_int(duk_hthread *thr);
9781DUK_INTERNAL_DECL duk_hstring *duk_debug_read_hstring(duk_hthread *thr);
9782/* XXX: exposed duk_debug_read_pointer */
9783/* XXX: exposed duk_debug_read_buffer */
9784/* XXX: exposed duk_debug_read_hbuffer */
9785#if 0
9786DUK_INTERNAL_DECL duk_heaphdr *duk_debug_read_heapptr(duk_hthread *thr);
9787#endif
9788#if defined(DUK_USE_DEBUGGER_INSPECT)
9789DUK_INTERNAL_DECL duk_heaphdr *duk_debug_read_any_ptr(duk_hthread *thr);
9790#endif
9791DUK_INTERNAL_DECL duk_tval *duk_debug_read_tval(duk_hthread *thr);
9792
9793DUK_INTERNAL_DECL void duk_debug_write_bytes(duk_hthread *thr, const duk_uint8_t *data, duk_size_t length);
9794DUK_INTERNAL_DECL void duk_debug_write_byte(duk_hthread *thr, duk_uint8_t x);
9795DUK_INTERNAL_DECL void duk_debug_write_unused(duk_hthread *thr);
9796DUK_INTERNAL_DECL void duk_debug_write_undefined(duk_hthread *thr);
9797#if defined(DUK_USE_DEBUGGER_INSPECT)
9798DUK_INTERNAL_DECL void duk_debug_write_null(duk_hthread *thr);
9799#endif
9800DUK_INTERNAL_DECL void duk_debug_write_boolean(duk_hthread *thr, duk_uint_t val);
9801DUK_INTERNAL_DECL void duk_debug_write_int(duk_hthread *thr, duk_int32_t x);
9802DUK_INTERNAL_DECL void duk_debug_write_uint(duk_hthread *thr, duk_uint32_t x);
9803DUK_INTERNAL_DECL void duk_debug_write_string(duk_hthread *thr, const char *data, duk_size_t length);
9804DUK_INTERNAL_DECL void duk_debug_write_cstring(duk_hthread *thr, const char *data);
9805DUK_INTERNAL_DECL void duk_debug_write_hstring(duk_hthread *thr, duk_hstring *h);
9806DUK_INTERNAL_DECL void duk_debug_write_buffer(duk_hthread *thr, const char *data, duk_size_t length);
9807DUK_INTERNAL_DECL void duk_debug_write_hbuffer(duk_hthread *thr, duk_hbuffer *h);
9808DUK_INTERNAL_DECL void duk_debug_write_pointer(duk_hthread *thr, void *ptr);
9809#if defined(DUK_USE_DEBUGGER_DUMPHEAP) || defined(DUK_USE_DEBUGGER_INSPECT)
9810DUK_INTERNAL_DECL void duk_debug_write_heapptr(duk_hthread *thr, duk_heaphdr *h);
9811#endif
9812DUK_INTERNAL_DECL void duk_debug_write_hobject(duk_hthread *thr, duk_hobject *obj);
9813DUK_INTERNAL_DECL void duk_debug_write_tval(duk_hthread *thr, duk_tval *tv);
9814#if 0 /* unused */
9815DUK_INTERNAL_DECL void duk_debug_write_request(duk_hthread *thr, duk_small_uint_t command);
9816#endif
9817DUK_INTERNAL_DECL void duk_debug_write_reply(duk_hthread *thr);
9818DUK_INTERNAL_DECL void duk_debug_write_error_eom(duk_hthread *thr, duk_small_uint_t err_code, const char *msg);
9819DUK_INTERNAL_DECL void duk_debug_write_notify(duk_hthread *thr, duk_small_uint_t command);
9820DUK_INTERNAL_DECL void duk_debug_write_eom(duk_hthread *thr);
9821
9822DUK_INTERNAL_DECL duk_uint_fast32_t duk_debug_curr_line(duk_hthread *thr);
9823DUK_INTERNAL_DECL void duk_debug_send_status(duk_hthread *thr);
9824#if defined(DUK_USE_DEBUGGER_THROW_NOTIFY)
9825DUK_INTERNAL_DECL void duk_debug_send_throw(duk_hthread *thr, duk_bool_t fatal);
9826#endif
9827
9828DUK_INTERNAL_DECL void duk_debug_halt_execution(duk_hthread *thr, duk_bool_t use_prev_pc);
9829DUK_INTERNAL_DECL duk_bool_t duk_debug_process_messages(duk_hthread *thr, duk_bool_t no_block);
9830
9831DUK_INTERNAL_DECL duk_small_int_t duk_debug_add_breakpoint(duk_hthread *thr, duk_hstring *filename, duk_uint32_t line);
9832DUK_INTERNAL_DECL duk_bool_t duk_debug_remove_breakpoint(duk_hthread *thr, duk_small_uint_t breakpoint_index);
9833
9834DUK_INTERNAL_DECL duk_bool_t duk_debug_is_attached(duk_heap *heap);
9835DUK_INTERNAL_DECL duk_bool_t duk_debug_is_paused(duk_heap *heap);
9836DUK_INTERNAL_DECL void duk_debug_set_paused(duk_heap *heap);
9837DUK_INTERNAL_DECL void duk_debug_clear_paused(duk_heap *heap);
9838DUK_INTERNAL_DECL void duk_debug_clear_pause_state(duk_heap *heap);
9839#endif /* DUK_USE_DEBUGGER_SUPPORT */
9840
9841#endif /* DUK_DEBUGGER_H_INCLUDED */
9842/* #include duk_debug.h */
9843/*
9844 * Debugging macros, DUK_DPRINT() and its variants in particular.
9845 *
9846 * DUK_DPRINT() allows formatted debug prints, and supports standard
9847 * and Duktape specific formatters. See duk_debug_vsnprintf.c for details.
9848 *
9849 * DUK_D(x), DUK_DD(x), and DUK_DDD(x) are used together with log macros
9850 * for technical reasons. They are concretely used to hide 'x' from the
9851 * compiler when the corresponding log level is disabled. This allows
9852 * clean builds on non-C99 compilers, at the cost of more verbose code.
9853 * Examples:
9854 *
9855 * DUK_D(DUK_DPRINT("foo"));
9856 * DUK_DD(DUK_DDPRINT("foo"));
9857 * DUK_DDD(DUK_DDDPRINT("foo"));
9858 *
9859 * This approach is preferable to the old "double parentheses" hack because
9860 * double parentheses make the C99 solution worse: __FILE__ and __LINE__ can
9861 * no longer be added transparently without going through globals, which
9862 * works poorly with threading.
9863 */
9864
9865#if !defined(DUK_DEBUG_H_INCLUDED)
9866#define DUK_DEBUG_H_INCLUDED
9867
9868#if defined(DUK_USE_DEBUG)
9869
9870#if defined(DUK_USE_DEBUG_LEVEL) && (DUK_USE_DEBUG_LEVEL >= 0)
9871#define DUK_D(x) x
9872#else
9873#define DUK_D(x) \
9874 do { \
9875 } while (0) /* omit */
9876#endif
9877
9878#if defined(DUK_USE_DEBUG_LEVEL) && (DUK_USE_DEBUG_LEVEL >= 1)
9879#define DUK_DD(x) x
9880#else
9881#define DUK_DD(x) \
9882 do { \
9883 } while (0) /* omit */
9884#endif
9885
9886#if defined(DUK_USE_DEBUG_LEVEL) && (DUK_USE_DEBUG_LEVEL >= 2)
9887#define DUK_DDD(x) x
9888#else
9889#define DUK_DDD(x) \
9890 do { \
9891 } while (0) /* omit */
9892#endif
9893
9894/*
9895 * Exposed debug macros: debugging enabled
9896 */
9897
9898#if defined(DUK_USE_VARIADIC_MACROS)
9899
9900/* Note: combining __FILE__, __LINE__, and __func__ into fmt would be
9901 * possible compile time, but waste some space with shared function names.
9902 */
9903#define DUK__DEBUG_LOG(lev, ...) \
9904 duk_debug_log((duk_int_t) (lev), DUK_FILE_MACRO, (duk_int_t) DUK_LINE_MACRO, DUK_FUNC_MACRO, __VA_ARGS__);
9905
9906#if defined(DUK_USE_DEBUG_LEVEL) && (DUK_USE_DEBUG_LEVEL >= 0)
9907#define DUK_DPRINT(...) DUK__DEBUG_LOG(DUK_LEVEL_DEBUG, __VA_ARGS__)
9908#else
9909#define DUK_DPRINT(...)
9910#endif
9911
9912#if defined(DUK_USE_DEBUG_LEVEL) && (DUK_USE_DEBUG_LEVEL >= 1)
9913#define DUK_DDPRINT(...) DUK__DEBUG_LOG(DUK_LEVEL_DDEBUG, __VA_ARGS__)
9914#else
9915#define DUK_DDPRINT(...)
9916#endif
9917
9918#if defined(DUK_USE_DEBUG_LEVEL) && (DUK_USE_DEBUG_LEVEL >= 2)
9919#define DUK_DDDPRINT(...) DUK__DEBUG_LOG(DUK_LEVEL_DDDEBUG, __VA_ARGS__)
9920#else
9921#define DUK_DDDPRINT(...)
9922#endif
9923
9924#else /* DUK_USE_VARIADIC_MACROS */
9925
9926#define DUK__DEBUG_STASH(lev) \
9927 (void) DUK_SNPRINTF(duk_debug_file_stash, DUK_DEBUG_STASH_SIZE, "%s", (const char *) DUK_FILE_MACRO), \
9928 (void) (duk_debug_file_stash[DUK_DEBUG_STASH_SIZE - 1] = (char) 0), \
9929 (void) (duk_debug_line_stash = (duk_int_t) DUK_LINE_MACRO), \
9930 (void) DUK_SNPRINTF(duk_debug_func_stash, DUK_DEBUG_STASH_SIZE, "%s", (const char *) DUK_FUNC_MACRO), \
9931 (void) (duk_debug_func_stash[DUK_DEBUG_STASH_SIZE - 1] = (char) 0), (void) (duk_debug_level_stash = (lev))
9932
9933/* Without variadic macros resort to comma expression trickery to handle debug
9934 * prints. This generates a lot of harmless warnings. These hacks are not
9935 * needed normally because DUK_D() and friends will hide the entire debug log
9936 * statement from the compiler.
9937 */
9938
9939#if defined(DUK_USE_DEBUG_LEVEL) && (DUK_USE_DEBUG_LEVEL >= 0)
9940#define DUK_DPRINT DUK__DEBUG_STASH(DUK_LEVEL_DEBUG), (void) duk_debug_log /* args go here in parens */
9941#else
9942#define DUK_DPRINT 0 && /* args go here as a comma expression in parens */
9943#endif
9944
9945#if defined(DUK_USE_DEBUG_LEVEL) && (DUK_USE_DEBUG_LEVEL >= 1)
9946#define DUK_DDPRINT DUK__DEBUG_STASH(DUK_LEVEL_DDEBUG), (void) duk_debug_log /* args go here in parens */
9947#else
9948#define DUK_DDPRINT 0 && /* args */
9949#endif
9950
9951#if defined(DUK_USE_DEBUG_LEVEL) && (DUK_USE_DEBUG_LEVEL >= 2)
9952#define DUK_DDDPRINT DUK__DEBUG_STASH(DUK_LEVEL_DDDEBUG), (void) duk_debug_log /* args go here in parens */
9953#else
9954#define DUK_DDDPRINT 0 && /* args */
9955#endif
9957#endif /* DUK_USE_VARIADIC_MACROS */
9958
9959#else /* DUK_USE_DEBUG */
9960
9961/*
9962 * Exposed debug macros: debugging disabled
9963 */
9964
9965#define DUK_D(x) \
9966 do { \
9967 } while (0) /* omit */
9968#define DUK_DD(x) \
9969 do { \
9970 } while (0) /* omit */
9971#define DUK_DDD(x) \
9972 do { \
9973 } while (0) /* omit */
9975#if defined(DUK_USE_VARIADIC_MACROS)
9977#define DUK_DPRINT(...)
9978#define DUK_DDPRINT(...)
9979#define DUK_DDDPRINT(...)
9980
9981#else /* DUK_USE_VARIADIC_MACROS */
9982
9983#define DUK_DPRINT 0 && /* args go here as a comma expression in parens */
9984#define DUK_DDPRINT 0 && /* args */
9985#define DUK_DDDPRINT 0 && /* args */
9986
9987#endif /* DUK_USE_VARIADIC_MACROS */
9988
9989#endif /* DUK_USE_DEBUG */
9990
9991/*
9992 * Structs
9993 */
9994
9995#if defined(DUK_USE_DEBUG)
9996struct duk_fixedbuffer {
9997 duk_uint8_t *buffer;
9998 duk_size_t length;
9999 duk_size_t offset;
10000 duk_bool_t truncated;
10001};
10002#endif
10003
10004/*
10005 * Prototypes
10006 */
10007
10008#if defined(DUK_USE_DEBUG)
10009DUK_INTERNAL_DECL duk_int_t duk_debug_vsnprintf(char *str, duk_size_t size, const char *format, va_list ap);
10010#if 0 /*unused*/
10011DUK_INTERNAL_DECL duk_int_t duk_debug_snprintf(char *str, duk_size_t size, const char *format, ...);
10012#endif
10013DUK_INTERNAL_DECL void duk_debug_format_funcptr(char *buf, duk_size_t buf_size, duk_uint8_t *fptr, duk_size_t fptr_size);
10014
10015#if defined(DUK_USE_VARIADIC_MACROS)
10016DUK_INTERNAL_DECL void duk_debug_log(duk_int_t level, const char *file, duk_int_t line, const char *func, const char *fmt, ...);
10017#else /* DUK_USE_VARIADIC_MACROS */
10018/* parameter passing, not thread safe */
10019#define DUK_DEBUG_STASH_SIZE 128
10020#if !defined(DUK_SINGLE_FILE)
10021DUK_INTERNAL_DECL char duk_debug_file_stash[DUK_DEBUG_STASH_SIZE];
10022DUK_INTERNAL_DECL duk_int_t duk_debug_line_stash;
10023DUK_INTERNAL_DECL char duk_debug_func_stash[DUK_DEBUG_STASH_SIZE];
10024DUK_INTERNAL_DECL duk_int_t duk_debug_level_stash;
10025#endif
10026DUK_INTERNAL_DECL void duk_debug_log(const char *fmt, ...);
10027#endif /* DUK_USE_VARIADIC_MACROS */
10028
10029DUK_INTERNAL_DECL void duk_fb_put_bytes(duk_fixedbuffer *fb, const duk_uint8_t *buffer, duk_size_t length);
10030DUK_INTERNAL_DECL void duk_fb_put_byte(duk_fixedbuffer *fb, duk_uint8_t x);
10031DUK_INTERNAL_DECL void duk_fb_put_cstring(duk_fixedbuffer *fb, const char *x);
10032DUK_INTERNAL_DECL void duk_fb_sprintf(duk_fixedbuffer *fb, const char *fmt, ...);
10033DUK_INTERNAL_DECL void duk_fb_put_funcptr(duk_fixedbuffer *fb, duk_uint8_t *fptr, duk_size_t fptr_size);
10034DUK_INTERNAL_DECL duk_bool_t duk_fb_is_full(duk_fixedbuffer *fb);
10035
10036#endif /* DUK_USE_DEBUG */
10037
10038#endif /* DUK_DEBUG_H_INCLUDED */
10039/* #include duk_error.h */
10040/*
10041 * Error handling macros, assertion macro, error codes.
10042 *
10043 * There are three types of 'errors':
10044 *
10045 * 1. Ordinary errors relative to a thread, cause a longjmp, catchable.
10046 * 2. Fatal errors relative to a heap, cause fatal handler to be called.
10047 * 3. Fatal errors without context, cause the default (not heap specific)
10048 * fatal handler to be called.
10049 *
10050 * Fatal errors without context are used by debug code such as assertions.
10051 * By providing a fatal error handler for a Duktape heap, user code can
10052 * avoid fatal errors without context in non-debug builds.
10053 */
10054
10055#if !defined(DUK_ERROR_H_INCLUDED)
10056#define DUK_ERROR_H_INCLUDED
10057
10058/*
10059 * Error codes: defined in duktape.h
10060 *
10061 * Error codes are used as a shorthand to throw exceptions from inside
10062 * the implementation. The appropriate ECMAScript object is constructed
10063 * based on the code. ECMAScript code throws objects directly. The error
10064 * codes are defined in the public API header because they are also used
10065 * by calling code.
10066 */
10067
10068/*
10069 * Normal error
10070 *
10071 * Normal error is thrown with a longjmp() through the current setjmp()
10072 * catchpoint record in the duk_heap. The 'curr_thread' of the duk_heap
10073 * identifies the throwing thread.
10074 *
10075 * Error formatting is usually unnecessary. The error macros provide a
10076 * zero argument version (no formatting) and separate macros for small
10077 * argument counts. Variadic macros are not used to avoid portability
10078 * issues and avoid the need for stash-based workarounds when they're not
10079 * available. Vararg calls are avoided for non-formatted error calls
10080 * because vararg call sites are larger than normal, and there are a lot
10081 * of call sites with no formatting.
10082 *
10083 * Note that special formatting provided by debug macros is NOT available.
10084 *
10085 * The _RAW variants allow the caller to specify file and line. This makes
10086 * it easier to write checked calls which want to use the call site of the
10087 * checked function, not the error macro call inside the checked function.
10088 */
10089
10090#if defined(DUK_USE_VERBOSE_ERRORS)
10091
10092/* Because there are quite many call sites, pack error code (require at most
10093 * 8-bit) into a single argument.
10095#define DUK_ERROR(thr, err, msg) \
10096 do { \
10097 duk_errcode_t duk__err = (err); \
10098 duk_int_t duk__line = (duk_int_t) DUK_LINE_MACRO; \
10099 DUK_ASSERT(duk__err >= 0 && duk__err <= 0xff); \
10100 DUK_ASSERT(duk__line >= 0 && duk__line <= 0x00ffffffL); \
10101 duk_err_handle_error((thr), DUK_FILE_MACRO, (((duk_uint_t) duk__err) << 24) | ((duk_uint_t) duk__line), (msg)); \
10102 } while (0)
10103#define DUK_ERROR_RAW(thr, file, line, err, msg) \
10104 do { \
10105 duk_errcode_t duk__err = (err); \
10106 duk_int_t duk__line = (duk_int_t) (line); \
10107 DUK_ASSERT(duk__err >= 0 && duk__err <= 0xff); \
10108 DUK_ASSERT(duk__line >= 0 && duk__line <= 0x00ffffffL); \
10109 duk_err_handle_error((thr), (file), (((duk_uint_t) duk__err) << 24) | ((duk_uint_t) duk__line), (msg)); \
10110 } while (0)
10111
10112#define DUK_ERROR_FMT1(thr, err, fmt, arg1) \
10113 do { \
10114 duk_errcode_t duk__err = (err); \
10115 duk_int_t duk__line = (duk_int_t) DUK_LINE_MACRO; \
10116 DUK_ASSERT(duk__err >= 0 && duk__err <= 0xff); \
10117 DUK_ASSERT(duk__line >= 0 && duk__line <= 0x00ffffffL); \
10118 duk_err_handle_error_fmt((thr), \
10119 DUK_FILE_MACRO, \
10120 (((duk_uint_t) duk__err) << 24) | ((duk_uint_t) duk__line), \
10121 (fmt), \
10122 (arg1)); \
10123 } while (0)
10124#define DUK_ERROR_RAW_FMT1(thr, file, line, err, fmt, arg1) \
10125 do { \
10126 duk_errcode_t duk__err = (err); \
10127 duk_int_t duk__line = (duk_int_t) (line); \
10128 DUK_ASSERT(duk__err >= 0 && duk__err <= 0xff); \
10129 DUK_ASSERT(duk__line >= 0 && duk__line <= 0x00ffffffL); \
10130 duk_err_handle_error_fmt((thr), \
10131 (file), \
10132 (((duk_uint_t) duk__err) << 24) | ((duk_uint_t) duk__line), \
10133 (fmt), \
10134 (arg1)); \
10135 } while (0)
10136
10137#define DUK_ERROR_FMT2(thr, err, fmt, arg1, arg2) \
10138 do { \
10139 duk_errcode_t duk__err = (err); \
10140 duk_int_t duk__line = (duk_int_t) DUK_LINE_MACRO; \
10141 DUK_ASSERT(duk__err >= 0 && duk__err <= 0xff); \
10142 DUK_ASSERT(duk__line >= 0 && duk__line <= 0x00ffffffL); \
10143 duk_err_handle_error_fmt((thr), \
10144 DUK_FILE_MACRO, \
10145 (((duk_uint_t) duk__err) << 24) | ((duk_uint_t) duk__line), \
10146 (fmt), \
10147 (arg1), \
10148 (arg2)); \
10149 } while (0)
10150#define DUK_ERROR_RAW_FMT2(thr, file, line, err, fmt, arg1, arg2) \
10151 do { \
10152 duk_errcode_t duk__err = (err); \
10153 duk_int_t duk__line = (duk_int_t) (line); \
10154 DUK_ASSERT(duk__err >= 0 && duk__err <= 0xff); \
10155 DUK_ASSERT(duk__line >= 0 && duk__line <= 0x00ffffffL); \
10156 duk_err_handle_error_fmt((thr), \
10157 (file), \
10158 (((duk_uint_t) duk__err) << 24) | ((duk_uint_t) duk__line), \
10159 (fmt), \
10160 (arg1), \
10161 (arg2)); \
10162 } while (0)
10163
10164#define DUK_ERROR_FMT3(thr, err, fmt, arg1, arg2, arg3) \
10165 do { \
10166 duk_errcode_t duk__err = (err); \
10167 duk_int_t duk__line = (duk_int_t) DUK_LINE_MACRO; \
10168 DUK_ASSERT(duk__err >= 0 && duk__err <= 0xff); \
10169 DUK_ASSERT(duk__line >= 0 && duk__line <= 0x00ffffffL); \
10170 duk_err_handle_error_fmt((thr), \
10171 DUK_FILE_MACRO, \
10172 (((duk_uint_t) duk__err) << 24) | ((duk_uint_t) duk__line), \
10173 (fmt), \
10174 (arg1), \
10175 (arg2), \
10176 (arg3)); \
10177 } while (0)
10178#define DUK_ERROR_RAW_FMT3(thr, file, line, err, fmt, arg1, arg2, arg3) \
10179 do { \
10180 duk_errcode_t duk__err = (err); \
10181 duk_int_t duk__line = (duk_int_t) (line); \
10182 DUK_ASSERT(duk__err >= 0 && duk__err <= 0xff); \
10183 DUK_ASSERT(duk__line >= 0 && duk__line <= 0x00ffffffL); \
10184 duk_err_handle_error_fmt((thr), \
10185 (file), \
10186 (((duk_uint_t) duk__err) << 24) | ((duk_uint_t) duk__line), \
10187 (fmt), \
10188 (arg1), \
10189 (arg2), \
10190 (arg3)); \
10191 } while (0)
10192
10193#define DUK_ERROR_FMT4(thr, err, fmt, arg1, arg2, arg3, arg4) \
10194 do { \
10195 duk_errcode_t duk__err = (err); \
10196 duk_int_t duk__line = (duk_int_t) DUK_LINE_MACRO; \
10197 DUK_ASSERT(duk__err >= 0 && duk__err <= 0xff); \
10198 DUK_ASSERT(duk__line >= 0 && duk__line <= 0x00ffffffL); \
10199 duk_err_handle_error_fmt((thr), \
10200 DUK_FILE_MACRO, \
10201 (((duk_uint_t) duk__err) << 24) | ((duk_uint_t) duk__line), \
10202 (fmt), \
10203 (arg1), \
10204 (arg2), \
10205 (arg3), \
10206 (arg4)); \
10207 } while (0)
10208#define DUK_ERROR_RAW_FMT4(thr, file, line, err, fmt, arg1, arg2, arg3, arg4) \
10209 do { \
10210 duk_errcode_t duk__err = (err); \
10211 duk_int_t duk__line = (duk_int_t) (line); \
10212 DUK_ASSERT(duk__err >= 0 && duk__err <= 0xff); \
10213 DUK_ASSERT(duk__line >= 0 && duk__line <= 0x00ffffffL); \
10214 duk_err_handle_error_fmt((thr), \
10215 (file), \
10216 (((duk_uint_t) duk__err) << 24) | ((duk_uint_t) duk__line), \
10217 (fmt), \
10218 (arg1), \
10219 (arg2), \
10220 (arg3), \
10221 (arg4)); \
10222 } while (0)
10223
10224#else /* DUK_USE_VERBOSE_ERRORS */
10225
10226#define DUK_ERROR(thr, err, msg) duk_err_handle_error((thr), (err))
10227#define DUK_ERROR_RAW(thr, file, line, err, msg) duk_err_handle_error((thr), (err))
10228
10229#define DUK_ERROR_FMT1(thr, err, fmt, arg1) DUK_ERROR((thr), (err), (fmt))
10230#define DUK_ERROR_RAW_FMT1(thr, file, line, err, fmt, arg1) DUK_ERROR_RAW((thr), (file), (line), (err), (fmt))
10231
10232#define DUK_ERROR_FMT2(thr, err, fmt, arg1, arg2) DUK_ERROR((thr), (err), (fmt))
10233#define DUK_ERROR_RAW_FMT2(thr, file, line, err, fmt, arg1, arg2) DUK_ERROR_RAW((thr), (file), (line), (err), (fmt))
10234
10235#define DUK_ERROR_FMT3(thr, err, fmt, arg1, arg2, arg3) DUK_ERROR((thr), (err), (fmt))
10236#define DUK_ERROR_RAW_FMT3(thr, file, line, err, fmt, arg1, arg2, arg3) DUK_ERROR_RAW((thr), (file), (line), (err), (fmt))
10237
10238#define DUK_ERROR_FMT4(thr, err, fmt, arg1, arg2, arg3, arg4) DUK_ERROR((thr), (err), (fmt))
10239#define DUK_ERROR_RAW_FMT4(thr, file, line, err, fmt, arg1, arg2, arg3, arg4) DUK_ERROR_RAW((thr), (file), (line), (err), (fmt))
10241#endif /* DUK_USE_VERBOSE_ERRORS */
10242
10243/*
10244 * Fatal error without context
10245 *
10246 * The macro is an expression to make it compatible with DUK_ASSERT_EXPR().
10247 */
10248
10249#define DUK_FATAL_WITHOUT_CONTEXT(msg) duk_default_fatal_handler(NULL, (msg))
10250
10251/*
10252 * Error throwing helpers
10253 *
10254 * The goal is to provide verbose and configurable error messages. Call
10255 * sites should be clean in source code and compile to a small footprint.
10256 * Small footprint is also useful for performance because small cold paths
10257 * reduce code cache pressure. Adding macros here only makes sense if there
10258 * are enough call sites to get concrete benefits.
10259 *
10260 * DUK_ERROR_xxx() macros are generic and can be used anywhere.
10261 *
10262 * DUK_DCERROR_xxx() macros can only be used in Duktape/C functions where
10263 * the "return DUK_RET_xxx;" shorthand is available for low memory targets.
10264 * The DUK_DCERROR_xxx() macros always either throw or perform a
10265 * 'return DUK_RET_xxx' from the calling function.
10266 */
10267
10268#if defined(DUK_USE_VERBOSE_ERRORS)
10269/* Verbose errors with key/value summaries (non-paranoid) or without key/value
10270 * summaries (paranoid, for some security sensitive environments), the paranoid
10271 * vs. non-paranoid distinction affects only a few specific errors.
10272 */
10273#if defined(DUK_USE_PARANOID_ERRORS)
10274#define DUK_ERROR_REQUIRE_TYPE_INDEX(thr, idx, expectname, lowmemstr) \
10275 do { \
10276 duk_err_require_type_index((thr), DUK_FILE_MACRO, (duk_int_t) DUK_LINE_MACRO, (idx), (expectname)); \
10277 } while (0)
10278#else /* DUK_USE_PARANOID_ERRORS */
10279#define DUK_ERROR_REQUIRE_TYPE_INDEX(thr, idx, expectname, lowmemstr) \
10280 do { \
10281 duk_err_require_type_index((thr), DUK_FILE_MACRO, (duk_int_t) DUK_LINE_MACRO, (idx), (expectname)); \
10282 } while (0)
10283#endif /* DUK_USE_PARANOID_ERRORS */
10284
10285#define DUK_ERROR_INTERNAL(thr) \
10286 do { \
10287 duk_err_error_internal((thr), DUK_FILE_MACRO, (duk_int_t) DUK_LINE_MACRO); \
10288 } while (0)
10289#define DUK_DCERROR_INTERNAL(thr) \
10290 do { \
10291 DUK_ERROR_INTERNAL((thr)); \
10292 return 0; \
10293 } while (0)
10294#define DUK_ERROR_ALLOC_FAILED(thr) \
10295 do { \
10296 duk_err_error_alloc_failed((thr), DUK_FILE_MACRO, (duk_int_t) DUK_LINE_MACRO); \
10297 } while (0)
10298#define DUK_ERROR_UNSUPPORTED(thr) \
10299 do { \
10300 DUK_ERROR((thr), DUK_ERR_ERROR, DUK_STR_UNSUPPORTED); \
10301 } while (0)
10302#define DUK_DCERROR_UNSUPPORTED(thr) \
10303 do { \
10304 DUK_ERROR_UNSUPPORTED((thr)); \
10305 return 0; \
10306 } while (0)
10307#define DUK_ERROR_ERROR(thr, msg) \
10308 do { \
10309 duk_err_error((thr), DUK_FILE_MACRO, (duk_int_t) DUK_LINE_MACRO, (msg)); \
10310 } while (0)
10311#define DUK_ERROR_RANGE_INDEX(thr, idx) \
10312 do { \
10313 duk_err_range_index((thr), DUK_FILE_MACRO, (duk_int_t) DUK_LINE_MACRO, (idx)); \
10314 } while (0)
10315#define DUK_ERROR_RANGE_PUSH_BEYOND(thr) \
10316 do { \
10317 duk_err_range_push_beyond((thr), DUK_FILE_MACRO, (duk_int_t) DUK_LINE_MACRO); \
10318 } while (0)
10319#define DUK_ERROR_RANGE_INVALID_ARGS(thr) \
10320 do { \
10321 DUK_ERROR_RANGE((thr), DUK_STR_INVALID_ARGS); \
10322 } while (0)
10323#define DUK_DCERROR_RANGE_INVALID_ARGS(thr) \
10324 do { \
10325 DUK_ERROR_RANGE_INVALID_ARGS((thr)); \
10326 return 0; \
10327 } while (0)
10328#define DUK_ERROR_RANGE_INVALID_COUNT(thr) \
10329 do { \
10330 DUK_ERROR_RANGE((thr), DUK_STR_INVALID_COUNT); \
10331 } while (0)
10332#define DUK_DCERROR_RANGE_INVALID_COUNT(thr) \
10333 do { \
10334 DUK_ERROR_RANGE_INVALID_COUNT((thr)); \
10335 return 0; \
10336 } while (0)
10337#define DUK_ERROR_RANGE_INVALID_LENGTH(thr) \
10338 do { \
10339 DUK_ERROR_RANGE((thr), DUK_STR_INVALID_LENGTH); \
10340 } while (0)
10341#define DUK_DCERROR_RANGE_INVALID_LENGTH(thr) \
10342 do { \
10343 DUK_ERROR_RANGE_INVALID_LENGTH((thr)); \
10344 return 0; \
10345 } while (0)
10346#define DUK_ERROR_RANGE(thr, msg) \
10347 do { \
10348 duk_err_range((thr), DUK_FILE_MACRO, (duk_int_t) DUK_LINE_MACRO, (msg)); \
10349 } while (0)
10350#define DUK_ERROR_EVAL(thr, msg) \
10351 do { \
10352 DUK_ERROR((thr), DUK_ERR_EVAL_ERROR, (msg)); \
10353 } while (0)
10354#define DUK_ERROR_REFERENCE(thr, msg) \
10355 do { \
10356 DUK_ERROR((thr), DUK_ERR_REFERENCE_ERROR, (msg)); \
10357 } while (0)
10358#define DUK_ERROR_SYNTAX(thr, msg) \
10359 do { \
10360 DUK_ERROR((thr), DUK_ERR_SYNTAX_ERROR, (msg)); \
10361 } while (0)
10362#define DUK_ERROR_TYPE_INVALID_ARGS(thr) \
10363 do { \
10364 duk_err_type_invalid_args((thr), DUK_FILE_MACRO, (duk_int_t) DUK_LINE_MACRO); \
10365 } while (0)
10366#define DUK_DCERROR_TYPE_INVALID_ARGS(thr) \
10367 do { \
10368 DUK_ERROR_TYPE_INVALID_ARGS((thr)); \
10369 return 0; \
10370 } while (0)
10371#define DUK_ERROR_TYPE_INVALID_STATE(thr) \
10372 do { \
10373 duk_err_type_invalid_state((thr), DUK_FILE_MACRO, (duk_int_t) DUK_LINE_MACRO); \
10374 } while (0)
10375#define DUK_DCERROR_TYPE_INVALID_STATE(thr) \
10376 do { \
10377 DUK_ERROR_TYPE_INVALID_STATE((thr)); \
10378 return 0; \
10379 } while (0)
10380#define DUK_ERROR_TYPE_INVALID_TRAP_RESULT(thr) \
10381 do { \
10382 duk_err_type_invalid_trap_result((thr), DUK_FILE_MACRO, (duk_int_t) DUK_LINE_MACRO); \
10383 } while (0)
10384#define DUK_DCERROR_TYPE_INVALID_TRAP_RESULT(thr) \
10385 do { \
10386 DUK_ERROR_TYPE((thr), DUK_STR_INVALID_TRAP_RESULT); \
10387 } while (0)
10388#define DUK_ERROR_TYPE(thr, msg) \
10389 do { \
10390 DUK_ERROR((thr), DUK_ERR_TYPE_ERROR, (msg)); \
10391 } while (0)
10392#define DUK_ERROR_URI(thr, msg) \
10393 do { \
10394 DUK_ERROR((thr), DUK_ERR_URI_ERROR, (msg)); \
10395 } while (0)
10396#else /* DUK_USE_VERBOSE_ERRORS */
10397/* Non-verbose errors for low memory targets: no file, line, or message. */
10398
10399#define DUK_ERROR_REQUIRE_TYPE_INDEX(thr, idx, expectname, lowmemstr) \
10400 do { \
10401 duk_err_type((thr)); \
10402 } while (0)
10403
10404#define DUK_ERROR_INTERNAL(thr) \
10405 do { \
10406 duk_err_error((thr)); \
10407 } while (0)
10408#define DUK_DCERROR_INTERNAL(thr) \
10409 do { \
10410 DUK_UNREF((thr)); \
10411 return DUK_RET_ERROR; \
10412 } while (0)
10413#define DUK_ERROR_ALLOC_FAILED(thr) \
10414 do { \
10415 duk_err_error((thr)); \
10416 } while (0)
10417#define DUK_ERROR_UNSUPPORTED(thr) \
10418 do { \
10419 duk_err_error((thr)); \
10420 } while (0)
10421#define DUK_DCERROR_UNSUPPORTED(thr) \
10422 do { \
10423 DUK_UNREF((thr)); \
10424 return DUK_RET_ERROR; \
10425 } while (0)
10426#define DUK_ERROR_ERROR(thr, msg) \
10427 do { \
10428 duk_err_error((thr)); \
10429 } while (0)
10430#define DUK_ERROR_RANGE_INDEX(thr, idx) \
10431 do { \
10432 duk_err_range((thr)); \
10433 } while (0)
10434#define DUK_ERROR_RANGE_PUSH_BEYOND(thr) \
10435 do { \
10436 duk_err_range((thr)); \
10437 } while (0)
10438#define DUK_ERROR_RANGE_INVALID_ARGS(thr) \
10439 do { \
10440 duk_err_range((thr)); \
10441 } while (0)
10442#define DUK_DCERROR_RANGE_INVALID_ARGS(thr) \
10443 do { \
10444 DUK_UNREF((thr)); \
10445 return DUK_RET_RANGE_ERROR; \
10446 } while (0)
10447#define DUK_ERROR_RANGE_INVALID_COUNT(thr) \
10448 do { \
10449 duk_err_range((thr)); \
10450 } while (0)
10451#define DUK_DCERROR_RANGE_INVALID_COUNT(thr) \
10452 do { \
10453 DUK_UNREF((thr)); \
10454 return DUK_RET_RANGE_ERROR; \
10455 } while (0)
10456#define DUK_ERROR_RANGE_INVALID_LENGTH(thr) \
10457 do { \
10458 duk_err_range((thr)); \
10459 } while (0)
10460#define DUK_DCERROR_RANGE_INVALID_LENGTH(thr) \
10461 do { \
10462 DUK_UNREF((thr)); \
10463 return DUK_RET_RANGE_ERROR; \
10464 } while (0)
10465#define DUK_ERROR_RANGE(thr, msg) \
10466 do { \
10467 duk_err_range((thr)); \
10468 } while (0)
10469#define DUK_ERROR_EVAL(thr, msg) \
10470 do { \
10471 duk_err_eval((thr)); \
10472 } while (0)
10473#define DUK_ERROR_REFERENCE(thr, msg) \
10474 do { \
10475 duk_err_reference((thr)); \
10476 } while (0)
10477#define DUK_ERROR_SYNTAX(thr, msg) \
10478 do { \
10479 duk_err_syntax((thr)); \
10480 } while (0)
10481#define DUK_ERROR_TYPE_INVALID_ARGS(thr) \
10482 do { \
10483 duk_err_type((thr)); \
10484 } while (0)
10485#define DUK_DCERROR_TYPE_INVALID_ARGS(thr) \
10486 do { \
10487 DUK_UNREF((thr)); \
10488 return DUK_RET_TYPE_ERROR; \
10489 } while (0)
10490#define DUK_ERROR_TYPE_INVALID_STATE(thr) \
10491 do { \
10492 duk_err_type((thr)); \
10493 } while (0)
10494#define DUK_DCERROR_TYPE_INVALID_STATE(thr) \
10495 do { \
10496 duk_err_type((thr)); \
10497 } while (0)
10498#define DUK_ERROR_TYPE_INVALID_TRAP_RESULT(thr) \
10499 do { \
10500 duk_err_type((thr)); \
10501 } while (0)
10502#define DUK_DCERROR_TYPE_INVALID_TRAP_RESULT(thr) \
10503 do { \
10504 DUK_UNREF((thr)); \
10505 return DUK_RET_TYPE_ERROR; \
10506 } while (0)
10507#define DUK_ERROR_TYPE_INVALID_TRAP_RESULT(thr) \
10508 do { \
10509 duk_err_type((thr)); \
10510 } while (0)
10511#define DUK_ERROR_TYPE(thr, msg) \
10512 do { \
10513 duk_err_type((thr)); \
10514 } while (0)
10515#define DUK_ERROR_URI(thr, msg) \
10516 do { \
10517 duk_err_uri((thr)); \
10518 } while (0)
10519#endif /* DUK_USE_VERBOSE_ERRORS */
10520
10521/*
10522 * Assert macro: failure causes a fatal error.
10523 *
10524 * NOTE: since the assert macro doesn't take a heap/context argument, there's
10525 * no way to look up a heap/context specific fatal error handler which may have
10526 * been given by the application. Instead, assertion failures always use the
10527 * internal default fatal error handler; it can be replaced via duk_config.h
10528 * and then applies to all Duktape heaps.
10529 */
10530
10531#if defined(DUK_USE_ASSERTIONS)
10532
10533/* The message should be a compile time constant without formatting (less risk);
10534 * we don't care about assertion text size because they're not used in production
10535 * builds.
10536 */
10537#define DUK_ASSERT(x) \
10538 do { \
10539 if (!(x)) { \
10540 DUK_FATAL_WITHOUT_CONTEXT("assertion failed: " #x " (" DUK_FILE_MACRO \
10541 ":" DUK_MACRO_STRINGIFY(DUK_LINE_MACRO) ")"); \
10542 } \
10543 } while (0)
10544
10545/* Assertion compatible inside a comma expression, evaluates to void. */
10546#define DUK_ASSERT_EXPR(x) \
10547 ((void) ((x) ? 0 : \
10548 (DUK_FATAL_WITHOUT_CONTEXT("assertion failed: " #x " (" DUK_FILE_MACRO \
10549 ":" DUK_MACRO_STRINGIFY(DUK_LINE_MACRO) ")"), \
10550 0)))
10551
10552#else /* DUK_USE_ASSERTIONS */
10553
10554#define DUK_ASSERT(x) \
10555 do { /* assertion omitted */ \
10556 } while (0)
10557
10558#define DUK_ASSERT_EXPR(x) ((void) 0)
10559
10560#endif /* DUK_USE_ASSERTIONS */
10561
10562/* this variant is used when an assert would generate a compile warning by
10563 * being always true (e.g. >= 0 comparison for an unsigned value
10564 */
10565#define DUK_ASSERT_DISABLE(x) \
10566 do { /* assertion disabled */ \
10567 } while (0)
10568
10569/*
10570 * Assertion helpers
10571 */
10572
10573#if defined(DUK_USE_ASSERTIONS) && defined(DUK_USE_REFERENCE_COUNTING)
10574#define DUK_ASSERT_REFCOUNT_NONZERO_HEAPHDR(h) \
10575 do { \
10576 DUK_ASSERT((h) == NULL || DUK_HEAPHDR_GET_REFCOUNT((duk_heaphdr *) (h)) > 0); \
10577 } while (0)
10578#define DUK_ASSERT_REFCOUNT_NONZERO_TVAL(tv) \
10579 do { \
10580 if ((tv) != NULL && DUK_TVAL_IS_HEAP_ALLOCATED((tv))) { \
10581 DUK_ASSERT(DUK_HEAPHDR_GET_REFCOUNT(DUK_TVAL_GET_HEAPHDR((tv))) > 0); \
10582 } \
10583 } while (0)
10584#else
10585#define DUK_ASSERT_REFCOUNT_NONZERO_HEAPHDR(h) /* no refcount check */
10586#define DUK_ASSERT_REFCOUNT_NONZERO_TVAL(tv) /* no refcount check */
10587#endif
10588
10589#define DUK_ASSERT_TOP(ctx, n) DUK_ASSERT((duk_idx_t) duk_get_top((ctx)) == (duk_idx_t) (n))
10591#if defined(DUK_USE_ASSERTIONS) && defined(DUK_USE_PACKED_TVAL)
10592#define DUK_ASSERT_DOUBLE_IS_NORMALIZED(dval) \
10593 do { \
10594 duk_double_union duk__assert_tmp_du; \
10595 duk__assert_tmp_du.d = (dval); \
10596 DUK_ASSERT(DUK_DBLUNION_IS_NORMALIZED(&duk__assert_tmp_du)); \
10597 } while (0)
10598#else
10599#define DUK_ASSERT_DOUBLE_IS_NORMALIZED(dval) /* nop */
10600#endif
10601
10602#define DUK_ASSERT_VS_SPACE(thr) DUK_ASSERT(thr->valstack_top < thr->valstack_end)
10603
10604/*
10605 * Helper to initialize a memory area (e.g. struct) with garbage when
10606 * assertions enabled.
10607 */
10608
10609#if defined(DUK_USE_ASSERTIONS)
10610#define DUK_ASSERT_SET_GARBAGE(ptr, size) \
10611 do { \
10612 duk_memset_unsafe((void *) (ptr), 0x5a, size); \
10613 } while (0)
10614#else
10615#define DUK_ASSERT_SET_GARBAGE(ptr, size) \
10616 do { \
10617 } while (0)
10618#endif
10620/*
10621 * Helper for valstack space
10622 *
10623 * Caller of DUK_ASSERT_VALSTACK_SPACE() estimates the number of free stack entries
10624 * required for its own use, and any child calls which are not (a) Duktape API calls
10625 * or (b) Duktape calls which involve extending the valstack (e.g. getter call).
10626 */
10627
10628#define DUK_VALSTACK_ASSERT_EXTRA \
10629 5 /* this is added to checks to allow for Duktape \
10630 * API calls in addition to function's own use \
10631 */
10632#if defined(DUK_USE_ASSERTIONS)
10633#define DUK_ASSERT_VALSTACK_SPACE(thr, n) \
10634 do { \
10635 DUK_ASSERT((thr) != NULL); \
10636 DUK_ASSERT((thr)->valstack_end - (thr)->valstack_top >= (n) + DUK_VALSTACK_ASSERT_EXTRA); \
10637 } while (0)
10638#else
10639#define DUK_ASSERT_VALSTACK_SPACE(thr, n) /* no valstack space check */
10640#endif
10641
10642/*
10643 * Prototypes
10644 */
10646#if defined(DUK_USE_VERBOSE_ERRORS)
10648 DUK_INTERNAL_DECL void duk_err_handle_error(duk_hthread *thr, const char *filename, duk_uint_t line_and_code, const char *msg));
10650 duk_err_handle_error_fmt(duk_hthread *thr, const char *filename, duk_uint_t line_and_code, const char *fmt, ...));
10651#else /* DUK_USE_VERBOSE_ERRORS */
10653#endif /* DUK_USE_VERBOSE_ERRORS */
10655#if defined(DUK_USE_VERBOSE_ERRORS)
10658 const char *msg,
10659 const char *filename,
10660 duk_int_t line));
10661#else
10663#endif
10664
10666
10667#define DUK_AUGMENT_FLAG_NOBLAME_FILELINE (1U << 0) /* if set, don't blame C file/line for .fileName and .lineNumber */
10668#define DUK_AUGMENT_FLAG_SKIP_ONE (1U << 1) /* if set, skip topmost activation in traceback construction */
10669
10670#if defined(DUK_USE_AUGMENT_ERROR_CREATE)
10672 duk_hthread *thr_callstack,
10673 const char *filename,
10675 duk_small_uint_t flags);
10676#endif
10677#if defined(DUK_USE_AUGMENT_ERROR_THROW)
10679#endif
10680
10681#if defined(DUK_USE_VERBOSE_ERRORS)
10682#if defined(DUK_USE_PARANOID_ERRORS)
10684 const char *filename,
10685 duk_int_t linenumber,
10687 const char *expect_name));
10688#else
10690 const char *filename,
10691 duk_int_t linenumber,
10692 duk_idx_t idx,
10693 const char *expect_name));
10694#endif
10695DUK_NORETURN(DUK_INTERNAL_DECL void duk_err_error_internal(duk_hthread *thr, const char *filename, duk_int_t linenumber));
10696DUK_NORETURN(DUK_INTERNAL_DECL void duk_err_error_alloc_failed(duk_hthread *thr, const char *filename, duk_int_t linenumber));
10698 DUK_INTERNAL_DECL void duk_err_error(duk_hthread *thr, const char *filename, duk_int_t linenumber, const char *message));
10700 DUK_INTERNAL_DECL void duk_err_range_index(duk_hthread *thr, const char *filename, duk_int_t linenumber, duk_idx_t idx));
10701DUK_NORETURN(DUK_INTERNAL_DECL void duk_err_range_push_beyond(duk_hthread *thr, const char *filename, duk_int_t linenumber));
10703 DUK_INTERNAL_DECL void duk_err_range(duk_hthread *thr, const char *filename, duk_int_t linenumber, const char *message));
10704DUK_NORETURN(DUK_INTERNAL_DECL void duk_err_type_invalid_args(duk_hthread *thr, const char *filename, duk_int_t linenumber));
10705DUK_NORETURN(DUK_INTERNAL_DECL void duk_err_type_invalid_state(duk_hthread *thr, const char *filename, duk_int_t linenumber));
10707#else /* DUK_VERBOSE_ERRORS */
10710DUK_NORETURN(DUK_INTERNAL_DECL void duk_err_eval(duk_hthread *thr));
10711DUK_NORETURN(DUK_INTERNAL_DECL void duk_err_reference(duk_hthread *thr));
10712DUK_NORETURN(DUK_INTERNAL_DECL void duk_err_syntax(duk_hthread *thr));
10713DUK_NORETURN(DUK_INTERNAL_DECL void duk_err_type(duk_hthread *thr));
10714DUK_NORETURN(DUK_INTERNAL_DECL void duk_err_uri(duk_hthread *thr));
10715#endif /* DUK_VERBOSE_ERRORS */
10716
10718
10719DUK_NORETURN(DUK_INTERNAL_DECL void duk_default_fatal_handler(void *udata, const char *msg));
10720
10722#if defined(DUK_USE_DEBUGGER_SUPPORT)
10723DUK_INTERNAL_DECL void duk_err_check_debugger_integration(duk_hthread *thr);
10724#endif
10725
10727
10728#endif /* DUK_ERROR_H_INCLUDED */
10729/* #include duk_unicode.h */
10731 * Unicode helpers
10734#if !defined(DUK_UNICODE_H_INCLUDED)
10735#define DUK_UNICODE_H_INCLUDED
10736
10737/*
10738 * UTF-8 / XUTF-8 / CESU-8 constants
10739 */
10740
10741#define DUK_UNICODE_MAX_XUTF8_LENGTH 7 /* up to 36 bit codepoints */
10742#define DUK_UNICODE_MAX_XUTF8_BMP_LENGTH 3 /* all codepoints up to U+FFFF */
10743#define DUK_UNICODE_MAX_CESU8_LENGTH 6 /* all codepoints up to U+10FFFF */
10744#define DUK_UNICODE_MAX_CESU8_BMP_LENGTH 3 /* all codepoints up to U+FFFF */
10745
10746/*
10747 * Useful Unicode codepoints
10748 *
10749 * Integer constants must be signed to avoid unexpected coercions
10750 * in comparisons.
10751 */
10752
10753#define DUK_UNICODE_CP_ZWNJ 0x200cL /* zero-width non-joiner */
10754#define DUK_UNICODE_CP_ZWJ 0x200dL /* zero-width joiner */
10755#define DUK_UNICODE_CP_REPLACEMENT_CHARACTER \
10756 0xfffdL /* http://en.wikipedia.org/wiki/Replacement_character#Replacement_character \
10757 */
10760 * ASCII character constants
10762 * C character literals like 'x' have a platform specific value and do
10763 * not match ASCII (UTF-8) values on e.g. EBCDIC platforms. So, use
10764 * these (admittedly awkward) constants instead. These constants must
10765 * also have signed values to avoid unexpected coercions in comparisons.
10767 * http://en.wikipedia.org/wiki/ASCII
10770#define DUK_ASC_NUL 0x00
10771#define DUK_ASC_SOH 0x01
10772#define DUK_ASC_STX 0x02
10773#define DUK_ASC_ETX 0x03
10774#define DUK_ASC_EOT 0x04
10775#define DUK_ASC_ENQ 0x05
10776#define DUK_ASC_ACK 0x06
10777#define DUK_ASC_BEL 0x07
10778#define DUK_ASC_BS 0x08
10779#define DUK_ASC_HT 0x09
10780#define DUK_ASC_LF 0x0a
10781#define DUK_ASC_VT 0x0b
10782#define DUK_ASC_FF 0x0c
10783#define DUK_ASC_CR 0x0d
10784#define DUK_ASC_SO 0x0e
10785#define DUK_ASC_SI 0x0f
10786#define DUK_ASC_DLE 0x10
10787#define DUK_ASC_DC1 0x11
10788#define DUK_ASC_DC2 0x12
10789#define DUK_ASC_DC3 0x13
10790#define DUK_ASC_DC4 0x14
10791#define DUK_ASC_NAK 0x15
10792#define DUK_ASC_SYN 0x16
10793#define DUK_ASC_ETB 0x17
10794#define DUK_ASC_CAN 0x18
10795#define DUK_ASC_EM 0x19
10796#define DUK_ASC_SUB 0x1a
10797#define DUK_ASC_ESC 0x1b
10798#define DUK_ASC_FS 0x1c
10799#define DUK_ASC_GS 0x1d
10800#define DUK_ASC_RS 0x1e
10801#define DUK_ASC_US 0x1f
10802#define DUK_ASC_SPACE 0x20
10803#define DUK_ASC_EXCLAMATION 0x21
10804#define DUK_ASC_DOUBLEQUOTE 0x22
10805#define DUK_ASC_HASH 0x23
10806#define DUK_ASC_DOLLAR 0x24
10807#define DUK_ASC_PERCENT 0x25
10808#define DUK_ASC_AMP 0x26
10809#define DUK_ASC_SINGLEQUOTE 0x27
10810#define DUK_ASC_LPAREN 0x28
10811#define DUK_ASC_RPAREN 0x29
10812#define DUK_ASC_STAR 0x2a
10813#define DUK_ASC_PLUS 0x2b
10814#define DUK_ASC_COMMA 0x2c
10815#define DUK_ASC_MINUS 0x2d
10816#define DUK_ASC_PERIOD 0x2e
10817#define DUK_ASC_SLASH 0x2f
10818#define DUK_ASC_0 0x30
10819#define DUK_ASC_1 0x31
10820#define DUK_ASC_2 0x32
10821#define DUK_ASC_3 0x33
10822#define DUK_ASC_4 0x34
10823#define DUK_ASC_5 0x35
10824#define DUK_ASC_6 0x36
10825#define DUK_ASC_7 0x37
10826#define DUK_ASC_8 0x38
10827#define DUK_ASC_9 0x39
10828#define DUK_ASC_COLON 0x3a
10829#define DUK_ASC_SEMICOLON 0x3b
10830#define DUK_ASC_LANGLE 0x3c
10831#define DUK_ASC_EQUALS 0x3d
10832#define DUK_ASC_RANGLE 0x3e
10833#define DUK_ASC_QUESTION 0x3f
10834#define DUK_ASC_ATSIGN 0x40
10835#define DUK_ASC_UC_A 0x41
10836#define DUK_ASC_UC_B 0x42
10837#define DUK_ASC_UC_C 0x43
10838#define DUK_ASC_UC_D 0x44
10839#define DUK_ASC_UC_E 0x45
10840#define DUK_ASC_UC_F 0x46
10841#define DUK_ASC_UC_G 0x47
10842#define DUK_ASC_UC_H 0x48
10843#define DUK_ASC_UC_I 0x49
10844#define DUK_ASC_UC_J 0x4a
10845#define DUK_ASC_UC_K 0x4b
10846#define DUK_ASC_UC_L 0x4c
10847#define DUK_ASC_UC_M 0x4d
10848#define DUK_ASC_UC_N 0x4e
10849#define DUK_ASC_UC_O 0x4f
10850#define DUK_ASC_UC_P 0x50
10851#define DUK_ASC_UC_Q 0x51
10852#define DUK_ASC_UC_R 0x52
10853#define DUK_ASC_UC_S 0x53
10854#define DUK_ASC_UC_T 0x54
10855#define DUK_ASC_UC_U 0x55
10856#define DUK_ASC_UC_V 0x56
10857#define DUK_ASC_UC_W 0x57
10858#define DUK_ASC_UC_X 0x58
10859#define DUK_ASC_UC_Y 0x59
10860#define DUK_ASC_UC_Z 0x5a
10861#define DUK_ASC_LBRACKET 0x5b
10862#define DUK_ASC_BACKSLASH 0x5c
10863#define DUK_ASC_RBRACKET 0x5d
10864#define DUK_ASC_CARET 0x5e
10865#define DUK_ASC_UNDERSCORE 0x5f
10866#define DUK_ASC_GRAVE 0x60
10867#define DUK_ASC_LC_A 0x61
10868#define DUK_ASC_LC_B 0x62
10869#define DUK_ASC_LC_C 0x63
10870#define DUK_ASC_LC_D 0x64
10871#define DUK_ASC_LC_E 0x65
10872#define DUK_ASC_LC_F 0x66
10873#define DUK_ASC_LC_G 0x67
10874#define DUK_ASC_LC_H 0x68
10875#define DUK_ASC_LC_I 0x69
10876#define DUK_ASC_LC_J 0x6a
10877#define DUK_ASC_LC_K 0x6b
10878#define DUK_ASC_LC_L 0x6c
10879#define DUK_ASC_LC_M 0x6d
10880#define DUK_ASC_LC_N 0x6e
10881#define DUK_ASC_LC_O 0x6f
10882#define DUK_ASC_LC_P 0x70
10883#define DUK_ASC_LC_Q 0x71
10884#define DUK_ASC_LC_R 0x72
10885#define DUK_ASC_LC_S 0x73
10886#define DUK_ASC_LC_T 0x74
10887#define DUK_ASC_LC_U 0x75
10888#define DUK_ASC_LC_V 0x76
10889#define DUK_ASC_LC_W 0x77
10890#define DUK_ASC_LC_X 0x78
10891#define DUK_ASC_LC_Y 0x79
10892#define DUK_ASC_LC_Z 0x7a
10893#define DUK_ASC_LCURLY 0x7b
10894#define DUK_ASC_PIPE 0x7c
10895#define DUK_ASC_RCURLY 0x7d
10896#define DUK_ASC_TILDE 0x7e
10897#define DUK_ASC_DEL 0x7f
10898
10899/*
10900 * Miscellaneous
10901 */
10902
10903/* Uppercase A is 0x41, lowercase a is 0x61; OR 0x20 to convert uppercase
10904 * to lowercase.
10905 */
10906#define DUK_LOWERCASE_CHAR_ASCII(x) ((x) | 0x20)
10907
10908/*
10909 * Unicode tables
10910 */
10911
10912#if defined(DUK_USE_SOURCE_NONBMP)
10913/*
10914 * Automatically generated by extract_chars.py, do not edit!
10915 */
10916
10917extern const duk_uint8_t duk_unicode_ids_noa[1116];
10918#else
10919/*
10920 * Automatically generated by extract_chars.py, do not edit!
10921 */
10922
10923extern const duk_uint8_t duk_unicode_ids_noabmp[625];
10924#endif
10925
10926#if defined(DUK_USE_SOURCE_NONBMP)
10927/*
10928 * Automatically generated by extract_chars.py, do not edit!
10929 */
10930
10931extern const duk_uint8_t duk_unicode_ids_m_let_noa[42];
10932#else
10933/*
10934 * Automatically generated by extract_chars.py, do not edit!
10935 */
10936
10937extern const duk_uint8_t duk_unicode_ids_m_let_noabmp[24];
10938#endif
10939
10940#if defined(DUK_USE_SOURCE_NONBMP)
10941/*
10942 * Automatically generated by extract_chars.py, do not edit!
10943 */
10944
10945extern const duk_uint8_t duk_unicode_idp_m_ids_noa[576];
10946#else
10947/*
10948 * Automatically generated by extract_chars.py, do not edit!
10949 */
10950
10951extern const duk_uint8_t duk_unicode_idp_m_ids_noabmp[358];
10952#endif
10953
10954/*
10955 * Automatically generated by extract_caseconv.py, do not edit!
10956 */
10957
10958extern const duk_uint8_t duk_unicode_caseconv_uc[1411];
10959extern const duk_uint8_t duk_unicode_caseconv_lc[706];
10960
10961#if defined(DUK_USE_REGEXP_CANON_WORKAROUND)
10963 * Automatically generated by extract_caseconv.py, do not edit!
10965
10966extern const duk_uint16_t duk_unicode_re_canon_lookup[65536];
10967#endif
10968
10969#if defined(DUK_USE_REGEXP_CANON_BITMAP)
10970/*
10971 * Automatically generated by extract_caseconv.py, do not edit!
10972 */
10973
10974#define DUK_CANON_BITMAP_BLKSIZE 32
10975#define DUK_CANON_BITMAP_BLKSHIFT 5
10976#define DUK_CANON_BITMAP_BLKMASK 31
10977extern const duk_uint8_t duk_unicode_re_canon_bitmap[256];
10978#endif
10979
10980/*
10981 * Extern
10982 */
10983
10984/* duk_unicode_support.c */
10985#if !defined(DUK_SINGLE_FILE)
10986DUK_INTERNAL_DECL const duk_uint8_t duk_unicode_xutf8_markers[7];
10988DUK_INTERNAL_DECL const duk_uint16_t duk_unicode_re_ranges_white[22];
10993DUK_INTERNAL_DECL const duk_int8_t duk_is_idchar_tab[128];
10994#endif /* !DUK_SINGLE_FILE */
10995
10996/*
10997 * Prototypes
10998 */
10999
11001#if defined(DUK_USE_ASSERTIONS)
11002DUK_INTERNAL_DECL duk_small_int_t duk_unicode_get_cesu8_length(duk_ucodepoint_t cp);
11003#endif
11007 const duk_uint8_t **ptr,
11008 const duk_uint8_t *ptr_start,
11009 const duk_uint8_t *ptr_end,
11010 duk_ucodepoint_t *out_cp);
11012 const duk_uint8_t **ptr,
11013 const duk_uint8_t *ptr_start,
11014 const duk_uint8_t *ptr_end);
11023#if defined(DUK_USE_REGEXP_SUPPORT)
11026#endif
11028#endif /* DUK_UNICODE_H_INCLUDED */
11029/* #include duk_json.h */
11030/*
11031 * Defines for JSON, especially duk_bi_json.c.
11033
11034#if !defined(DUK_JSON_H_INCLUDED)
11035#define DUK_JSON_H_INCLUDED
11036
11037/* Encoding/decoding flags */
11038#define DUK_JSON_FLAG_ASCII_ONLY (1U << 0) /* escape any non-ASCII characters */
11039#define DUK_JSON_FLAG_AVOID_KEY_QUOTES (1U << 1) /* avoid key quotes when key is an ASCII Identifier */
11040#define DUK_JSON_FLAG_EXT_CUSTOM (1U << 2) /* extended types: custom encoding */
11041#define DUK_JSON_FLAG_EXT_COMPATIBLE (1U << 3) /* extended types: compatible encoding */
11043/* How much stack to require on entry to object/array encode */
11044#define DUK_JSON_ENC_REQSTACK 32
11046/* How much stack to require on entry to object/array decode */
11047#define DUK_JSON_DEC_REQSTACK 32
11049/* How large a loop detection stack to use */
11050#define DUK_JSON_ENC_LOOPARRAY 64
11051
11052/* Encoding state. Heap object references are all borrowed. */
11053typedef struct {
11055 duk_bufwriter_ctx bw; /* output bufwriter */
11056 duk_hobject *h_replacer; /* replacer function */
11057 duk_hstring *h_gap; /* gap (if empty string, NULL) */
11058 duk_idx_t idx_proplist; /* explicit PropertyList */
11059 duk_idx_t idx_loop; /* valstack index of loop detection object */
11061 duk_small_uint_t flag_ascii_only;
11062 duk_small_uint_t flag_avoid_key_quotes;
11063#if defined(DUK_USE_JX) || defined(DUK_USE_JC)
11064 duk_small_uint_t flag_ext_custom;
11065 duk_small_uint_t flag_ext_compatible;
11066 duk_small_uint_t flag_ext_custom_or_compatible;
11067#endif
11068 duk_uint_t recursion_depth;
11069 duk_uint_t recursion_limit;
11070 duk_uint_t mask_for_undefined; /* type bit mask: types which certainly produce 'undefined' */
11071#if defined(DUK_USE_JX) || defined(DUK_USE_JC)
11072 duk_small_uint_t stridx_custom_undefined;
11073 duk_small_uint_t stridx_custom_nan;
11074 duk_small_uint_t stridx_custom_neginf;
11075 duk_small_uint_t stridx_custom_posinf;
11076 duk_small_uint_t stridx_custom_function;
11077#endif
11078 duk_hobject *visiting[DUK_JSON_ENC_LOOPARRAY]; /* indexed by recursion_depth */
11080
11081typedef struct {
11083 const duk_uint8_t *p;
11084 const duk_uint8_t *p_start;
11085 const duk_uint8_t *p_end;
11086 duk_idx_t idx_reviver;
11087 duk_small_uint_t flags;
11088#if defined(DUK_USE_JX) || defined(DUK_USE_JC)
11089 duk_small_uint_t flag_ext_custom;
11090 duk_small_uint_t flag_ext_compatible;
11091 duk_small_uint_t flag_ext_custom_or_compatible;
11092#endif
11093 duk_int_t recursion_depth;
11094 duk_int_t recursion_limit;
11097#endif /* DUK_JSON_H_INCLUDED */
11098/* #include duk_js.h */
11100 * ECMAScript execution, support primitives.
11102
11103#if !defined(DUK_JS_H_INCLUDED)
11104#define DUK_JS_H_INCLUDED
11106/* Flags for call handling. Lowest flags must match bytecode DUK_BC_CALL_FLAG_xxx 1:1. */
11107#define DUK_CALL_FLAG_TAILCALL (1U << 0) /* setup for a tail call */
11108#define DUK_CALL_FLAG_CONSTRUCT (1U << 1) /* constructor call (i.e. called as 'new Foo()') */
11109#define DUK_CALL_FLAG_CALLED_AS_EVAL (1U << 2) /* call was made using the identifier 'eval' */
11110#define DUK_CALL_FLAG_ALLOW_ECMATOECMA (1U << 3) /* ecma-to-ecma call with executor reuse is possible */
11111#define DUK_CALL_FLAG_DIRECT_EVAL (1U << 4) /* call is a direct eval call */
11112#define DUK_CALL_FLAG_CONSTRUCT_PROXY (1U << 5) /* handled via 'construct' proxy trap, check return value invariant(s) */
11113#define DUK_CALL_FLAG_DEFAULT_INSTANCE_UPDATED \
11114 (1U << 6) /* prototype of 'default instance' updated, temporary flag in call handling */
11115
11116/* Flags for duk_js_equals_helper(). */
11117#define DUK_EQUALS_FLAG_SAMEVALUE (1U << 0) /* use SameValue instead of non-strict equality */
11118#define DUK_EQUALS_FLAG_STRICT (1U << 1) /* use strict equality instead of non-strict equality */
11119
11120/* Flags for duk_js_compare_helper(). */
11121#define DUK_COMPARE_FLAG_NEGATE (1U << 0) /* negate result */
11122#define DUK_COMPARE_FLAG_EVAL_LEFT_FIRST (1U << 1) /* eval left argument first */
11123
11124/* conversions, coercions, comparison, etc */
11132DUK_INTERNAL_DECL duk_uarridx_t duk_js_to_arrayindex_string(const duk_uint8_t *str, duk_uint32_t blen);
11133#if !defined(DUK_USE_HSTRING_ARRIDX)
11134DUK_INTERNAL_DECL duk_uarridx_t duk_js_to_arrayindex_hstring_fast_known(duk_hstring *h);
11135DUK_INTERNAL_DECL duk_uarridx_t duk_js_to_arrayindex_hstring_fast(duk_hstring *h);
11136#endif
11139 const duk_uint8_t *buf2,
11140 duk_size_t len1,
11141 duk_size_t len2);
11143#if 0 /* unused */
11144DUK_INTERNAL_DECL duk_small_int_t duk_js_buffer_compare(duk_heap *heap, duk_hbuffer *h1, duk_hbuffer *h2);
11145#endif
11148#if defined(DUK_USE_SYMBOL_BUILTIN)
11150#endif
11155
11156/* arithmetic */
11157DUK_INTERNAL_DECL double duk_js_arith_pow(double x, double y);
11158DUK_INTERNAL_DECL double duk_js_arith_mod(double x, double y);
11160#define duk_js_equals(thr, tv_x, tv_y) duk_js_equals_helper((thr), (tv_x), (tv_y), 0)
11161#define duk_js_strict_equals(tv_x, tv_y) duk_js_equals_helper(NULL, (tv_x), (tv_y), DUK_EQUALS_FLAG_STRICT)
11162#define duk_js_samevalue(tv_x, tv_y) duk_js_equals_helper(NULL, (tv_x), (tv_y), DUK_EQUALS_FLAG_SAMEVALUE)
11163
11164/* E5 Sections 11.8.1, 11.8.5; x < y */
11165#define duk_js_lessthan(thr, tv_x, tv_y) duk_js_compare_helper((thr), (tv_x), (tv_Y), DUK_COMPARE_FLAG_EVAL_LEFT_FIRST)
11166
11167/* E5 Sections 11.8.2, 11.8.5; x > y --> y < x */
11168#define duk_js_greaterthan(thr, tv_x, tv_y) duk_js_compare_helper((thr), (tv_y), (tv_x), 0)
11169
11170/* E5 Sections 11.8.3, 11.8.5; x <= y --> not (x > y) --> not (y < x) */
11171#define duk_js_lessthanorequal(thr, tv_x, tv_y) duk_js_compare_helper((thr), (tv_y), (tv_x), DUK_COMPARE_FLAG_NEGATE)
11172
11173/* E5 Sections 11.8.4, 11.8.5; x >= y --> not (x < y) */
11174#define duk_js_greaterthanorequal(thr, tv_x, tv_y) \
11175 duk_js_compare_helper((thr), (tv_x), (tv_y), DUK_COMPARE_FLAG_EVAL_LEFT_FIRST | DUK_COMPARE_FLAG_NEGATE)
11176
11177/* identifiers and environment handling */
11178#if 0 /*unused*/
11179DUK_INTERNAL duk_bool_t duk_js_hasvar_envrec(duk_hthread *thr, duk_hobject *env, duk_hstring *name);
11180#endif
11183 duk_activation *act,
11184 duk_hstring *name,
11185 duk_bool_t throw_flag);
11187 duk_hobject *env,
11188 duk_hstring *name,
11189 duk_tval *val,
11190 duk_bool_t strict);
11192 duk_activation *act,
11193 duk_hstring *name,
11194 duk_tval *val,
11195 duk_bool_t strict);
11196#if 0 /*unused*/
11197DUK_INTERNAL_DECL duk_bool_t duk_js_delvar_envrec(duk_hthread *thr, duk_hobject *env, duk_hstring *name);
11198#endif
11201 duk_activation *act,
11202 duk_hstring *name,
11203 duk_tval *val,
11204 duk_small_uint_t prop_flags,
11205 duk_bool_t is_func_decl);
11209 duk_hobject *func,
11210 duk_size_t bottom_byteoff);
11212 duk_hcompfunc *fun_temp,
11213 duk_hobject *outer_var_env,
11214 duk_hobject *outer_lex_env,
11215 duk_bool_t add_auto_proto);
11216
11217/* call handling */
11222duk_handle_safe_call(duk_hthread *thr, duk_safe_call_function func, void *udata, duk_idx_t num_stack_args, duk_idx_t num_stack_res);
11224#if defined(DUK_USE_VERBOSE_ERRORS)
11226#endif
11228/* bytecode execution */
11230
11231#endif /* DUK_JS_H_INCLUDED */
11232/* #include duk_numconv.h */
11233/*
11234 * Number-to-string conversion. The semantics of these is very tightly
11235 * bound with the ECMAScript semantics required for call sites.
11236 */
11237
11238#if !defined(DUK_NUMCONV_H_INCLUDED)
11239#define DUK_NUMCONV_H_INCLUDED
11240
11241/* Output a specified number of digits instead of using the shortest
11242 * form. Used for toPrecision() and toFixed().
11243 */
11244#define DUK_N2S_FLAG_FIXED_FORMAT (1U << 0)
11245
11246/* Force exponential format. Used for toExponential(). */
11247#define DUK_N2S_FLAG_FORCE_EXP (1U << 1)
11249/* If number would need zero padding (for whole number part), use
11250 * exponential format instead. E.g. if input number is 12300, 3
11251 * digits are generated ("123"), output "1.23e+4" instead of "12300".
11252 * Used for toPrecision().
11253 */
11254#define DUK_N2S_FLAG_NO_ZERO_PAD (1U << 2)
11255
11256/* Digit count indicates number of fractions (i.e. an absolute
11257 * digit index instead of a relative one). Used together with
11258 * DUK_N2S_FLAG_FIXED_FORMAT for toFixed().
11259 */
11260#define DUK_N2S_FLAG_FRACTION_DIGITS (1U << 3)
11261
11263 * String-to-number conversion
11264 */
11266/* Maximum exponent value when parsing numbers. This is not strictly
11267 * compliant as there should be no upper limit, but as we parse the
11268 * exponent without a bigint, impose some limit. The limit should be
11269 * small enough that multiplying it (or limit-1 to be precise) won't
11270 * overflow signed 32-bit integer range. Exponent is only parsed with
11271 * radix 10, but with maximum radix (36) a safe limit is:
11272 * (10000000*36).toString(16) -> '15752a00'
11273 */
11274#define DUK_S2N_MAX_EXPONENT 10000000L
11275
11276/* Trim white space (= allow leading and trailing whitespace) */
11277#define DUK_S2N_FLAG_TRIM_WHITE (1U << 0)
11278
11279/* Allow exponent */
11280#define DUK_S2N_FLAG_ALLOW_EXP (1U << 1)
11281
11282/* Allow trailing garbage (e.g. treat "123foo" as "123) */
11283#define DUK_S2N_FLAG_ALLOW_GARBAGE (1U << 2)
11284
11285/* Allow leading plus sign */
11286#define DUK_S2N_FLAG_ALLOW_PLUS (1U << 3)
11287
11288/* Allow leading minus sign */
11289#define DUK_S2N_FLAG_ALLOW_MINUS (1U << 4)
11290
11291/* Allow 'Infinity' */
11292#define DUK_S2N_FLAG_ALLOW_INF (1U << 5)
11293
11294/* Allow fraction part */
11295#define DUK_S2N_FLAG_ALLOW_FRAC (1U << 6)
11296
11297/* Allow naked fraction (e.g. ".123") */
11298#define DUK_S2N_FLAG_ALLOW_NAKED_FRAC (1U << 7)
11299
11300/* Allow empty fraction (e.g. "123.") */
11301#define DUK_S2N_FLAG_ALLOW_EMPTY_FRAC (1U << 8)
11302
11303/* Allow empty string to be interpreted as 0 */
11304#define DUK_S2N_FLAG_ALLOW_EMPTY_AS_ZERO (1U << 9)
11306/* Allow leading zeroes (e.g. "0123" -> "123") */
11307#define DUK_S2N_FLAG_ALLOW_LEADING_ZERO (1U << 10)
11308
11309/* Allow automatic detection of hex base ("0x" or "0X" prefix),
11310 * overrides radix argument and forces integer mode.
11311 */
11312#define DUK_S2N_FLAG_ALLOW_AUTO_HEX_INT (1U << 11)
11313
11314/* Allow automatic detection of legacy octal base ("0n"),
11315 * overrides radix argument and forces integer mode.
11316 */
11317#define DUK_S2N_FLAG_ALLOW_AUTO_LEGACY_OCT_INT (1U << 12)
11318
11319/* Allow automatic detection of ES2015 octal base ("0o123"),
11320 * overrides radix argument and forces integer mode.
11321 */
11322#define DUK_S2N_FLAG_ALLOW_AUTO_OCT_INT (1U << 13)
11323
11324/* Allow automatic detection of ES2015 binary base ("0b10001"),
11325 * overrides radix argument and forces integer mode.
11326 */
11327#define DUK_S2N_FLAG_ALLOW_AUTO_BIN_INT (1U << 14)
11328
11329/*
11330 * Prototypes
11331 */
11332
11334 duk_small_int_t radix,
11336 duk_small_uint_t flags);
11338
11339#endif /* DUK_NUMCONV_H_INCLUDED */
11340/* #include duk_bi_protos.h */
11341/*
11342 * Prototypes for built-in functions not automatically covered by the
11343 * header declarations emitted by genbuiltins.py.
11344 */
11345
11346#if !defined(DUK_BUILTIN_PROTOS_H_INCLUDED)
11347#define DUK_BUILTIN_PROTOS_H_INCLUDED
11348
11349/* Buffer size needed for ISO 8601 formatting.
11350 * Accurate value is 32 + 1 for NUL termination:
11351 * >>> len('+123456-01-23T12:34:56.123+12:34')
11352 * 32
11353 * Include additional space to be safe.
11354 */
11355#define DUK_BI_DATE_ISO8601_BUFSIZE 40
11356
11357/* Helpers exposed for internal use */
11364/* Built-in providers */
11365#if defined(DUK_USE_DATE_NOW_GETTIMEOFDAY)
11366DUK_INTERNAL_DECL duk_double_t duk_bi_date_get_now_gettimeofday(void);
11367#endif
11368#if defined(DUK_USE_DATE_NOW_TIME)
11370#endif
11371#if defined(DUK_USE_DATE_NOW_WINDOWS)
11372DUK_INTERNAL_DECL duk_double_t duk_bi_date_get_now_windows(void);
11373#endif
11374#if defined(DUK_USE_DATE_NOW_WINDOWS_SUBMS)
11375DUK_INTERNAL_DECL duk_double_t duk_bi_date_get_now_windows_subms(void);
11376#endif
11377#if defined(DUK_USE_DATE_TZO_GMTIME_R) || defined(DUK_USE_DATE_TZO_GMTIME_S) || defined(DUK_USE_DATE_TZO_GMTIME)
11379#endif
11380#if defined(DUK_USE_DATE_TZO_WINDOWS)
11381DUK_INTERNAL_DECL duk_int_t duk_bi_date_get_local_tzoffset_windows(duk_double_t d);
11382#endif
11383#if defined(DUK_USE_DATE_TZO_WINDOWS_NO_DST)
11384DUK_INTERNAL_DECL duk_int_t duk_bi_date_get_local_tzoffset_windows_no_dst(duk_double_t d);
11385#endif
11386#if defined(DUK_USE_DATE_PRS_STRPTIME)
11387DUK_INTERNAL_DECL duk_bool_t duk_bi_date_parse_string_strptime(duk_hthread *thr, const char *str);
11388#endif
11389#if defined(DUK_USE_DATE_PRS_GETDATE)
11390DUK_INTERNAL_DECL duk_bool_t duk_bi_date_parse_string_getdate(duk_hthread *thr, const char *str);
11391#endif
11392#if defined(DUK_USE_DATE_FMT_STRFTIME)
11393DUK_INTERNAL_DECL duk_bool_t duk_bi_date_format_parts_strftime(duk_hthread *thr,
11394 duk_int_t *parts,
11395 duk_int_t tzoffset,
11396 duk_small_uint_t flags);
11397#endif
11398
11399#if defined(DUK_USE_GET_MONOTONIC_TIME_CLOCK_GETTIME)
11400DUK_INTERNAL_DECL duk_double_t duk_bi_date_get_monotonic_time_clock_gettime(void);
11401#endif
11402#if defined(DUK_USE_GET_MONOTONIC_TIME_WINDOWS_QPC)
11403DUK_INTERNAL_DECL duk_double_t duk_bi_date_get_monotonic_time_windows_qpc(void);
11404#endif
11405
11407void duk_bi_json_parse_helper(duk_hthread *thr, duk_idx_t idx_value, duk_idx_t idx_reviver, duk_small_uint_t flags);
11410 duk_idx_t idx_value,
11411 duk_idx_t idx_replacer,
11412 duk_idx_t idx_space,
11413 duk_small_uint_t flags);
11414
11417#if defined(DUK_USE_ES6_PROXY)
11419#endif
11420
11421#endif /* DUK_BUILTIN_PROTOS_H_INCLUDED */
11422/* #include duk_selftest.h */
11423/*
11424 * Selftest code
11425 */
11426
11427#if !defined(DUK_SELFTEST_H_INCLUDED)
11428#define DUK_SELFTEST_H_INCLUDED
11429
11430#if defined(DUK_USE_SELF_TESTS)
11431DUK_INTERNAL_DECL duk_uint_t duk_selftest_run_tests(duk_alloc_function alloc_func,
11432 duk_realloc_function realloc_func,
11433 duk_free_function free_func,
11434 void *udata);
11435#endif
11436
11437#endif /* DUK_SELFTEST_H_INCLUDED */
11439#endif /* DUK_INTERNAL_H_INCLUDED */
11440
11441#if defined(DUK_USE_COMPUTED_NAN)
11442DUK_INTERNAL double duk_computed_nan;
11443#endif
11444
11445#if defined(DUK_USE_COMPUTED_INFINITY)
11446DUK_INTERNAL double duk_computed_infinity;
11447#endif
11448
11449#if defined(DUK_USE_REPL_FPCLASSIFY)
11450DUK_INTERNAL int duk_repl_fpclassify(double x) {
11452 duk_uint_fast16_t expt;
11453 duk_small_int_t mzero;
11454
11455 u.d = x;
11456 expt = (duk_uint_fast16_t) (u.us[DUK_DBL_IDX_US0] & 0x7ff0UL);
11457 if (expt > 0x0000UL && expt < 0x7ff0UL) {
11458 /* expt values [0x001,0x7fe] = normal */
11459 return DUK_FP_NORMAL;
11460 }
11461
11462 mzero = (u.ui[DUK_DBL_IDX_UI1] == 0 && (u.ui[DUK_DBL_IDX_UI0] & 0x000fffffUL) == 0);
11463 if (expt == 0x0000UL) {
11464 /* expt 0x000 is zero/subnormal */
11465 if (mzero) {
11466 return DUK_FP_ZERO;
11467 } else {
11468 return DUK_FP_SUBNORMAL;
11469 }
11470 } else {
11471 /* expt 0xfff is infinite/nan */
11472 if (mzero) {
11473 return DUK_FP_INFINITE;
11474 } else {
11475 return DUK_FP_NAN;
11476 }
11477 }
11479#endif
11480
11481#if defined(DUK_USE_REPL_SIGNBIT)
11482DUK_INTERNAL int duk_repl_signbit(double x) {
11484 u.d = x;
11485 return (int) (u.uc[DUK_DBL_IDX_UC0] & 0x80UL);
11486}
11487#endif
11488
11489#if defined(DUK_USE_REPL_ISFINITE)
11490DUK_INTERNAL int duk_repl_isfinite(double x) {
11491 int c = DUK_FPCLASSIFY(x);
11492 if (c == DUK_FP_NAN || c == DUK_FP_INFINITE) {
11493 return 0;
11494 } else {
11495 return 1;
11497}
11498#endif
11499
11500#if defined(DUK_USE_REPL_ISNAN)
11501DUK_INTERNAL int duk_repl_isnan(double x) {
11502 int c = DUK_FPCLASSIFY(x);
11503 return (c == DUK_FP_NAN);
11504}
11505#endif
11506
11507#if defined(DUK_USE_REPL_ISINF)
11508DUK_INTERNAL int duk_repl_isinf(double x) {
11509 int c = DUK_FPCLASSIFY(x);
11510 return (c == DUK_FP_INFINITE);
11511}
11512#endif
11513/*
11514 * Debugging macro calls.
11515 */
11516
11517/* #include duk_internal.h -> already included */
11518
11519#if defined(DUK_USE_DEBUG)
11520
11521/*
11522 * Debugging enabled
11523 */
11524
11525#include <stdio.h>
11526#include <stdlib.h>
11527#include <stdarg.h>
11528
11529#if !defined(DUK_USE_DEBUG_WRITE)
11530#error debugging enabled (DUK_USE_DEBUG) but DUK_USE_DEBUG_WRITE not defined
11531#endif
11532
11533#define DUK__DEBUG_BUFSIZE DUK_USE_DEBUG_BUFSIZE
11534
11535#if defined(DUK_USE_VARIADIC_MACROS)
11536
11537DUK_INTERNAL void duk_debug_log(duk_int_t level, const char *file, duk_int_t line, const char *func, const char *fmt, ...) {
11538 va_list ap;
11539 long arg_level;
11540 const char *arg_file;
11541 long arg_line;
11542 const char *arg_func;
11543 const char *arg_msg;
11544 char buf[DUK__DEBUG_BUFSIZE];
11545
11546 va_start(ap, fmt);
11547
11548 duk_memzero((void *) buf, (size_t) DUK__DEBUG_BUFSIZE);
11549 duk_debug_vsnprintf(buf, DUK__DEBUG_BUFSIZE - 1, fmt, ap);
11550
11551 arg_level = (long) level;
11552 arg_file = (const char *) file;
11553 arg_line = (long) line;
11554 arg_func = (const char *) func;
11555 arg_msg = (const char *) buf;
11556 DUK_USE_DEBUG_WRITE(arg_level, arg_file, arg_line, arg_func, arg_msg);
11557
11558 va_end(ap);
11559}
11560
11561#else /* DUK_USE_VARIADIC_MACROS */
11562
11563DUK_INTERNAL char duk_debug_file_stash[DUK_DEBUG_STASH_SIZE];
11564DUK_INTERNAL duk_int_t duk_debug_line_stash;
11565DUK_INTERNAL char duk_debug_func_stash[DUK_DEBUG_STASH_SIZE];
11566DUK_INTERNAL duk_int_t duk_debug_level_stash;
11567
11568DUK_INTERNAL void duk_debug_log(const char *fmt, ...) {
11569 va_list ap;
11570 long arg_level;
11571 const char *arg_file;
11572 long arg_line;
11573 const char *arg_func;
11574 const char *arg_msg;
11575 char buf[DUK__DEBUG_BUFSIZE];
11576
11577 va_start(ap, fmt);
11578
11579 duk_memzero((void *) buf, (size_t) DUK__DEBUG_BUFSIZE);
11580 duk_debug_vsnprintf(buf, DUK__DEBUG_BUFSIZE - 1, fmt, ap);
11581
11582 arg_level = (long) duk_debug_level_stash;
11583 arg_file = (const char *) duk_debug_file_stash;
11584 arg_line = (long) duk_debug_line_stash;
11585 arg_func = (const char *) duk_debug_func_stash;
11586 arg_msg = (const char *) buf;
11587 DUK_USE_DEBUG_WRITE(arg_level, arg_file, arg_line, arg_func, arg_msg);
11588
11589 va_end(ap);
11590}
11591
11592#endif /* DUK_USE_VARIADIC_MACROS */
11593
11594#else /* DUK_USE_DEBUG */
11595
11596/*
11597 * Debugging disabled
11598 */
11599
11600#endif /* DUK_USE_DEBUG */
11602/* automatic undefs */
11603#undef DUK__DEBUG_BUFSIZE
11604/*
11605 * Automatically generated by genbuiltins.py, do not edit!
11606 */
11608/* #include duk_internal.h -> already included */
11609
11610#if defined(DUK_USE_ASSERTIONS)
11611#define DUK__REFCINIT(refc) 0 /*h_assert_refcount*/, (refc) /*actual*/
11612#else
11613#define DUK__REFCINIT(refc) (refc) /*actual*/
11614#endif
11615
11616#if defined(DUK_USE_ROM_STRINGS)
11617#error ROM support not enabled, rerun configure.py with --rom-support
11618#else /* DUK_USE_ROM_STRINGS */
11619DUK_INTERNAL const duk_uint8_t duk_strings_data[972] = {
1162079,40,209,144,168,105,6,78,54,139,89,185,44,48,46,90,120,8,154,140,35,103,
1162135,113,193,73,5,52,112,180,104,166,135,52,188,4,98,12,27,146,156,80,211,31,
11622129,115,150,64,52,220,109,24,18,68,156,24,38,67,114,36,55,9,119,151,132,
11623140,93,18,113,128,153,201,212,201,205,2,248,8,196,24,224,104,82,146,40,224,
11624193,48,114,168,37,147,196,54,123,28,4,98,12,43,148,67,103,177,192,70,32,
11625196,121,68,54,123,28,18,192,199,144,124,4,98,12,43,136,108,244,117,184,8,
11626196,24,95,40,134,207,71,91,128,140,65,133,113,13,158,158,151,1,24,131,11,
11627229,16,217,233,233,112,17,136,48,206,21,110,4,244,244,184,8,196,24,103,10,
11628183,2,122,218,156,4,98,12,24,203,112,64,179,113,193,79,8,218,155,131,32,
11629184,70,212,220,13,10,82,68,252,123,144,217,146,38,228,207,18,0,100,37,64,
11630178,212,11,161,17,104,162,96,10,200,193,57,165,65,169,16,5,100,81,27,70,18,
1163132,10,200,68,185,13,116,221,197,184,64,89,57,41,197,13,49,234,5,208,156,
11632113,87,55,118,147,20,187,56,161,166,92,221,212,73,210,236,226,134,153,115,
11633119,76,201,203,179,138,26,99,73,212,136,136,164,25,174,137,56,32,72,137,
11634101,23,52,45,13,34,86,9,79,136,104,201,114,149,96,52,138,134,140,151,75,
11635226,233,186,120,121,22,39,54,83,141,5,55,68,236,36,164,3,16,225,115,150,64,
1163652,205,163,2,72,154,83,138,26,99,75,12,11,150,103,5,36,20,211,70,140,133,
1163767,72,49,241,160,227,81,196,52,168,106,39,132,252,183,136,105,80,212,79,2,
11638249,110,128,126,88,95,133,109,237,237,237,151,235,127,46,249,119,203,190,
11639186,206,33,181,2,208,61,190,12,19,34,65,19,81,132,108,228,97,1,107,33,12,
1164032,45,100,137,64,247,175,9,19,155,41,198,130,155,134,69,146,100,227,226,
11641231,146,51,192,204,73,140,224,145,221,102,241,68,196,169,248,30,75,12,11,
11642151,242,233,187,143,138,24,137,162,164,255,253,63,3,201,97,129,114,254,92,
11643112,75,136,108,166,6,136,159,255,167,224,121,44,48,46,95,203,166,238,74,
11644113,67,77,201,128,223,255,223,224,121,44,48,46,95,203,145,46,9,205,16,39,
11645201,62,36,0,192,21,147,255,238,145,39,199,197,211,116,240,242,113,197,78,
11646214,211,226,233,187,107,105,19,119,37,56,161,166,52,221,212,201,205,36,240,
11647242,16,96,152,12,26,20,164,137,150,70,154,103,28,137,50,202,96,18,132,241,
1164841,104,105,56,218,48,36,138,183,57,56,128,68,24,38,2,52,12,34,10,133,147,
11649141,3,8,119,185,13,153,34,125,206,76,17,49,38,93,206,52,151,154,119,56,28,
1165076,130,112,200,141,206,21,209,96,23,35,238,114,160,139,0,243,238,114,78,
11651164,68,68,110,113,226,210,90,26,66,110,113,128,121,247,57,80,68,141,170,
11652183,56,84,52,11,70,73,19,110,114,160,93,8,113,57,143,66,200,84,53,244,154,
1165373,24,240,81,32,38,68,18,49,228,207,23,88,100,109,70,114,92,193,4,137,173,
11654168,36,220,73,19,247,247,182,168,209,144,187,223,58,156,104,79,190,183,127,
11655123,105,160,110,247,206,167,26,19,239,173,223,222,218,67,75,189,243,169,
11656198,132,251,235,183,247,182,154,134,151,123,231,83,141,9,247,215,111,239,
11657109,22,141,22,247,206,167,26,19,239,172,223,218,45,26,47,157,78,52,39,223,
1165874,24,144,10,32,129,34,20,64,152,142,129,57,179,67,104,68,12,129,161,140,
1165972,156,100,40,40,185,152,100,89,38,65,13,196,34,228,67,149,13,2,215,129,
11660149,209,65,104,209,77,14,104,144,81,33,170,67,101,48,52,68,113,70,210,88,
11661209,36,233,22,154,86,68,196,114,76,232,145,102,120,186,195,156,112,105,225,
11662228,113,71,80,68,162,115,101,50,85,200,25,108,116,44,132,178,38,114,137,96,
11663148,136,70,209,134,37,222,232,204,228,188,200,209,200,200,99,221,25,150,84,
11664121,34,70,209,107,36,227,66,20,160,92,136,164,49,235,35,8,217,201,40,108,
11665201,18,128,68,26,201,51,188,2,80,12,67,190,40,168,38,68,190,46,153,5,50,12,
11666207,160,86,129,26,83,4,208,34,225,4,88,192,
11667};
11668#endif /* DUK_USE_ROM_STRINGS */
11669
11670#if defined(DUK_USE_ROM_OBJECTS)
11671#error ROM support not enabled, rerun configure.py with --rom-support
11672#else /* DUK_USE_ROM_OBJECTS */
11673/* native functions: 185 */
11675 NULL,
11860};
11861#if defined(DUK_USE_DOUBLE_LE)
11862DUK_INTERNAL const duk_uint8_t duk_builtins_data[4281] = {
11863144,148,105,226,32,68,52,228,254,12,104,202,37,132,52,167,194,138,105,245,
11864124,57,28,211,57,18,64,52,239,126,44,138,111,175,241,164,19,87,145,30,33,
11865167,22,145,159,8,211,139,9,225,42,5,240,145,139,163,163,8,211,139,10,228,
1186664,211,19,132,140,93,29,56,70,156,88,119,34,66,146,36,104,137,194,70,46,
11867142,172,35,78,44,47,146,195,102,11,240,145,139,163,175,8,211,139,9,228,240,
11868242,112,145,139,163,179,8,211,139,8,237,34,130,118,49,116,118,225,26,48,0,
118691,98,29,201,158,46,183,39,135,147,132,140,93,16,132,76,66,33,8,66,16,132,
1187033,8,66,26,180,105,97,167,68,150,34,33,154,112,0,1,91,247,35,79,111,237,
11871198,174,232,47,31,23,95,17,13,31,249,96,211,49,50,53,214,77,141,24,0,0,181,
1187210,228,240,242,15,128,140,65,128,134,188,0,0,90,167,97,181,224,0,2,213,62,
1187353,224,0,2,213,66,237,120,0,0,181,81,204,107,192,0,5,170,150,67,94,0,0,45,
1187484,245,90,240,0,1,106,169,162,215,128,0,11,85,93,150,188,0,0,90,171,111,53,
11875109,22,162,26,48,0,1,84,23,201,146,243,225,26,39,12,145,136,104,192,0,5,61,
1187611,228,201,121,240,100,19,134,72,196,33,195,14,40,203,112,64,190,76,232,
11877145,153,136,0,0,0,0,0,0,31,15,249,152,0,0,0,0,0,0,30,15,249,120,144,13,96,
11878155,194,56,80,206,36,67,141,20,228,70,57,81,206,100,131,156,39,132,168,23,
11879194,70,46,137,208,21,200,129,166,39,9,24,186,39,72,119,34,66,146,36,104,
11880137,194,70,46,137,212,23,201,97,179,5,248,72,197,209,58,194,121,60,60,156,
1188136,98,232,157,129,29,164,80,78,198,46,137,218,146,121,25,71,146,9,209,5,
11882209,61,48,126,14,138,152,30,67,186,23,143,139,175,131,202,135,228,72,85,
11883144,83,60,179,30,94,209,233,102,30,98,105,230,103,30,114,121,231,104,30,
11884122,137,231,233,30,130,153,232,106,30,138,169,232,235,30,144,67,193,25,19,
11885136,108,207,30,41,224,140,137,194,173,192,153,228,5,242,100,188,248,70,137,
11886195,36,79,78,47,147,37,231,193,144,78,25,34,122,145,111,36,74,232,176,13,
1188717,61,234,226,93,207,148,160,84,75,141,7,27,161,32,33,18,225,80,212,76,154,
118882,2,70,65,56,100,237,34,140,209,2,67,32,156,50,118,145,64,186,230,61,205,
1188935,103,155,32,36,141,19,134,78,210,40,206,16,36,70,137,195,39,105,20,11,
11890174,99,220,210,54,121,210,1,137,33,1,228,207,16,17,70,146,66,3,201,164,32,
118910,65,112,152,56,196,159,31,23,77,211,195,201,199,23,160,72,214,246,81,6,12,
1189273,241,214,111,31,23,60,145,158,56,50,72,81,67,230,232,242,80,19,49,39,199,
1189389,188,124,92,242,70,120,227,64,194,75,154,72,12,9,73,6,111,21,120,12,40,
11894144,19,39,25,0,225,144,168,105,56,248,185,228,140,241,200,96,64,100,42,26,
1189578,62,46,121,35,52,18,92,116,1,36,64,47,158,64,49,98,66,100,156,242,65,23,
11896196,149,35,103,194,94,100,108,144,230,203,156,64,66,37,201,16,11,32,249,
11897132,4,34,92,44,93,146,55,152,72,24,137,112,151,153,27,36,5,100,229,144,8,
11898162,98,92,210,5,76,73,241,214,111,31,23,60,145,158,57,44,48,46,92,185,164,
11899160,72,151,41,0,50,107,179,244,59,36,93,127,92,6,19,172,3,11,216,0,56,224,
11900151,29,102,241,241,115,201,25,227,164,64,106,37,199,197,211,116,240,242,
11901113,197,233,144,40,248,185,228,140,241,196,75,132,109,24,72,128,43,39,84,
11902129,13,173,161,144,168,105,56,98,78,100,142,214,215,69,1,13,173,161,144,
11903168,105,57,34,78,100,142,214,215,69,16,67,107,105,110,114,168,254,24,147,
11904153,35,181,181,212,32,67,107,105,110,114,168,254,72,147,153,35,181,181,212,
1190536,65,130,3,144,8,26,252,200,13,30,85,16,16,64,90,242,231,192,64,161,163,
11906203,31,26,172,193,17,4,23,105,159,96,27,172,251,16,32,196,4,14,137,112,17,
11907136,48,164,28,134,80,215,202,1,132,130,8,12,39,52,64,155,31,24,56,36,1,189,
11908207,132,0,35,233,35,195,62,3,196,149,36,100,72,160,2,200,232,44,227,0,11,
1190937,160,68,142,128,36,157,25,200,32,26,79,90,4,73,43,192,122,54,71,65,103,
1191044,248,14,134,140,151,227,138,231,208,45,96,148,248,134,140,151,227,138,
11911231,240,1,255,254,10,74,146,56,128,104,4,147,152,72,6,144,28,174,143,8,1,
1191230,1,165,3,96,31,0,211,3,21,11,153,35,0,211,131,68,131,160,137,16,250,5,
11913196,131,160,137,200,160,199,156,67,248,0,255,255,65,140,10,48,177,115,56,
1191435,130,60,19,134,79,89,240,52,177,115,56,39,12,156,123,144,217,251,15,135,
1191534,167,30,20,170,154,255,232,12,47,244,0,97,28,17,224,39,238,32,40,71,4,
11916120,39,12,156,4,253,228,5,137,195,39,30,228,54,124,4,253,228,128,194,115,
1191768,9,252,15,128,232,104,201,126,56,191,35,64,90,193,41,241,13,25,47,199,23,
11918228,105,3,86,225,1,100,224,156,199,130,36,249,144,10,192,76,71,250,16,15,
1191918,61,96,17,62,200,3,72,128,136,143,247,32,22,75,64,137,248,64,22,79,90,39,
11920249,64,38,84,12,167,20,52,223,196,2,230,238,45,214,36,120,32,72,158,208,4,
11921102,238,45,194,2,201,197,186,196,143,4,9,19,218,0,92,221,202,61,228,143,4,
119229,19,218,8,35,55,113,110,16,22,78,81,239,36,120,32,72,158,208,64,73,197,12,
11923255,0,13,18,60,128,159,212,128,169,76,17,156,185,100,76,255,163,64,65,26,
1192457,114,200,153,255,70,144,33,13,18,232,50,75,226,104,6,149,3,41,199,246,
11925130,12,128,28,142,156,120,203,175,158,8,194,207,1,6,81,20,79,88,11,237,84,
1192611,161,32,127,255,255,255,255,255,247,191,137,235,16,221,170,129,116,36,0,
1192716,0,0,0,0,0,0,12,196,0,0,0,0,0,0,15,135,242,61,123,164,137,162,164,218,67,
1192874,134,162,120,128,0,0,0,0,0,1,224,254,71,173,33,129,52,84,155,72,105,80,
11929212,79,16,0,0,0,0,0,0,60,63,195,244,143,146,22,230,192,0,0,0,0,0,0,176,60,
1193033,214,2,251,82,1,73,180,134,204,134,36,96,127,255,255,255,255,255,159,161,
11931144,235,16,221,169,0,164,218,67,102,67,18,48,63,255,255,255,255,255,207,
11932240,196,60,17,145,56,134,204,241,226,158,8,200,156,42,220,9,158,65,196,34,
1193392,42,26,137,147,120,64,74,37,196,54,100,49,35,188,36,5,68,184,208,113,187,
11934194,80,212,75,146,1,73,196,54,100,49,35,188,38,57,37,56,240,0,0,0,0,0,0,0,
119350,32,235,248,68,48,156,2,24,94,24,0,243,119,10,139,144,123,242,3,102,238,
1193618,239,115,72,217,160,11,223,16,23,55,113,241,32,145,36,57,188,18,16,102,3,
119375,120,35,34,89,32,15,180,152,173,127,0,218,235,88,0,228,180,227,200,0,0,0,
119380,0,0,248,127,197,107,240,64,6,77,220,24,38,78,74,113,67,77,130,4,12,155,
11939185,52,48,156,148,226,134,155,4,10,194,96,129,132,166,238,45,194,2,201,193,
11940130,100,228,167,20,52,216,32,113,41,187,139,112,128,178,114,104,97,57,41,
11941197,13,54,8,32,48,216,32,130,195,224,130,19,97,124,134,23,6,0,57,137,62,77,
1194212,38,12,0,179,18,124,45,22,190,96,128,141,176,134,28,98,79,180,152,139,
11943218,45,124,193,1,27,97,16,32,196,159,24,230,204,246,194,40,89,137,62,210,
1194498,103,92,217,158,216,70,7,49,39,193,130,100,182,17,194,140,73,246,147,16,
11945250,9,146,216,72,6,49,39,193,131,22,194,72,73,137,62,210,98,31,65,139,97,
1194640,32,196,159,14,234,70,86,194,88,89,137,62,210,98,63,93,72,202,216,76,10,
1194749,39,198,33,180,153,37,108,38,134,152,147,237,38,38,117,13,164,201,43,97,
1194856,40,196,159,36,65,57,163,149,176,158,26,98,79,180,152,165,210,9,205,28,
11949173,133,0,243,18,124,98,22,180,72,130,115,71,43,97,68,72,196,159,105,49,51,
11950168,90,209,34,9,205,28,173,133,33,19,18,124,154,24,76,185,164,227,138,89,
1195118,119,0,7,145,39,201,161,132,188,64,124,137,62,49,11,90,36,65,57,163,149,
11952210,166,37,34,79,180,152,153,212,45,104,145,4,230,142,87,74,160,84,137,62,
1195372,130,115,71,43,171,234,134,200,147,237,38,41,116,130,115,71,43,171,235,5,
1195472,147,227,16,218,76,146,186,254,184,108,137,62,210,98,103,80,218,76,146,
11955186,254,192,68,137,62,29,212,140,174,207,178,23,34,79,180,152,143,215,82,
1195650,187,62,208,60,137,62,12,19,37,210,182,21,34,79,180,152,135,208,76,151,
1195774,224,68,137,62,49,205,153,238,175,186,23,34,79,180,152,153,215,54,103,
11958186,190,240,92,137,62,22,139,95,48,64,70,235,251,225,210,36,251,73,136,189,
11959162,215,204,16,17,186,255,2,14,98,79,152,32,35,108,48,64,242,36,249,130,2,
1196055,75,6,212,224,72,200,51,128,114,108,28,100,128,0,0,0,0,0,0,0,12,110,127,
1196148,98,115,249,201,117,243,249,195,21,159,206,38,47,63,156,86,8,75,144,94,
1196282,1,38,73,79,208,67,95,233,1,6,128,14,79,129,186,40,249,18,149,182,207,
11963144,200,155,188,248,204,105,184,207,142,199,137,175,201,0,159,72,10,5,21,
11964221,10,120,74,129,124,36,98,232,228,74,81,62,160,20,10,107,186,21,114,32,
11965105,137,194,70,46,142,68,165,19,235,1,64,170,187,161,119,34,66,146,36,104,
11966137,194,70,46,142,68,165,19,236,1,64,174,187,161,95,37,134,204,23,225,35,
1196723,71,34,82,137,246,128,160,89,93,208,167,147,195,201,194,70,46,142,68,165,
1196819,238,1,64,182,187,161,71,105,20,19,177,139,163,145,41,68,16,7,6,15,82,70,
1196972,115,96,0,0,0,0,0,27,234,32,91,60,165,195,201,194,8,134,149,216,162,0,
11970192,41,225,8,2,48,177,36,1,149,13,196,15,0,200,209,97,199,128,99,32,176,
11971195,192,113,57,143,0,167,133,32,230,80,28,202,139,175,238,2,48,189,192,20,
119721,119,80,87,193,186,129,89,56,72,197,209,200,193,185,35,23,71,109,13,219,
1197336,98,232,237,156,13,26,208,211,14,102,19,87,137,91,95,128,0,10,96,24,92,0,
119740,83,2,53,56,0,0,165,3,28,204,160,160,226,100,226,200,211,76,241,240,0,1,
11975102,8,22,75,64,137,73,20,230,105,133,7,19,39,22,70,154,103,143,128,0,11,48,
1197620,28,76,156,113,75,34,78,62,0,0,45,3,103,31,0,0,22,65,44,57,137,62,33,179,
11977216,162,152,192,131,18,124,162,27,61,138,41,108,32,196,159,16,217,232,235,
1197881,76,104,73,137,62,81,13,158,142,181,20,184,16,98,79,136,108,244,244,168,
11979166,56,36,196,159,40,134,207,79,74,138,93,10,49,39,194,173,192,158,158,149,
1198020,188,20,98,79,133,91,129,61,109,74,41,124,30,68,159,16,217,236,83,108,96,
1198168,137,62,81,13,158,197,54,182,17,34,79,136,108,244,117,169,182,52,38,68,
11982159,40,134,207,71,90,155,92,8,145,39,196,54,122,122,84,219,28,19,34,79,148,
1198367,103,167,165,77,174,133,72,147,225,86,224,79,79,74,155,94,10,145,39,194,
11984173,192,158,182,165,54,190,206,25,212,35,208,226,100,150,211,201,29,162,44,
11985140,35,103,0,0,0,0,0,0,3,192,252,206,25,228,35,208,226,100,150,211,201,29,
11986162,44,140,35,103,0,0,0,0,0,0,3,192,252,206,25,244,35,208,226,100,150,211,
11987201,29,162,44,140,35,103,0,0,0,0,0,0,3,192,252,206,26,4,35,208,226,100,150,
11988211,201,29,162,44,140,35,103,0,0,0,0,0,0,0,1,0,206,26,20,35,208,226,100,
11989150,211,201,29,162,44,140,35,103,0,0,0,0,0,0,0,1,0,206,26,36,35,208,226,
11990100,150,211,201,29,162,44,140,35,103,0,0,0,0,0,0,0,65,0,206,26,52,35,208,
11991226,100,150,211,201,29,162,44,140,35,103,0,0,0,0,0,0,0,65,0,206,26,68,35,
11992208,226,100,150,211,201,29,162,44,140,35,103,0,0,0,0,0,0,0,65,0,206,26,84,
1199335,208,226,100,150,211,201,29,162,44,140,35,103,0,0,0,0,0,0,0,129,0,195,
11994154,99,16,38,36,0,251,68,117,179,216,162,128,68,72,1,241,13,158,197,20,150,
1199525,18,0,125,162,58,217,232,235,117,100,162,136,25,18,0,125,162,58,217,232,
11996235,116,36,162,145,2,226,64,15,136,108,244,117,186,178,81,73,129,113,32,7,
11997196,54,122,58,221,9,40,165,64,200,144,3,237,17,214,207,79,75,171,37,20,80,
11998200,144,3,237,17,214,207,79,75,161,37,20,138,23,18,0,124,67,103,167,165,
11999213,146,138,77,11,137,0,62,33,179,211,210,232,73,69,42,133,196,128,31,10,
12000183,2,125,89,40,163,5,196,128,31,10,183,2,125,9,40,164,96,200,144,3,224,
12001221,64,172,157,89,40,163,134,68,128,31,6,234,5,100,232,73,69,35,133,68,128,
1200231,104,142,182,125,89,40,180,0,168,144,3,237,17,214,207,161,37,22,144,19,
1200318,0,124,67,103,213,146,139,80,9,137,0,62,33,179,232,73,69,172,5,90,40,153,
1200459,68,117,179,216,166,192,77,162,137,147,136,108,246,41,180,176,219,69,19,
1200539,104,142,182,122,58,221,89,41,178,6,218,40,153,59,68,117,179,209,214,232,
1200673,77,162,6,90,40,153,56,134,207,71,91,171,37,54,152,25,104,162,100,226,27,
1200761,29,110,132,148,218,160,109,162,137,147,180,71,91,61,61,46,172,148,217,
1200867,109,20,76,157,162,58,217,233,233,116,36,166,209,67,45,20,76,156,67,103,
12009167,165,213,146,155,77,12,180,81,50,113,13,158,158,151,66,74,109,84,50,209,
1201068,201,194,173,192,159,86,74,108,193,150,138,38,78,21,110,4,250,18,83,104,
12011193,182,138,38,78,13,212,10,201,213,146,155,56,109,162,137,147,131,117,2,
12012178,116,36,166,209,194,237,20,76,157,162,58,217,245,100,167,16,2,237,20,76,
12013157,162,58,217,244,36,167,18,2,173,20,76,156,67,103,213,146,156,80,10,180,
1201481,50,113,13,159,66,74,113,97,175,221,48,216,110,64,4,42,22,189,179,0,196,
12015133,0,185,80,32,28,78,99,193,18,80,36,4,19,159,141,172,0,178,90,4,74,73,0,
1201622,209,68,201,187,129,4,2,8,3,132,64,60,36,6,149,113,72,176,171,240,84,0,
12017157,91,116,116,32,11,42,218,221,216,181,129,32,3,234,219,165,3,188,231,235,
12018249,8,187,152,252,47,86,227,105,18,7,244,17,91,42,56,175,185,248,110,173,
12019198,209,208,36,0,238,82,97,87,188,189,179,240,93,122,32,12,22,162,42,125,
12020144,132,160,7,236,161,25,232,237,105,64,205,59,127,102,158,160,230,63,11,
12021217,66,51,210,129,154,118,254,205,61,65,236,127,171,197,34,168,48,6,90,194,
120221,0,39,75,88,72,8,9,33,186,194,80,64,76,13,214,19,2,130,96,110,150,189,0,
1202365,6,51,214,20,128,65,17,11,214,19,130,137,121,211,210,211,144,6,39,75,88,
1202480,0,201,119,235,10,8,41,86,231,71,88,80,129,79,135,186,122,133,224,34,25,
1202569,234,80,3,91,141,172,40,96,139,113,180,181,133,36,21,110,54,142,134,176,
12026165,1,176,23,213,47,0,216,134,234,215,128,111,117,181,232,128,209,3,70,230,
12027107,64,5,139,168,209,235,10,32,36,144,102,235,136,3,146,27,172,40,160,146,
12028132,103,172,40,192,115,3,117,133,28,22,113,163,69,172,41,103,1,66,188,17,
12029145,52,168,4,202,113,67,76,130,227,76,194,13,240,108,0,0,83,224,0,2,193,0,
12030104,146,84,97,48,0,1,94,192,56,169,24,145,179,192,0,5,112,8,56,16,32,128,
1203156,18,52,125,230,86,147,190,140,28,50,21,13,39,31,23,60,145,158,57,12,141,
1203247,129,6,155,194,188,24,49,39,199,89,188,124,92,242,70,120,224,201,33,69,
1203315,155,163,201,68,14,49,39,199,197,211,116,240,242,113,197,232,18,180,254,
1203436,3,17,46,18,243,35,100,128,172,156,178,70,163,154,76,34,248,146,164,108,
12035248,75,204,141,146,28,217,115,137,27,95,27,241,173,236,162,160,224,200,2,
12036206,9,113,13,148,192,209,18,22,164,146,37,193,57,162,4,249,39,196,128,24,2,
12037178,66,213,136,68,201,16,77,209,131,31,192,242,88,96,92,191,151,34,100,136,
1203838,232,255,252,92,221,199,197,12,68,209,82,66,212,11,155,185,41,197,13,55,
1203938,3,66,213,47,135,254,72,12,162,99,133,116,112,0,1,72,66,14,16,16,50,37,
12040202,160,150,154,66,14,20,8,57,192,28,24,80,113,50,113,100,105,166,120,248,
120410,0,179,1,65,196,201,199,20,178,36,227,224,0,2,208,54,113,240,0,1,100,11,
12042181,192,0,5,178,1,18,160,65,24,131,20,145,25,188,48,132,122,28,76,146,218,
12043121,35,180,69,145,132,108,224,0,0,0,0,0,0,120,31,153,188,56,132,122,28,76,
12044146,218,121,35,180,69,145,132,108,224,0,0,0,0,0,0,120,31,168,160,45,110,23,
1204530,176,33,184,0,0,183,32,29,235,2,27,199,23,0,0,23,4,51,120,129,8,244,56,
12046153,37,180,242,71,104,139,35,8,217,192,0,0,0,0,0,0,240,63,51,120,145,8,244,
1204756,153,37,180,242,71,104,139,35,8,217,192,0,0,0,0,0,0,0,64,51,120,161,8,
12048244,56,153,37,180,242,71,104,139,35,8,217,192,0,0,0,0,0,0,0,64,51,120,177,
120498,244,56,153,37,180,242,71,104,139,35,8,217,192,0,0,0,0,0,0,16,64,51,120,
12050193,8,244,56,153,37,180,242,71,104,139,35,8,217,192,0,0,0,0,0,0,16,64,51,
12051120,209,8,244,56,153,37,180,242,71,104,139,35,8,217,192,0,0,0,0,0,0,16,64,
1205251,120,225,8,244,56,153,37,180,242,71,104,139,35,8,217,192,0,0,0,0,0,0,32,
1205364,32,227,194,0,97,57,162,4,246,104,5,34,92,35,68,225,161,166,220,16,16,
12054137,112,52,41,73,29,185,1,65,196,201,197,145,166,153,246,72,3,137,204,120,
1205534,74,8,199,1,67,17,162,112,201,84,128,97,144,78,25,42,16,131,169,1,205,66,
120568,35,68,225,161,166,239,128,0,10,192,64,196,104,156,50,96,0,2,172,73,240,
12057117,96,57,170,97,4,104,156,52,52,221,240,0,1,82,1,74,9,129,125,240,0,1,82,
1205832,148,25,174,137,58,23,51,190,0,0,42,69,64,195,32,156,50,96,0,2,160,81,
12059238,2,3,107,173,218,3,192,
12060};
12061#elif defined(DUK_USE_DOUBLE_BE)
12062DUK_INTERNAL const duk_uint8_t duk_builtins_data[4281] = {
12063144,148,105,226,32,68,52,228,254,12,104,202,37,132,52,167,194,138,105,245,
12064124,57,28,211,57,18,64,52,239,126,44,138,111,175,241,164,19,87,145,30,33,
12065167,22,145,159,8,211,139,9,225,42,5,240,145,139,163,163,8,211,139,10,228,
1206664,211,19,132,140,93,29,56,70,156,88,119,34,66,146,36,104,137,194,70,46,
12067142,172,35,78,44,47,146,195,102,11,240,145,139,163,175,8,211,139,9,228,240,
12068242,112,145,139,163,179,8,211,139,8,237,34,130,118,49,116,118,225,26,48,0,
120691,98,29,201,158,46,183,39,135,147,132,140,93,16,132,76,66,33,8,66,16,132,
1207033,8,66,26,180,105,97,167,68,150,34,33,154,112,0,1,91,247,35,79,111,237,
12071198,174,232,47,31,23,95,17,13,31,249,96,211,49,50,53,214,77,141,24,0,0,181,
1207210,228,240,242,15,128,140,65,128,134,188,0,0,90,167,97,181,224,0,2,213,62,
1207353,224,0,2,213,66,237,120,0,0,181,81,204,107,192,0,5,170,150,67,94,0,0,45,
1207484,245,90,240,0,1,106,169,162,215,128,0,11,85,93,150,188,0,0,90,171,111,53,
12075109,22,162,26,48,0,1,84,23,201,146,243,225,26,39,12,145,136,104,192,0,5,61,
1207611,228,201,121,240,100,19,134,72,196,33,195,14,40,203,112,64,190,76,232,
12077145,153,136,15,255,0,0,0,0,0,0,25,152,15,254,0,0,0,0,0,0,25,120,144,13,96,
12078155,194,56,80,206,36,67,141,20,228,70,57,81,206,100,131,156,39,132,168,23,
12079194,70,46,137,208,21,200,129,166,39,9,24,186,39,72,119,34,66,146,36,104,
12080137,194,70,46,137,212,23,201,97,179,5,248,72,197,209,58,194,121,60,60,156,
1208136,98,232,157,129,29,164,80,78,198,46,137,218,146,121,25,71,146,9,209,5,
12082209,61,48,126,14,138,152,30,67,186,23,143,139,175,131,202,135,228,72,85,
12083144,83,60,179,30,94,209,233,102,30,98,105,230,103,30,114,121,231,104,30,
12084122,137,231,233,30,130,153,232,106,30,138,169,232,235,30,144,67,193,25,19,
12085136,108,207,30,41,224,140,137,194,173,192,153,228,5,242,100,188,248,70,137,
12086195,36,79,78,47,147,37,231,193,144,78,25,34,122,145,111,36,74,232,176,13,
1208717,61,234,226,93,207,148,160,84,75,141,7,27,161,32,33,18,225,80,212,76,154,
120882,2,70,65,56,100,237,34,140,209,2,67,32,156,50,118,145,64,186,230,61,205,
1208935,103,155,32,36,141,19,134,78,210,40,206,16,36,70,137,195,39,105,20,11,
12090174,99,220,210,54,121,210,1,137,33,1,228,207,16,17,70,146,66,3,201,164,32,
120910,65,112,152,56,196,159,31,23,77,211,195,201,199,23,160,72,214,246,81,6,12,
1209273,241,214,111,31,23,60,145,158,56,50,72,81,67,230,232,242,80,19,49,39,199,
1209389,188,124,92,242,70,120,227,64,194,75,154,72,12,9,73,6,111,21,120,12,40,
12094144,19,39,25,0,225,144,168,105,56,248,185,228,140,241,200,96,64,100,42,26,
1209578,62,46,121,35,52,18,92,116,1,36,64,47,158,64,49,98,66,100,156,242,65,23,
12096196,149,35,103,194,94,100,108,144,230,203,156,64,66,37,201,16,11,32,249,
12097132,4,34,92,44,93,146,55,152,72,24,137,112,151,153,27,36,5,100,229,144,8,
12098162,98,92,210,5,76,73,241,214,111,31,23,60,145,158,57,44,48,46,92,185,164,
12099160,72,151,41,0,50,107,179,244,59,36,93,127,92,6,19,172,3,11,216,0,56,224,
12100151,29,102,241,241,115,201,25,227,164,64,106,37,199,197,211,116,240,242,
12101113,197,233,144,40,248,185,228,140,241,196,75,132,109,24,72,128,43,39,84,
12102129,13,173,161,144,168,105,56,98,78,100,142,214,215,69,1,13,173,161,144,
12103168,105,57,34,78,100,142,214,215,69,16,67,107,105,110,114,168,254,24,147,
12104153,35,181,181,212,32,67,107,105,110,114,168,254,72,147,153,35,181,181,212,
1210536,65,130,3,144,8,26,252,200,13,30,85,16,16,64,90,242,231,192,64,161,163,
12106203,31,26,172,193,17,4,23,105,159,96,27,172,251,16,32,196,4,14,137,112,17,
12107136,48,164,28,134,80,215,202,1,132,130,8,12,39,52,64,155,31,24,56,36,1,189,
12108207,132,0,35,233,35,195,62,3,196,149,36,100,72,160,2,200,232,44,227,0,11,
1210937,160,68,142,128,36,157,25,200,32,26,79,90,4,73,43,192,122,54,71,65,103,
1211044,248,14,134,140,151,227,138,231,208,45,96,148,248,134,140,151,227,138,
12111231,240,1,255,254,10,74,146,56,128,104,4,147,152,72,6,144,28,174,143,8,1,
1211230,1,165,3,96,31,0,211,3,21,11,153,35,0,211,131,68,131,160,137,16,250,5,
12113196,131,160,137,200,160,199,156,67,248,0,255,255,65,140,10,48,177,115,56,
1211435,130,60,19,134,79,89,240,52,177,115,56,39,12,156,123,144,217,251,15,135,
1211534,167,30,20,170,154,255,232,12,47,244,0,97,28,17,224,39,238,32,40,71,4,
12116120,39,12,156,4,253,228,5,137,195,39,30,228,54,124,4,253,228,128,194,115,
1211768,9,252,15,128,232,104,201,126,56,191,35,64,90,193,41,241,13,25,47,199,23,
12118228,105,3,86,225,1,100,224,156,199,130,36,249,144,10,192,76,71,250,16,15,
1211918,61,96,17,62,200,3,72,128,136,143,247,32,22,75,64,137,248,64,22,79,90,39,
12120249,64,38,84,12,167,20,52,223,196,2,230,238,45,214,36,120,32,72,158,208,4,
12121102,238,45,194,2,201,197,186,196,143,4,9,19,218,0,92,221,202,61,228,143,4,
121229,19,218,8,35,55,113,110,16,22,78,81,239,36,120,32,72,158,208,64,73,197,12,
12123255,0,13,18,60,128,159,212,128,169,76,17,156,185,100,76,255,163,64,65,26,
1212457,114,200,153,255,70,144,33,13,18,232,50,75,226,104,6,149,3,41,199,246,
12125130,12,128,28,142,156,120,203,175,158,8,194,207,1,6,81,20,79,88,11,237,84,
1212611,161,32,63,247,255,255,255,255,255,255,137,235,16,221,170,129,116,36,0,0,
121270,0,0,0,0,0,28,196,7,255,128,0,0,0,0,0,2,61,123,164,137,162,164,218,67,74,
12128134,162,120,128,255,224,0,0,0,0,0,0,71,173,33,129,52,84,155,72,105,80,212,
1212979,16,63,252,0,0,0,0,0,0,3,244,143,146,22,230,192,60,176,0,0,0,0,0,0,33,
12130214,2,251,82,1,73,180,134,204,134,36,96,33,159,255,255,255,255,255,255,144,
12131235,16,221,169,0,164,218,67,102,67,18,48,48,207,255,255,255,255,255,255,
12132196,60,17,145,56,134,204,241,226,158,8,200,156,42,220,9,158,65,196,34,92,
1213342,26,137,147,120,64,74,37,196,54,100,49,35,188,36,5,68,184,208,113,187,
12134194,80,212,75,146,1,73,196,54,100,49,35,188,38,57,37,56,240,0,0,0,0,0,0,0,
121350,32,235,248,68,48,156,2,24,94,24,0,243,119,10,139,144,123,242,3,102,238,
1213618,239,115,72,217,160,11,223,16,23,55,113,241,32,145,36,57,188,18,16,102,3,
121375,120,35,34,89,32,15,180,152,173,127,0,218,235,88,0,228,180,227,200,127,
12138248,0,0,0,0,0,0,197,107,240,64,6,77,220,24,38,78,74,113,67,77,130,4,12,155,
12139185,52,48,156,148,226,134,155,4,10,194,96,129,132,166,238,45,194,2,201,193,
12140130,100,228,167,20,52,216,32,113,41,187,139,112,128,178,114,104,97,57,41,
12141197,13,54,8,32,48,216,32,130,195,224,130,19,97,124,134,23,6,0,57,137,62,77,
1214212,38,12,0,179,18,124,45,22,190,96,128,141,176,134,28,98,79,180,152,139,
12143218,45,124,193,1,27,97,16,32,196,159,24,230,204,246,194,40,89,137,62,210,
1214498,103,92,217,158,216,70,7,49,39,193,130,100,182,17,194,140,73,246,147,16,
12145250,9,146,216,72,6,49,39,193,131,22,194,72,73,137,62,210,98,31,65,139,97,
1214640,32,196,159,14,234,70,86,194,88,89,137,62,210,98,63,93,72,202,216,76,10,
1214749,39,198,33,180,153,37,108,38,134,152,147,237,38,38,117,13,164,201,43,97,
1214856,40,196,159,36,65,57,163,149,176,158,26,98,79,180,152,165,210,9,205,28,
12149173,133,0,243,18,124,98,22,180,72,130,115,71,43,97,68,72,196,159,105,49,51,
12150168,90,209,34,9,205,28,173,133,33,19,18,124,154,24,76,185,164,227,138,89,
1215118,119,0,7,145,39,201,161,132,188,64,124,137,62,49,11,90,36,65,57,163,149,
12152210,166,37,34,79,180,152,153,212,45,104,145,4,230,142,87,74,160,84,137,62,
1215372,130,115,71,43,171,234,134,200,147,237,38,41,116,130,115,71,43,171,235,5,
1215472,147,227,16,218,76,146,186,254,184,108,137,62,210,98,103,80,218,76,146,
12155186,254,192,68,137,62,29,212,140,174,207,178,23,34,79,180,152,143,215,82,
1215650,187,62,208,60,137,62,12,19,37,210,182,21,34,79,180,152,135,208,76,151,
1215774,224,68,137,62,49,205,153,238,175,186,23,34,79,180,152,153,215,54,103,
12158186,190,240,92,137,62,22,139,95,48,64,70,235,251,225,210,36,251,73,136,189,
12159162,215,204,16,17,186,255,2,14,98,79,152,32,35,108,48,64,242,36,249,130,2,
1216055,75,6,212,224,72,200,51,128,114,108,28,100,128,0,0,0,0,0,0,0,12,110,127,
1216148,98,115,249,201,117,243,249,195,21,159,206,38,47,63,156,86,8,75,144,94,
1216282,1,38,73,79,208,67,95,233,1,6,128,14,79,129,186,40,249,18,149,182,207,
12163144,200,155,188,248,204,105,184,207,142,199,137,175,201,0,159,72,10,5,21,
12164221,10,120,74,129,124,36,98,232,228,74,81,62,160,20,10,107,186,21,114,32,
12165105,137,194,70,46,142,68,165,19,235,1,64,170,187,161,119,34,66,146,36,104,
12166137,194,70,46,142,68,165,19,236,1,64,174,187,161,95,37,134,204,23,225,35,
1216723,71,34,82,137,246,128,160,89,93,208,167,147,195,201,194,70,46,142,68,165,
1216819,238,1,64,182,187,161,71,105,20,19,177,139,163,145,41,68,16,7,6,15,82,70,
1216972,115,96,32,106,27,128,0,0,0,0,91,60,165,195,201,194,8,134,149,216,162,0,
12170192,41,225,8,2,48,177,36,1,149,13,196,15,0,200,209,97,199,128,99,32,176,
12171195,192,113,57,143,0,167,133,32,230,80,28,202,139,175,238,2,48,189,192,20,
121721,119,80,87,193,186,129,89,56,72,197,209,200,193,185,35,23,71,109,13,219,
1217336,98,232,237,156,13,26,208,211,14,102,19,87,137,91,95,128,0,10,96,24,92,0,
121740,83,2,53,56,0,0,165,3,28,204,160,160,226,100,226,200,211,76,241,240,0,1,
12175102,8,22,75,64,137,73,20,230,105,133,7,19,39,22,70,154,103,143,128,0,11,48,
1217620,28,76,156,113,75,34,78,62,0,0,45,3,103,31,0,0,22,65,44,57,137,62,33,179,
12177216,162,152,192,131,18,124,162,27,61,138,41,108,32,196,159,16,217,232,235,
1217881,76,104,73,137,62,81,13,158,142,181,20,184,16,98,79,136,108,244,244,168,
12179166,56,36,196,159,40,134,207,79,74,138,93,10,49,39,194,173,192,158,158,149,
1218020,188,20,98,79,133,91,129,61,109,74,41,124,30,68,159,16,217,236,83,108,96,
1218168,137,62,81,13,158,197,54,182,17,34,79,136,108,244,117,169,182,52,38,68,
12182159,40,134,207,71,90,155,92,8,145,39,196,54,122,122,84,219,28,19,34,79,148,
1218367,103,167,165,77,174,133,72,147,225,86,224,79,79,74,155,94,10,145,39,194,
12184173,192,158,182,165,54,190,206,25,212,35,208,226,100,150,211,201,29,162,44,
12185140,35,103,0,255,192,0,0,0,0,0,0,206,25,228,35,208,226,100,150,211,201,29,
12186162,44,140,35,103,0,255,192,0,0,0,0,0,0,206,25,244,35,208,226,100,150,211,
12187201,29,162,44,140,35,103,0,255,192,0,0,0,0,0,0,206,26,4,35,208,226,100,150,
12188211,201,29,162,44,140,35,103,1,0,0,0,0,0,0,0,0,206,26,20,35,208,226,100,
12189150,211,201,29,162,44,140,35,103,1,0,0,0,0,0,0,0,0,206,26,36,35,208,226,
12190100,150,211,201,29,162,44,140,35,103,1,0,64,0,0,0,0,0,0,206,26,52,35,208,
12191226,100,150,211,201,29,162,44,140,35,103,1,0,64,0,0,0,0,0,0,206,26,68,35,
12192208,226,100,150,211,201,29,162,44,140,35,103,1,0,64,0,0,0,0,0,0,206,26,84,
1219335,208,226,100,150,211,201,29,162,44,140,35,103,1,0,128,0,0,0,0,0,0,195,
12194154,99,16,38,36,0,251,68,117,179,216,162,128,68,72,1,241,13,158,197,20,150,
1219525,18,0,125,162,58,217,232,235,117,100,162,136,25,18,0,125,162,58,217,232,
12196235,116,36,162,145,2,226,64,15,136,108,244,117,186,178,81,73,129,113,32,7,
12197196,54,122,58,221,9,40,165,64,200,144,3,237,17,214,207,79,75,171,37,20,80,
12198200,144,3,237,17,214,207,79,75,161,37,20,138,23,18,0,124,67,103,167,165,
12199213,146,138,77,11,137,0,62,33,179,211,210,232,73,69,42,133,196,128,31,10,
12200183,2,125,89,40,163,5,196,128,31,10,183,2,125,9,40,164,96,200,144,3,224,
12201221,64,172,157,89,40,163,134,68,128,31,6,234,5,100,232,73,69,35,133,68,128,
1220231,104,142,182,125,89,40,180,0,168,144,3,237,17,214,207,161,37,22,144,19,
1220318,0,124,67,103,213,146,139,80,9,137,0,62,33,179,232,73,69,172,5,90,40,153,
1220459,68,117,179,216,166,192,77,162,137,147,136,108,246,41,180,176,219,69,19,
1220539,104,142,182,122,58,221,89,41,178,6,218,40,153,59,68,117,179,209,214,232,
1220673,77,162,6,90,40,153,56,134,207,71,91,171,37,54,152,25,104,162,100,226,27,
1220761,29,110,132,148,218,160,109,162,137,147,180,71,91,61,61,46,172,148,217,
1220867,109,20,76,157,162,58,217,233,233,116,36,166,209,67,45,20,76,156,67,103,
12209167,165,213,146,155,77,12,180,81,50,113,13,158,158,151,66,74,109,84,50,209,
1221068,201,194,173,192,159,86,74,108,193,150,138,38,78,21,110,4,250,18,83,104,
12211193,182,138,38,78,13,212,10,201,213,146,155,56,109,162,137,147,131,117,2,
12212178,116,36,166,209,194,237,20,76,157,162,58,217,245,100,167,16,2,237,20,76,
12213157,162,58,217,244,36,167,18,2,173,20,76,156,67,103,213,146,156,80,10,180,
1221481,50,113,13,159,66,74,113,97,175,221,48,216,110,64,4,42,22,189,179,0,196,
12215133,0,185,80,32,28,78,99,193,18,80,36,4,19,159,141,172,0,178,90,4,74,73,0,
1221622,209,68,201,187,129,4,2,8,3,132,64,60,36,4,0,91,240,168,177,69,118,144,
12217157,91,116,116,32,32,1,53,216,221,218,170,139,3,234,219,165,0,255,152,185,
1221811,251,232,231,188,47,86,227,105,18,1,255,184,170,59,41,92,23,240,110,173,
12219198,209,208,36,3,253,188,183,177,82,110,80,224,93,122,32,32,4,144,253,170,
1222034,22,140,7,236,161,25,232,237,105,64,63,230,160,158,102,127,59,205,11,217,
1222166,51,210,128,127,237,65,60,204,254,119,155,171,197,34,168,48,6,90,194,1,0,
1222239,75,88,72,8,9,33,186,194,80,64,76,13,214,19,2,130,96,110,150,189,0,65,6,
1222351,214,20,128,65,17,11,214,19,130,137,121,211,210,211,144,6,39,75,88,80,0,
12224201,119,235,10,8,41,86,231,71,88,80,129,79,135,186,122,133,224,34,25,69,
12225234,80,3,91,141,172,40,96,139,113,180,181,133,36,21,110,54,142,134,176,165,
122261,176,23,213,47,0,216,134,234,215,128,111,117,181,232,128,209,3,70,230,107,
1222764,5,139,168,209,235,10,32,36,144,102,235,136,3,146,27,172,40,160,146,132,
12228103,172,40,192,115,3,117,133,28,22,113,163,69,172,41,103,1,66,188,17,145,
1222952,168,4,202,113,67,76,130,227,76,194,13,240,108,0,0,83,224,0,2,193,0,104,
12230146,84,97,48,0,1,94,192,56,169,24,145,179,192,0,5,112,8,56,16,32,128,56,18,
1223152,125,230,86,147,190,140,28,50,21,13,39,31,23,60,145,158,57,12,141,47,129,
122326,155,194,188,24,49,39,199,89,188,124,92,242,70,120,224,201,33,69,15,155,
12233163,201,68,14,49,39,199,197,211,116,240,242,113,197,232,18,180,254,36,3,17,
1223446,18,243,35,100,128,172,156,178,70,163,154,76,34,248,146,164,108,248,75,
12235204,141,146,28,217,115,137,27,95,27,241,173,236,162,160,224,200,2,206,9,
12236113,13,148,192,209,18,22,164,146,37,193,57,162,4,249,39,196,128,24,2,178,
1223766,213,136,68,201,16,77,209,131,31,192,242,88,96,92,191,151,34,100,136,38,
12238232,255,252,92,221,199,197,12,68,209,82,66,212,11,155,185,41,197,13,55,38,
122393,66,213,47,135,254,72,12,162,99,133,116,112,0,1,72,66,14,16,16,50,37,202,
12240160,150,154,66,14,20,8,57,192,28,24,80,113,50,113,100,105,166,120,248,0,0,
12241179,1,65,196,201,199,20,178,36,227,224,0,2,208,54,113,240,0,1,100,11,181,
12242192,0,5,178,1,18,160,65,24,131,20,145,25,188,48,132,122,28,76,146,218,121,
1224335,180,69,145,132,108,224,31,248,0,0,0,0,0,0,25,188,56,132,122,28,76,146,
12244218,121,35,180,69,145,132,108,224,31,248,0,0,0,0,0,0,40,160,45,110,23,30,
12245176,33,184,0,0,183,32,29,235,2,27,199,23,0,0,23,4,51,120,129,8,244,56,153,
1224637,180,242,71,104,139,35,8,217,192,63,240,0,0,0,0,0,0,51,120,145,8,244,56,
12247153,37,180,242,71,104,139,35,8,217,192,64,0,0,0,0,0,0,0,51,120,161,8,244,
1224856,153,37,180,242,71,104,139,35,8,217,192,64,0,0,0,0,0,0,0,51,120,177,8,
12249244,56,153,37,180,242,71,104,139,35,8,217,192,64,16,0,0,0,0,0,0,51,120,193,
122508,244,56,153,37,180,242,71,104,139,35,8,217,192,64,16,0,0,0,0,0,0,51,120,
12251209,8,244,56,153,37,180,242,71,104,139,35,8,217,192,64,16,0,0,0,0,0,0,51,
12252120,225,8,244,56,153,37,180,242,71,104,139,35,8,217,192,64,32,0,0,0,0,0,0,
1225332,227,194,0,97,57,162,4,246,104,5,34,92,35,68,225,161,166,220,16,16,137,
12254112,52,41,73,29,185,1,65,196,201,197,145,166,153,246,72,3,137,204,120,34,
1225574,8,199,1,67,17,162,112,201,84,128,97,144,78,25,42,16,131,169,1,205,66,8,
1225635,68,225,161,166,239,128,0,10,192,64,196,104,156,50,96,0,2,172,73,240,117,
1225796,57,170,97,4,104,156,52,52,221,240,0,1,82,1,74,9,129,125,240,0,1,82,32,
12258148,25,174,137,58,23,51,190,0,0,42,69,64,195,32,156,50,96,0,2,160,81,238,2,
122593,107,173,218,3,192,
12260};
12261#elif defined(DUK_USE_DOUBLE_ME)
12262DUK_INTERNAL const duk_uint8_t duk_builtins_data[4281] = {
12263144,148,105,226,32,68,52,228,254,12,104,202,37,132,52,167,194,138,105,245,
12264124,57,28,211,57,18,64,52,239,126,44,138,111,175,241,164,19,87,145,30,33,
12265167,22,145,159,8,211,139,9,225,42,5,240,145,139,163,163,8,211,139,10,228,
1226664,211,19,132,140,93,29,56,70,156,88,119,34,66,146,36,104,137,194,70,46,
12267142,172,35,78,44,47,146,195,102,11,240,145,139,163,175,8,211,139,9,228,240,
12268242,112,145,139,163,179,8,211,139,8,237,34,130,118,49,116,118,225,26,48,0,
122691,98,29,201,158,46,183,39,135,147,132,140,93,16,132,76,66,33,8,66,16,132,
1227033,8,66,26,180,105,97,167,68,150,34,33,154,112,0,1,91,247,35,79,111,237,
12271198,174,232,47,31,23,95,17,13,31,249,96,211,49,50,53,214,77,141,24,0,0,181,
1227210,228,240,242,15,128,140,65,128,134,188,0,0,90,167,97,181,224,0,2,213,62,
1227353,224,0,2,213,66,237,120,0,0,181,81,204,107,192,0,5,170,150,67,94,0,0,45,
1227484,245,90,240,0,1,106,169,162,215,128,0,11,85,93,150,188,0,0,90,171,111,53,
12275109,22,162,26,48,0,1,84,23,201,146,243,225,26,39,12,145,136,104,192,0,5,61,
1227611,228,201,121,240,100,19,134,72,196,33,195,14,40,203,112,64,190,76,232,
12277145,153,136,0,0,31,15,224,0,0,0,25,152,0,0,30,15,224,0,0,0,25,120,144,13,
1227896,155,194,56,80,206,36,67,141,20,228,70,57,81,206,100,131,156,39,132,168,
1227923,194,70,46,137,208,21,200,129,166,39,9,24,186,39,72,119,34,66,146,36,104,
12280137,194,70,46,137,212,23,201,97,179,5,248,72,197,209,58,194,121,60,60,156,
1228136,98,232,157,129,29,164,80,78,198,46,137,218,146,121,25,71,146,9,209,5,
12282209,61,48,126,14,138,152,30,67,186,23,143,139,175,131,202,135,228,72,85,
12283144,83,60,179,30,94,209,233,102,30,98,105,230,103,30,114,121,231,104,30,
12284122,137,231,233,30,130,153,232,106,30,138,169,232,235,30,144,67,193,25,19,
12285136,108,207,30,41,224,140,137,194,173,192,153,228,5,242,100,188,248,70,137,
12286195,36,79,78,47,147,37,231,193,144,78,25,34,122,145,111,36,74,232,176,13,
1228717,61,234,226,93,207,148,160,84,75,141,7,27,161,32,33,18,225,80,212,76,154,
122882,2,70,65,56,100,237,34,140,209,2,67,32,156,50,118,145,64,186,230,61,205,
1228935,103,155,32,36,141,19,134,78,210,40,206,16,36,70,137,195,39,105,20,11,
12290174,99,220,210,54,121,210,1,137,33,1,228,207,16,17,70,146,66,3,201,164,32,
122910,65,112,152,56,196,159,31,23,77,211,195,201,199,23,160,72,214,246,81,6,12,
1229273,241,214,111,31,23,60,145,158,56,50,72,81,67,230,232,242,80,19,49,39,199,
1229389,188,124,92,242,70,120,227,64,194,75,154,72,12,9,73,6,111,21,120,12,40,
12294144,19,39,25,0,225,144,168,105,56,248,185,228,140,241,200,96,64,100,42,26,
1229578,62,46,121,35,52,18,92,116,1,36,64,47,158,64,49,98,66,100,156,242,65,23,
12296196,149,35,103,194,94,100,108,144,230,203,156,64,66,37,201,16,11,32,249,
12297132,4,34,92,44,93,146,55,152,72,24,137,112,151,153,27,36,5,100,229,144,8,
12298162,98,92,210,5,76,73,241,214,111,31,23,60,145,158,57,44,48,46,92,185,164,
12299160,72,151,41,0,50,107,179,244,59,36,93,127,92,6,19,172,3,11,216,0,56,224,
12300151,29,102,241,241,115,201,25,227,164,64,106,37,199,197,211,116,240,242,
12301113,197,233,144,40,248,185,228,140,241,196,75,132,109,24,72,128,43,39,84,
12302129,13,173,161,144,168,105,56,98,78,100,142,214,215,69,1,13,173,161,144,
12303168,105,57,34,78,100,142,214,215,69,16,67,107,105,110,114,168,254,24,147,
12304153,35,181,181,212,32,67,107,105,110,114,168,254,72,147,153,35,181,181,212,
1230536,65,130,3,144,8,26,252,200,13,30,85,16,16,64,90,242,231,192,64,161,163,
12306203,31,26,172,193,17,4,23,105,159,96,27,172,251,16,32,196,4,14,137,112,17,
12307136,48,164,28,134,80,215,202,1,132,130,8,12,39,52,64,155,31,24,56,36,1,189,
12308207,132,0,35,233,35,195,62,3,196,149,36,100,72,160,2,200,232,44,227,0,11,
1230937,160,68,142,128,36,157,25,200,32,26,79,90,4,73,43,192,122,54,71,65,103,
1231044,248,14,134,140,151,227,138,231,208,45,96,148,248,134,140,151,227,138,
12311231,240,1,255,254,10,74,146,56,128,104,4,147,152,72,6,144,28,174,143,8,1,
1231230,1,165,3,96,31,0,211,3,21,11,153,35,0,211,131,68,131,160,137,16,250,5,
12313196,131,160,137,200,160,199,156,67,248,0,255,255,65,140,10,48,177,115,56,
1231435,130,60,19,134,79,89,240,52,177,115,56,39,12,156,123,144,217,251,15,135,
1231534,167,30,20,170,154,255,232,12,47,244,0,97,28,17,224,39,238,32,40,71,4,
12316120,39,12,156,4,253,228,5,137,195,39,30,228,54,124,4,253,228,128,194,115,
1231768,9,252,15,128,232,104,201,126,56,191,35,64,90,193,41,241,13,25,47,199,23,
12318228,105,3,86,225,1,100,224,156,199,130,36,249,144,10,192,76,71,250,16,15,
1231918,61,96,17,62,200,3,72,128,136,143,247,32,22,75,64,137,248,64,22,79,90,39,
12320249,64,38,84,12,167,20,52,223,196,2,230,238,45,214,36,120,32,72,158,208,4,
12321102,238,45,194,2,201,197,186,196,143,4,9,19,218,0,92,221,202,61,228,143,4,
123229,19,218,8,35,55,113,110,16,22,78,81,239,36,120,32,72,158,208,64,73,197,12,
12323255,0,13,18,60,128,159,212,128,169,76,17,156,185,100,76,255,163,64,65,26,
1232457,114,200,153,255,70,144,33,13,18,232,50,75,226,104,6,149,3,41,199,246,
12325130,12,128,28,142,156,120,203,175,158,8,194,207,1,6,81,20,79,88,11,237,84,
1232611,161,32,127,255,247,191,255,255,255,255,137,235,16,221,170,129,116,36,0,
123270,0,0,0,16,0,0,12,196,0,0,15,135,240,0,0,0,2,61,123,164,137,162,164,218,67,
1232874,134,162,120,128,0,1,224,254,0,0,0,0,71,173,33,129,52,84,155,72,105,80,
12329212,79,16,0,0,60,63,192,0,0,0,3,244,143,146,22,230,192,0,0,176,60,0,0,0,0,
1233033,214,2,251,82,1,73,180,134,204,134,36,96,127,255,159,161,255,255,255,255,
12331144,235,16,221,169,0,164,218,67,102,67,18,48,63,255,207,240,255,255,255,
12332255,196,60,17,145,56,134,204,241,226,158,8,200,156,42,220,9,158,65,196,34,
1233392,42,26,137,147,120,64,74,37,196,54,100,49,35,188,36,5,68,184,208,113,187,
12334194,80,212,75,146,1,73,196,54,100,49,35,188,38,57,37,56,240,0,0,0,0,0,0,0,
123350,32,235,248,68,48,156,2,24,94,24,0,243,119,10,139,144,123,242,3,102,238,
1233618,239,115,72,217,160,11,223,16,23,55,113,241,32,145,36,57,188,18,16,102,3,
123375,120,35,34,89,32,15,180,152,173,127,0,218,235,88,0,228,180,227,200,0,0,
12338248,127,0,0,0,0,197,107,240,64,6,77,220,24,38,78,74,113,67,77,130,4,12,155,
12339185,52,48,156,148,226,134,155,4,10,194,96,129,132,166,238,45,194,2,201,193,
12340130,100,228,167,20,52,216,32,113,41,187,139,112,128,178,114,104,97,57,41,
12341197,13,54,8,32,48,216,32,130,195,224,130,19,97,124,134,23,6,0,57,137,62,77,
1234212,38,12,0,179,18,124,45,22,190,96,128,141,176,134,28,98,79,180,152,139,
12343218,45,124,193,1,27,97,16,32,196,159,24,230,204,246,194,40,89,137,62,210,
1234498,103,92,217,158,216,70,7,49,39,193,130,100,182,17,194,140,73,246,147,16,
12345250,9,146,216,72,6,49,39,193,131,22,194,72,73,137,62,210,98,31,65,139,97,
1234640,32,196,159,14,234,70,86,194,88,89,137,62,210,98,63,93,72,202,216,76,10,
1234749,39,198,33,180,153,37,108,38,134,152,147,237,38,38,117,13,164,201,43,97,
1234856,40,196,159,36,65,57,163,149,176,158,26,98,79,180,152,165,210,9,205,28,
12349173,133,0,243,18,124,98,22,180,72,130,115,71,43,97,68,72,196,159,105,49,51,
12350168,90,209,34,9,205,28,173,133,33,19,18,124,154,24,76,185,164,227,138,89,
1235118,119,0,7,145,39,201,161,132,188,64,124,137,62,49,11,90,36,65,57,163,149,
12352210,166,37,34,79,180,152,153,212,45,104,145,4,230,142,87,74,160,84,137,62,
1235372,130,115,71,43,171,234,134,200,147,237,38,41,116,130,115,71,43,171,235,5,
1235472,147,227,16,218,76,146,186,254,184,108,137,62,210,98,103,80,218,76,146,
12355186,254,192,68,137,62,29,212,140,174,207,178,23,34,79,180,152,143,215,82,
1235650,187,62,208,60,137,62,12,19,37,210,182,21,34,79,180,152,135,208,76,151,
1235774,224,68,137,62,49,205,153,238,175,186,23,34,79,180,152,153,215,54,103,
12358186,190,240,92,137,62,22,139,95,48,64,70,235,251,225,210,36,251,73,136,189,
12359162,215,204,16,17,186,255,2,14,98,79,152,32,35,108,48,64,242,36,249,130,2,
1236055,75,6,212,224,72,200,51,128,114,108,28,100,128,0,0,0,0,0,0,0,12,110,127,
1236148,98,115,249,201,117,243,249,195,21,159,206,38,47,63,156,86,8,75,144,94,
1236282,1,38,73,79,208,67,95,233,1,6,128,14,79,129,186,40,249,18,149,182,207,
12363144,200,155,188,248,204,105,184,207,142,199,137,175,201,0,159,72,10,5,21,
12364221,10,120,74,129,124,36,98,232,228,74,81,62,160,20,10,107,186,21,114,32,
12365105,137,194,70,46,142,68,165,19,235,1,64,170,187,161,119,34,66,146,36,104,
12366137,194,70,46,142,68,165,19,236,1,64,174,187,161,95,37,134,204,23,225,35,
1236723,71,34,82,137,246,128,160,89,93,208,167,147,195,201,194,70,46,142,68,165,
1236819,238,1,64,182,187,161,71,105,20,19,177,139,163,145,41,68,16,7,6,15,82,70,
1236972,115,96,0,27,234,32,0,0,0,0,91,60,165,195,201,194,8,134,149,216,162,0,
12370192,41,225,8,2,48,177,36,1,149,13,196,15,0,200,209,97,199,128,99,32,176,
12371195,192,113,57,143,0,167,133,32,230,80,28,202,139,175,238,2,48,189,192,20,
123721,119,80,87,193,186,129,89,56,72,197,209,200,193,185,35,23,71,109,13,219,
1237336,98,232,237,156,13,26,208,211,14,102,19,87,137,91,95,128,0,10,96,24,92,0,
123740,83,2,53,56,0,0,165,3,28,204,160,160,226,100,226,200,211,76,241,240,0,1,
12375102,8,22,75,64,137,73,20,230,105,133,7,19,39,22,70,154,103,143,128,0,11,48,
1237620,28,76,156,113,75,34,78,62,0,0,45,3,103,31,0,0,22,65,44,57,137,62,33,179,
12377216,162,152,192,131,18,124,162,27,61,138,41,108,32,196,159,16,217,232,235,
1237881,76,104,73,137,62,81,13,158,142,181,20,184,16,98,79,136,108,244,244,168,
12379166,56,36,196,159,40,134,207,79,74,138,93,10,49,39,194,173,192,158,158,149,
1238020,188,20,98,79,133,91,129,61,109,74,41,124,30,68,159,16,217,236,83,108,96,
1238168,137,62,81,13,158,197,54,182,17,34,79,136,108,244,117,169,182,52,38,68,
12382159,40,134,207,71,90,155,92,8,145,39,196,54,122,122,84,219,28,19,34,79,148,
1238367,103,167,165,77,174,133,72,147,225,86,224,79,79,74,155,94,10,145,39,194,
12384173,192,158,182,165,54,190,206,25,212,35,208,226,100,150,211,201,29,162,44,
12385140,35,103,0,0,3,192,252,0,0,0,0,206,25,228,35,208,226,100,150,211,201,29,
12386162,44,140,35,103,0,0,3,192,252,0,0,0,0,206,25,244,35,208,226,100,150,211,
12387201,29,162,44,140,35,103,0,0,3,192,252,0,0,0,0,206,26,4,35,208,226,100,150,
12388211,201,29,162,44,140,35,103,0,0,0,1,0,0,0,0,0,206,26,20,35,208,226,100,
12389150,211,201,29,162,44,140,35,103,0,0,0,1,0,0,0,0,0,206,26,36,35,208,226,
12390100,150,211,201,29,162,44,140,35,103,0,0,0,65,0,0,0,0,0,206,26,52,35,208,
12391226,100,150,211,201,29,162,44,140,35,103,0,0,0,65,0,0,0,0,0,206,26,68,35,
12392208,226,100,150,211,201,29,162,44,140,35,103,0,0,0,65,0,0,0,0,0,206,26,84,
1239335,208,226,100,150,211,201,29,162,44,140,35,103,0,0,0,129,0,0,0,0,0,195,
12394154,99,16,38,36,0,251,68,117,179,216,162,128,68,72,1,241,13,158,197,20,150,
1239525,18,0,125,162,58,217,232,235,117,100,162,136,25,18,0,125,162,58,217,232,
12396235,116,36,162,145,2,226,64,15,136,108,244,117,186,178,81,73,129,113,32,7,
12397196,54,122,58,221,9,40,165,64,200,144,3,237,17,214,207,79,75,171,37,20,80,
12398200,144,3,237,17,214,207,79,75,161,37,20,138,23,18,0,124,67,103,167,165,
12399213,146,138,77,11,137,0,62,33,179,211,210,232,73,69,42,133,196,128,31,10,
12400183,2,125,89,40,163,5,196,128,31,10,183,2,125,9,40,164,96,200,144,3,224,
12401221,64,172,157,89,40,163,134,68,128,31,6,234,5,100,232,73,69,35,133,68,128,
1240231,104,142,182,125,89,40,180,0,168,144,3,237,17,214,207,161,37,22,144,19,
1240318,0,124,67,103,213,146,139,80,9,137,0,62,33,179,232,73,69,172,5,90,40,153,
1240459,68,117,179,216,166,192,77,162,137,147,136,108,246,41,180,176,219,69,19,
1240539,104,142,182,122,58,221,89,41,178,6,218,40,153,59,68,117,179,209,214,232,
1240673,77,162,6,90,40,153,56,134,207,71,91,171,37,54,152,25,104,162,100,226,27,
1240761,29,110,132,148,218,160,109,162,137,147,180,71,91,61,61,46,172,148,217,
1240867,109,20,76,157,162,58,217,233,233,116,36,166,209,67,45,20,76,156,67,103,
12409167,165,213,146,155,77,12,180,81,50,113,13,158,158,151,66,74,109,84,50,209,
1241068,201,194,173,192,159,86,74,108,193,150,138,38,78,21,110,4,250,18,83,104,
12411193,182,138,38,78,13,212,10,201,213,146,155,56,109,162,137,147,131,117,2,
12412178,116,36,166,209,194,237,20,76,157,162,58,217,245,100,167,16,2,237,20,76,
12413157,162,58,217,244,36,167,18,2,173,20,76,156,67,103,213,146,156,80,10,180,
1241481,50,113,13,159,66,74,113,97,175,221,48,216,110,64,4,42,22,189,179,0,196,
12415133,0,185,80,32,28,78,99,193,18,80,36,4,19,159,141,172,0,178,90,4,74,73,0,
1241622,209,68,201,187,129,4,2,8,3,132,64,60,36,0,171,240,84,6,149,113,72,176,
12417157,91,116,116,32,88,181,129,32,11,42,218,221,131,234,219,165,1,8,187,152,
12418255,188,231,235,248,47,86,227,105,18,2,56,175,185,255,244,17,91,40,110,173,
12419198,209,208,36,7,188,189,179,240,238,82,97,80,93,122,32,125,144,132,160,12,
1242022,162,42,7,236,161,25,232,237,105,64,158,160,230,63,205,59,127,102,11,217,
1242166,51,210,129,61,65,236,127,154,118,254,205,171,197,34,168,48,6,90,194,1,0,
1242239,75,88,72,8,9,33,186,194,80,64,76,13,214,19,2,130,96,110,150,189,0,65,6,
1242351,214,20,128,65,17,11,214,19,130,137,121,211,210,211,144,6,39,75,88,80,0,
12424201,119,235,10,8,41,86,231,71,88,80,129,79,135,186,122,133,224,34,25,69,
12425234,80,3,91,141,172,40,96,139,113,180,181,133,36,21,110,54,142,134,176,165,
124261,176,23,213,47,0,216,134,234,215,128,111,117,181,232,128,209,3,70,230,107,
1242764,5,139,168,209,235,10,32,36,144,102,235,136,3,146,27,172,40,160,146,132,
12428103,172,40,192,115,3,117,133,28,22,113,163,69,172,41,103,1,66,188,17,145,
1242952,168,4,202,113,67,76,130,227,76,194,13,240,108,0,0,83,224,0,2,193,0,104,
12430146,84,97,48,0,1,94,192,56,169,24,145,179,192,0,5,112,8,56,16,32,128,56,18,
1243152,125,230,86,147,190,140,28,50,21,13,39,31,23,60,145,158,57,12,141,47,129,
124326,155,194,188,24,49,39,199,89,188,124,92,242,70,120,224,201,33,69,15,155,
12433163,201,68,14,49,39,199,197,211,116,240,242,113,197,232,18,180,254,36,3,17,
1243446,18,243,35,100,128,172,156,178,70,163,154,76,34,248,146,164,108,248,75,
12435204,141,146,28,217,115,137,27,95,27,241,173,236,162,160,224,200,2,206,9,
12436113,13,148,192,209,18,22,164,146,37,193,57,162,4,249,39,196,128,24,2,178,
1243766,213,136,68,201,16,77,209,131,31,192,242,88,96,92,191,151,34,100,136,38,
12438232,255,252,92,221,199,197,12,68,209,82,66,212,11,155,185,41,197,13,55,38,
124393,66,213,47,135,254,72,12,162,99,133,116,112,0,1,72,66,14,16,16,50,37,202,
12440160,150,154,66,14,20,8,57,192,28,24,80,113,50,113,100,105,166,120,248,0,0,
12441179,1,65,196,201,199,20,178,36,227,224,0,2,208,54,113,240,0,1,100,11,181,
12442192,0,5,178,1,18,160,65,24,131,20,145,25,188,48,132,122,28,76,146,218,121,
1244335,180,69,145,132,108,224,0,0,120,31,128,0,0,0,25,188,56,132,122,28,76,146,
12444218,121,35,180,69,145,132,108,224,0,0,120,31,128,0,0,0,40,160,45,110,23,30,
12445176,33,184,0,0,183,32,29,235,2,27,199,23,0,0,23,4,51,120,129,8,244,56,153,
1244637,180,242,71,104,139,35,8,217,192,0,0,240,63,0,0,0,0,51,120,145,8,244,56,
12447153,37,180,242,71,104,139,35,8,217,192,0,0,0,64,0,0,0,0,51,120,161,8,244,
1244856,153,37,180,242,71,104,139,35,8,217,192,0,0,0,64,0,0,0,0,51,120,177,8,
12449244,56,153,37,180,242,71,104,139,35,8,217,192,0,0,16,64,0,0,0,0,51,120,193,
124508,244,56,153,37,180,242,71,104,139,35,8,217,192,0,0,16,64,0,0,0,0,51,120,
12451209,8,244,56,153,37,180,242,71,104,139,35,8,217,192,0,0,16,64,0,0,0,0,51,
12452120,225,8,244,56,153,37,180,242,71,104,139,35,8,217,192,0,0,32,64,0,0,0,0,
1245332,227,194,0,97,57,162,4,246,104,5,34,92,35,68,225,161,166,220,16,16,137,
12454112,52,41,73,29,185,1,65,196,201,197,145,166,153,246,72,3,137,204,120,34,
1245574,8,199,1,67,17,162,112,201,84,128,97,144,78,25,42,16,131,169,1,205,66,8,
1245635,68,225,161,166,239,128,0,10,192,64,196,104,156,50,96,0,2,172,73,240,117,
1245796,57,170,97,4,104,156,52,52,221,240,0,1,82,1,74,9,129,125,240,0,1,82,32,
12458148,25,174,137,58,23,51,190,0,0,42,69,64,195,32,156,50,96,0,2,160,81,238,2,
124593,107,173,218,3,192,
12460};
12461#else
12462#error invalid endianness defines
12463#endif
12464#endif /* DUK_USE_ROM_OBJECTS */
12465
12466/* automatic undefs */
12467#undef DUK__REFCINIT
12468/*
12469 * Error and fatal handling.
12470 */
12471
12472/* #include duk_internal.h -> already included */
12473
12474#define DUK__ERRFMT_BUFSIZE 256 /* size for formatting buffers */
12475
12476#if defined(DUK_USE_VERBOSE_ERRORS)
12477
12479 const char *filename,
12480 duk_uint_t line_and_code,
12481 const char *fmt,
12482 ...) {
12483 va_list ap;
12485 va_start(ap, fmt);
12486 (void) DUK_VSNPRINTF(msg, sizeof(msg), fmt, ap);
12487 msg[sizeof(msg) - 1] = (char) 0;
12489 (duk_errcode_t) (line_and_code >> 24),
12490 msg,
12491 filename,
12492 (duk_int_t) (line_and_code & 0x00ffffffL));
12493 va_end(ap); /* dead code, but ensures portability (see Linux man page notes) */
12494}
12495
12496DUK_INTERNAL DUK_COLD void duk_err_handle_error(duk_hthread *thr, const char *filename, duk_uint_t line_and_code, const char *msg) {
12498 (duk_errcode_t) (line_and_code >> 24),
12499 msg,
12500 filename,
12501 (duk_int_t) (line_and_code & 0x00ffffffL));
12502}
12503
12504#else /* DUK_USE_VERBOSE_ERRORS */
12505
12507 duk_err_create_and_throw(thr, code);
12508}
12509
12510#endif /* DUK_USE_VERBOSE_ERRORS */
12511
12512/*
12513 * Error throwing helpers
12514 */
12515
12516#if defined(DUK_USE_VERBOSE_ERRORS)
12517#if defined(DUK_USE_PARANOID_ERRORS)
12519 const char *filename,
12520 duk_int_t linenumber,
12522 const char *expect_name) {
12524 filename,
12525 linenumber,
12527 "%s required, found %s (stack index %ld)",
12528 expect_name,
12529 duk_get_type_name(thr, idx),
12530 (long) idx);
12531}
12532#else
12534 const char *filename,
12535 duk_int_t linenumber,
12537 const char *expect_name) {
12539 filename,
12540 linenumber,
12542 "%s required, found %s (stack index %ld)",
12543 expect_name,
12544 duk_push_string_readable(thr, idx),
12545 (long) idx);
12546}
12547#endif
12548DUK_INTERNAL DUK_COLD void duk_err_error_internal(duk_hthread *thr, const char *filename, duk_int_t linenumber) {
12549 DUK_ERROR_RAW(thr, filename, linenumber, DUK_ERR_ERROR, DUK_STR_INTERNAL_ERROR);
12550}
12551DUK_INTERNAL DUK_COLD void duk_err_error_alloc_failed(duk_hthread *thr, const char *filename, duk_int_t linenumber) {
12552 DUK_ERROR_RAW(thr, filename, linenumber, DUK_ERR_ERROR, DUK_STR_ALLOC_FAILED);
12553}
12554DUK_INTERNAL DUK_COLD void duk_err_error(duk_hthread *thr, const char *filename, duk_int_t linenumber, const char *message) {
12555 DUK_ERROR_RAW(thr, filename, linenumber, DUK_ERR_ERROR, message);
12556}
12557DUK_INTERNAL DUK_COLD void duk_err_range(duk_hthread *thr, const char *filename, duk_int_t linenumber, const char *message) {
12558 DUK_ERROR_RAW(thr, filename, linenumber, DUK_ERR_RANGE_ERROR, message);
12559}
12560DUK_INTERNAL DUK_COLD void duk_err_range_index(duk_hthread *thr, const char *filename, duk_int_t linenumber, duk_idx_t idx) {
12561 DUK_ERROR_RAW_FMT1(thr, filename, linenumber, DUK_ERR_RANGE_ERROR, "invalid stack index %ld", (long) (idx));
12562}
12563DUK_INTERNAL DUK_COLD void duk_err_range_push_beyond(duk_hthread *thr, const char *filename, duk_int_t linenumber) {
12565}
12566DUK_INTERNAL DUK_COLD void duk_err_type_invalid_args(duk_hthread *thr, const char *filename, duk_int_t linenumber) {
12567 DUK_ERROR_RAW(thr, filename, linenumber, DUK_ERR_TYPE_ERROR, DUK_STR_INVALID_ARGS);
12568}
12569DUK_INTERNAL DUK_COLD void duk_err_type_invalid_state(duk_hthread *thr, const char *filename, duk_int_t linenumber) {
12570 DUK_ERROR_RAW(thr, filename, linenumber, DUK_ERR_TYPE_ERROR, DUK_STR_INVALID_STATE);
12571}
12572DUK_INTERNAL DUK_COLD void duk_err_type_invalid_trap_result(duk_hthread *thr, const char *filename, duk_int_t linenumber) {
12574}
12575#else
12576/* The file/line arguments are NULL and 0, they're ignored by DUK_ERROR_RAW()
12577 * when non-verbose errors are used.
12578 */
12579
12580DUK_NORETURN(DUK_LOCAL_DECL void duk__err_shared(duk_hthread *thr, duk_errcode_t code));
12581DUK_LOCAL void duk__err_shared(duk_hthread *thr, duk_errcode_t code) {
12582 DUK_ERROR_RAW(thr, NULL, 0, code, NULL);
12583}
12585 duk__err_shared(thr, DUK_ERR_ERROR);
12586}
12588 duk__err_shared(thr, DUK_ERR_RANGE_ERROR);
12589}
12590DUK_INTERNAL DUK_COLD void duk_err_eval(duk_hthread *thr) {
12591 duk__err_shared(thr, DUK_ERR_EVAL_ERROR);
12592}
12593DUK_INTERNAL DUK_COLD void duk_err_reference(duk_hthread *thr) {
12594 duk__err_shared(thr, DUK_ERR_REFERENCE_ERROR);
12595}
12596DUK_INTERNAL DUK_COLD void duk_err_syntax(duk_hthread *thr) {
12597 duk__err_shared(thr, DUK_ERR_SYNTAX_ERROR);
12598}
12599DUK_INTERNAL DUK_COLD void duk_err_type(duk_hthread *thr) {
12600 duk__err_shared(thr, DUK_ERR_TYPE_ERROR);
12601}
12602DUK_INTERNAL DUK_COLD void duk_err_uri(duk_hthread *thr) {
12603 duk__err_shared(thr, DUK_ERR_URI_ERROR);
12604}
12605#endif
12606
12607/*
12608 * Default fatal error handler
12609 */
12610
12611DUK_INTERNAL DUK_COLD void duk_default_fatal_handler(void *udata, const char *msg) {
12612 DUK_UNREF(udata);
12613 DUK_UNREF(msg);
12614
12615 msg = msg ? msg : "NULL";
12616
12617#if defined(DUK_USE_FATAL_HANDLER)
12618 /* duk_config.h provided a custom default fatal handler. */
12619 DUK_D(DUK_DPRINT("custom default fatal error handler called: %s", msg));
12620 DUK_USE_FATAL_HANDLER(udata, msg);
12621#elif defined(DUK_USE_CPP_EXCEPTIONS)
12622 /* With C++ use a duk_fatal_exception which user code can catch in
12623 * a natural way.
12624 */
12625 DUK_D(DUK_DPRINT("built-in default C++ fatal error handler called: %s", msg));
12626 throw duk_fatal_exception(msg);
12627#else
12628 /* Default behavior is to abort() on error. There's no printout
12629 * which makes this awkward, so it's always recommended to use an
12630 * explicit fatal error handler.
12631 *
12632 * ====================================================================
12633 * NOTE: If you are seeing this, you are most likely dealing with an
12634 * uncaught error. You should provide a fatal error handler in Duktape
12635 * heap creation, and should consider using a protected call as your
12636 * first call into an empty Duktape context to properly handle errors.
12637 * See:
12638 * - http://duktape.org/guide.html#error-handling
12639 * - http://wiki.duktape.org/HowtoFatalErrors.html
12640 * - http://duktape.org/api.html#taglist-protected
12641 * ====================================================================
12642 */
12643 DUK_D(DUK_DPRINT("built-in default fatal error handler called: %s", msg));
12644 DUK_ABORT();
12645#endif
12646
12647 DUK_D(DUK_DPRINT("fatal error handler returned, enter forever loop"));
12648 for (;;) {
12649 /* Loop forever to ensure we don't return. */
12650 }
12651}
12652
12653/* automatic undefs */
12654#undef DUK__ERRFMT_BUFSIZE
12656 * Various Unicode help functions for character classification predicates,
12657 * case conversion, decoding, etc.
12658 */
12659
12660/* #include duk_internal.h -> already included */
12661
12662/*
12663 * Fast path tables
12664 */
12665
12666#if defined(DUK_USE_IDCHAR_FASTPATH)
12667DUK_INTERNAL const duk_int8_t duk_is_idchar_tab[128] = {
12668 /* 0: not IdentifierStart or IdentifierPart
12669 * 1: IdentifierStart and IdentifierPart
12670 * -1: IdentifierPart only
12671 */
12672 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 0x00...0x0f */
12673 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 0x10...0x1f */
12674 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 0x20...0x2f */
12675 -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 0, 0, 0, 0, 0, 0, /* 0x30...0x3f */
12676 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, /* 0x40...0x4f */
12677 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 1, /* 0x50...0x5f */
12678 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, /* 0x60...0x6f */
12679 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0 /* 0x70...0x7f */
12680};
12681#endif
12682
12683/*
12684 * XUTF-8 and CESU-8 encoding/decoding
12685 */
12686
12689 if (x < 0x80UL) {
12690 /* 7 bits */
12691 return 1;
12692 } else if (x < 0x800UL) {
12693 /* 11 bits */
12694 return 2;
12695 } else if (x < 0x10000UL) {
12696 /* 16 bits */
12697 return 3;
12698 } else if (x < 0x200000UL) {
12699 /* 21 bits */
12700 return 4;
12701 } else if (x < 0x4000000UL) {
12702 /* 26 bits */
12703 return 5;
12704 } else if (x < (duk_ucodepoint_t) 0x80000000UL) {
12705 /* 31 bits */
12706 return 6;
12707 } else {
12708 /* 36 bits */
12709 return 7;
12710 }
12711}
12712
12713#if defined(DUK_USE_ASSERTIONS)
12714DUK_INTERNAL duk_small_int_t duk_unicode_get_cesu8_length(duk_ucodepoint_t cp) {
12716 if (x < 0x80UL) {
12717 /* 7 bits */
12718 return 1;
12719 } else if (x < 0x800UL) {
12720 /* 11 bits */
12721 return 2;
12722 } else if (x < 0x10000UL) {
12723 /* 16 bits */
12724 return 3;
12725 } else {
12726 /* Encoded as surrogate pair, each encoding to 3 bytes for
12727 * 6 bytes total. Codepoints above U+10FFFF encode as 6 bytes
12728 * too, see duk_unicode_encode_cesu8().
12730 return 3 + 3;
12731 }
12732}
12733#endif /* DUK_USE_ASSERTIONS */
12734
12735DUK_INTERNAL const duk_uint8_t duk_unicode_xutf8_markers[7] = { 0x00, 0xc0, 0xe0, 0xf0, 0xf8, 0xfc, 0xfe };
12736
12737/* Encode to extended UTF-8; 'out' must have space for at least
12738 * DUK_UNICODE_MAX_XUTF8_LENGTH bytes. Allows encoding of any
12739 * 32-bit (unsigned) codepoint.
12740 */
12743 duk_small_int_t len;
12744 duk_uint8_t marker;
12746
12748 DUK_ASSERT(len > 0);
12749
12750 marker = duk_unicode_xutf8_markers[len - 1]; /* 64-bit OK because always >= 0 */
12751
12752 i = len;
12753 DUK_ASSERT(i > 0);
12754 do {
12755 i--;
12756 if (i > 0) {
12757 out[i] = (duk_uint8_t) (0x80 + (x & 0x3f));
12758 x >>= 6;
12759 } else {
12760 /* Note: masking of 'x' is not necessary because of
12761 * range check and shifting -> no bits overlapping
12762 * the marker should be set.
12764 out[0] = (duk_uint8_t) (marker + x);
12765 }
12766 } while (i > 0);
12767
12768 return len;
12769}
12770
12771/* Encode to CESU-8; 'out' must have space for at least
12772 * DUK_UNICODE_MAX_CESU8_LENGTH bytes; codepoints above U+10FFFF
12773 * will encode to garbage but won't overwrite the output buffer.
12774 */
12777 duk_small_int_t len;
12778
12779 if (x < 0x80UL) {
12780 out[0] = (duk_uint8_t) x;
12781 len = 1;
12782 } else if (x < 0x800UL) {
12783 out[0] = (duk_uint8_t) (0xc0 + ((x >> 6) & 0x1f));
12784 out[1] = (duk_uint8_t) (0x80 + (x & 0x3f));
12785 len = 2;
12786 } else if (x < 0x10000UL) {
12787 /* surrogate pairs get encoded here */
12788 out[0] = (duk_uint8_t) (0xe0 + ((x >> 12) & 0x0f));
12789 out[1] = (duk_uint8_t) (0x80 + ((x >> 6) & 0x3f));
12790 out[2] = (duk_uint8_t) (0x80 + (x & 0x3f));
12791 len = 3;
12792 } else {
12793 /*
12794 * Unicode codepoints above U+FFFF are encoded as surrogate
12795 * pairs here. This ensures that all CESU-8 codepoints are
12796 * 16-bit values as expected in ECMAScript. The surrogate
12797 * pairs always get a 3-byte encoding (each) in CESU-8.
12798 * See: http://en.wikipedia.org/wiki/Surrogate_pair
12799 *
12800 * 20-bit codepoint, 10 bits (A and B) per surrogate pair:
12801 *
12802 * x = 0b00000000 0000AAAA AAAAAABB BBBBBBBB
12803 * sp1 = 0b110110AA AAAAAAAA (0xd800 + ((x >> 10) & 0x3ff))
12804 * sp2 = 0b110111BB BBBBBBBB (0xdc00 + (x & 0x3ff))
12805 *
12806 * Encoded into CESU-8:
12807 *
12808 * sp1 -> 0b11101101 (0xe0 + ((sp1 >> 12) & 0x0f))
12809 * -> 0b1010AAAA (0x80 + ((sp1 >> 6) & 0x3f))
12810 * -> 0b10AAAAAA (0x80 + (sp1 & 0x3f))
12811 * sp2 -> 0b11101101 (0xe0 + ((sp2 >> 12) & 0x0f))
12812 * -> 0b1011BBBB (0x80 + ((sp2 >> 6) & 0x3f))
12813 * -> 0b10BBBBBB (0x80 + (sp2 & 0x3f))
12814 *
12815 * Note that 0x10000 must be subtracted first. The code below
12816 * avoids the sp1, sp2 temporaries which saves around 20 bytes
12817 * of code.
12818 */
12819
12820 x -= 0x10000UL;
12821
12822 out[0] = (duk_uint8_t) (0xed);
12823 out[1] = (duk_uint8_t) (0xa0 + ((x >> 16) & 0x0f));
12824 out[2] = (duk_uint8_t) (0x80 + ((x >> 10) & 0x3f));
12825 out[3] = (duk_uint8_t) (0xed);
12826 out[4] = (duk_uint8_t) (0xb0 + ((x >> 6) & 0x0f));
12827 out[5] = (duk_uint8_t) (0x80 + (x & 0x3f));
12828 len = 6;
12829 }
12830
12831 return len;
12832}
12833
12834/* Decode helper. Return zero on error. */
12836 const duk_uint8_t **ptr,
12837 const duk_uint8_t *ptr_start,
12838 const duk_uint8_t *ptr_end,
12839 duk_ucodepoint_t *out_cp) {
12840 const duk_uint8_t *p;
12841 duk_uint32_t res;
12844
12845 DUK_UNREF(thr);
12846
12847 p = *ptr;
12848 if (p < ptr_start || p >= ptr_end) {
12849 goto fail;
12850 }
12851
12852 /*
12853 * UTF-8 decoder which accepts longer than standard byte sequences.
12854 * This allows full 32-bit code points to be used.
12855 */
12856
12857 ch = (duk_uint_fast8_t) (*p++);
12858 if (ch < 0x80) {
12859 /* 0xxx xxxx [7 bits] */
12860 res = (duk_uint32_t) (ch & 0x7f);
12861 n = 0;
12862 } else if (ch < 0xc0) {
12863 /* 10xx xxxx -> invalid */
12864 goto fail;
12865 } else if (ch < 0xe0) {
12866 /* 110x xxxx 10xx xxxx [11 bits] */
12867 res = (duk_uint32_t) (ch & 0x1f);
12868 n = 1;
12869 } else if (ch < 0xf0) {
12870 /* 1110 xxxx 10xx xxxx 10xx xxxx [16 bits] */
12871 res = (duk_uint32_t) (ch & 0x0f);
12872 n = 2;
12873 } else if (ch < 0xf8) {
12874 /* 1111 0xxx 10xx xxxx 10xx xxxx 10xx xxxx [21 bits] */
12875 res = (duk_uint32_t) (ch & 0x07);
12876 n = 3;
12877 } else if (ch < 0xfc) {
12878 /* 1111 10xx 10xx xxxx 10xx xxxx 10xx xxxx 10xx xxxx [26 bits] */
12879 res = (duk_uint32_t) (ch & 0x03);
12880 n = 4;
12881 } else if (ch < 0xfe) {
12882 /* 1111 110x 10xx xxxx 10xx xxxx 10xx xxxx 10xx xxxx 10xx xxxx [31 bits] */
12883 res = (duk_uint32_t) (ch & 0x01);
12884 n = 5;
12885 } else if (ch < 0xff) {
12886 /* 1111 1110 10xx xxxx 10xx xxxx 10xx xxxx 10xx xxxx 10xx xxxx 10xx xxxx [36 bits] */
12887 res = (duk_uint32_t) (0);
12888 n = 6;
12889 } else {
12890 /* 8-byte format could be:
12891 * 1111 1111 10xx xxxx 10xx xxxx 10xx xxxx 10xx xxxx 10xx xxxx 10xx xxxx 10xx xxxx [41 bits]
12892 *
12893 * However, this format would not have a zero bit following the
12894 * leading one bits and would not allow 0xFF to be used as an
12895 * "invalid xutf-8" marker for internal keys. Further, 8-byte
12896 * encodings (up to 41 bit code points) are not currently needed.
12897 */
12898 goto fail;
12899 }
12900
12901 DUK_ASSERT(p >= ptr_start); /* verified at beginning */
12902 if (p + n > ptr_end) {
12903 /* check pointer at end */
12904 goto fail;
12905 }
12906
12907 while (n > 0) {
12908 DUK_ASSERT(p >= ptr_start && p < ptr_end);
12909 ch = (duk_uint_fast8_t) (*p++);
12910#if 0
12911 if (ch & 0xc0 != 0x80) {
12912 /* not a continuation byte */
12913 p--;
12914 *ptr = p;
12916 return 1;
12917 }
12918#endif
12919 res = (res << 6) + (duk_uint32_t) (ch & 0x3f);
12920 n--;
12921 }
12922
12923 *ptr = p;
12924 *out_cp = res;
12925 return 1;
12926
12927fail:
12928 return 0;
12929}
12930
12931/* used by e.g. duk_regexp_executor.c, string built-ins */
12933 const duk_uint8_t **ptr,
12934 const duk_uint8_t *ptr_start,
12935 const duk_uint8_t *ptr_end) {
12937
12938 if (duk_unicode_decode_xutf8(thr, ptr, ptr_start, ptr_end, &cp)) {
12939 return cp;
12940 }
12941 DUK_ERROR_INTERNAL(thr);
12942 DUK_WO_NORETURN(return 0;);
12943}
12944
12945/* Compute (extended) utf-8 length without codepoint encoding validation,
12946 * used for string interning.
12947 *
12948 * NOTE: This algorithm is performance critical, more so than string hashing
12949 * in some cases. It is needed when interning a string and needs to scan
12950 * every byte of the string with no skipping. Having an ASCII fast path
12951 * is useful if possible in the algorithm. The current algorithms were
12952 * chosen from several variants, based on x64 gcc -O2 testing. See:
12953 * https://github.com/svaarala/duktape/pull/422
12954 *
12955 * NOTE: must match tools/dukutil.py:duk_unicode_unvalidated_utf8_length().
12956 */
12957
12958#if defined(DUK_USE_PREFER_SIZE)
12959/* Small variant; roughly 150 bytes smaller than the fast variant. */
12961 const duk_uint8_t *p;
12962 const duk_uint8_t *p_end;
12963 duk_size_t ncont;
12964 duk_size_t clen;
12965
12966 p = data;
12967 p_end = data + blen;
12968 ncont = 0;
12969 while (p != p_end) {
12970 duk_uint8_t x;
12971 x = *p++;
12972 if (DUK_UNLIKELY(x >= 0x80 && x <= 0xbf)) {
12973 ncont++;
12975 }
12976
12977 DUK_ASSERT(ncont <= blen);
12978 clen = blen - ncont;
12979 DUK_ASSERT(clen <= blen);
12980 return clen;
12981}
12982#else /* DUK_USE_PREFER_SIZE */
12983/* This seems like a good overall approach. Fast path for ASCII in 4 byte
12984 * blocks.
12985 */
12987 const duk_uint8_t *p;
12988 const duk_uint8_t *p_end;
12989 const duk_uint32_t *p32_end;
12990 const duk_uint32_t *p32;
12991 duk_size_t ncont;
12992 duk_size_t clen;
12993
12994 ncont = 0; /* number of continuation (non-initial) bytes in [0x80,0xbf] */
12995 p = data;
12996 p_end = data + blen;
12997 if (blen < 16) {
12998 goto skip_fastpath;
12999 }
13000
13001 /* Align 'p' to 4; the input data may have arbitrary alignment.
13002 * End of string check not needed because blen >= 16.
13003 */
13004 while (((duk_size_t) (const void *) p) & 0x03U) {
13005 duk_uint8_t x;
13006 x = *p++;
13007 if (DUK_UNLIKELY(x >= 0x80 && x <= 0xbf)) {
13008 ncont++;
13009 }
13010 }
13011
13012 /* Full, aligned 4-byte reads. */
13013 p32_end = (const duk_uint32_t *) (const void *) (p + ((duk_size_t) (p_end - p) & (duk_size_t) (~0x03)));
13014 p32 = (const duk_uint32_t *) (const void *) p;
13015 while (p32 != (const duk_uint32_t *) p32_end) {
13016 duk_uint32_t x;
13017 x = *p32++;
13018 if (DUK_LIKELY((x & 0x80808080UL) == 0)) {
13019 ; /* ASCII fast path */
13020 } else {
13021 /* Flip highest bit of each byte which changes
13022 * the bit pattern 10xxxxxx into 00xxxxxx which
13023 * allows an easy bit mask test.
13024 */
13025 x ^= 0x80808080UL;
13026 if (DUK_UNLIKELY(!(x & 0xc0000000UL))) {
13027 ncont++;
13028 }
13029 if (DUK_UNLIKELY(!(x & 0x00c00000UL))) {
13030 ncont++;
13031 }
13032 if (DUK_UNLIKELY(!(x & 0x0000c000UL))) {
13033 ncont++;
13034 }
13035 if (DUK_UNLIKELY(!(x & 0x000000c0UL))) {
13036 ncont++;
13037 }
13038 }
13039 }
13040 p = (const duk_uint8_t *) p32;
13041 /* Fall through to handle the rest. */
13042
13043skip_fastpath:
13044 while (p != p_end) {
13045 duk_uint8_t x;
13046 x = *p++;
13047 if (DUK_UNLIKELY(x >= 0x80 && x <= 0xbf)) {
13048 ncont++;
13049 }
13050 }
13051
13052 DUK_ASSERT(ncont <= blen);
13053 clen = blen - ncont;
13054 DUK_ASSERT(clen <= blen);
13055 return clen;
13056}
13057#endif /* DUK_USE_PREFER_SIZE */
13058
13059/* Check whether a string is UTF-8 compatible or not. */
13061 duk_size_t i = 0;
13062#if !defined(DUK_USE_PREFER_SIZE)
13063 duk_size_t len_safe;
13064#endif
13065
13066 /* Many practical strings are ASCII only, so use a fast path check
13067 * to check chunks of bytes at once with minimal branch cost.
13068 */
13069#if !defined(DUK_USE_PREFER_SIZE)
13070 len_safe = len & ~0x03UL;
13071 for (; i < len_safe; i += 4) {
13072 duk_uint8_t t = buf[i] | buf[i + 1] | buf[i + 2] | buf[i + 3];
13073 if (DUK_UNLIKELY((t & 0x80U) != 0U)) {
13074 /* At least one byte was outside 0x00-0x7f, break
13075 * out to slow path (and remain there).
13076 *
13077 * XXX: We could also deal with the problem character
13078 * and resume fast path later.
13079 */
13080 break;
13081 }
13082 }
13083#endif
13084
13085 for (; i < len;) {
13086 duk_uint8_t t;
13087 duk_size_t left;
13088 duk_size_t ncont;
13089 duk_uint32_t cp;
13090 duk_uint32_t mincp;
13091
13092 t = buf[i++];
13093 if (DUK_LIKELY((t & 0x80U) == 0U)) {
13094 /* Fast path, ASCII. */
13095 continue;
13096 }
13097
13098 /* Non-ASCII start byte, slow path.
13099 *
13100 * 10xx xxxx -> continuation byte
13101 * 110x xxxx + 1*CONT -> [0x80, 0x7ff]
13102 * 1110 xxxx + 2*CONT -> [0x800, 0xffff], must reject [0xd800,0xdfff]
13103 * 1111 0xxx + 3*CONT -> [0x10000, 0x10ffff]
13104 */
13105 left = len - i;
13106 if (t <= 0xdfU) { /* 1101 1111 = 0xdf */
13107 if (t <= 0xbfU) { /* 1011 1111 = 0xbf */
13108 return 0;
13109 }
13110 ncont = 1;
13111 mincp = 0x80UL;
13112 cp = t & 0x1fU;
13113 } else if (t <= 0xefU) { /* 1110 1111 = 0xef */
13114 ncont = 2;
13115 mincp = 0x800UL;
13116 cp = t & 0x0fU;
13117 } else if (t <= 0xf7U) { /* 1111 0111 = 0xf7 */
13118 ncont = 3;
13119 mincp = 0x10000UL;
13120 cp = t & 0x07U;
13121 } else {
13122 return 0;
13123 }
13124 if (left < ncont) {
13125 return 0;
13126 }
13127 while (ncont > 0U) {
13128 t = buf[i++];
13129 if ((t & 0xc0U) != 0x80U) { /* 10xx xxxx */
13130 return 0;
13131 }
13132 cp = (cp << 6) + (t & 0x3fU);
13133 ncont--;
13134 }
13135 if (cp < mincp || cp > 0x10ffffUL || (cp >= 0xd800UL && cp <= 0xdfffUL)) {
13136 return 0;
13137 }
13138 }
13140 return 1;
13141}
13142
13143/*
13144 * Unicode range matcher
13145 *
13146 * Matches a codepoint against a packed bitstream of character ranges.
13147 * Used for slow path Unicode matching.
13148 */
13149
13150/* Must match tools/extract_chars.py, generate_match_table3(). */
13152 duk_uint32_t t;
13153
13154 t = (duk_uint32_t) duk_bd_decode(bd_ctx, 4);
13155 if (t <= 0x0eU) {
13156 return t;
13157 }
13158 t = (duk_uint32_t) duk_bd_decode(bd_ctx, 8);
13159 if (t <= 0xfdU) {
13160 return t + 0x0f;
13161 }
13162 if (t == 0xfeU) {
13163 t = (duk_uint32_t) duk_bd_decode(bd_ctx, 12);
13164 return t + 0x0fU + 0xfeU;
13165 } else {
13166 t = (duk_uint32_t) duk_bd_decode(bd_ctx, 24);
13167 return t + 0x0fU + 0xfeU + 0x1000UL;
13168 }
13169}
13170
13171DUK_LOCAL duk_small_int_t duk__uni_range_match(const duk_uint8_t *unitab, duk_size_t unilen, duk_codepoint_t cp) {
13172 duk_bitdecoder_ctx bd_ctx;
13173 duk_codepoint_t prev_re;
13174
13175 duk_memzero(&bd_ctx, sizeof(bd_ctx));
13176 bd_ctx.data = (const duk_uint8_t *) unitab;
13177 bd_ctx.length = (duk_size_t) unilen;
13178
13179 prev_re = 0;
13180 for (;;) {
13181 duk_codepoint_t r1, r2;
13182 r1 = (duk_codepoint_t) duk__uni_decode_value(&bd_ctx);
13183 if (r1 == 0) {
13184 break;
13185 }
13186 r2 = (duk_codepoint_t) duk__uni_decode_value(&bd_ctx);
13187
13188 r1 = prev_re + r1;
13189 r2 = r1 + r2;
13190 prev_re = r2;
13191
13192 /* [r1,r2] is the range */
13193
13194 DUK_DDD(DUK_DDDPRINT("duk__uni_range_match: cp=%06lx range=[0x%06lx,0x%06lx]",
13195 (unsigned long) cp,
13196 (unsigned long) r1,
13197 (unsigned long) r2));
13198 if (cp >= r1 && cp <= r2) {
13199 return 1;
13200 }
13201 }
13202
13203 return 0;
13204}
13205
13206/*
13207 * "WhiteSpace" production check.
13208 */
13209
13211 /*
13212 * E5 Section 7.2 specifies six characters specifically as
13213 * white space:
13214 *
13215 * 0009;<control>;Cc;0;S;;;;;N;CHARACTER TABULATION;;;;
13216 * 000B;<control>;Cc;0;S;;;;;N;LINE TABULATION;;;;
13217 * 000C;<control>;Cc;0;WS;;;;;N;FORM FEED (FF);;;;
13218 * 0020;SPACE;Zs;0;WS;;;;;N;;;;;
13219 * 00A0;NO-BREAK SPACE;Zs;0;CS;<noBreak> 0020;;;;N;NON-BREAKING SPACE;;;;
13220 * FEFF;ZERO WIDTH NO-BREAK SPACE;Cf;0;BN;;;;;N;BYTE ORDER MARK;;;;
13221 *
13222 * It also specifies any Unicode category 'Zs' characters as white
13223 * space. These can be extracted with the "tools/extract_chars.py" script.
13224 * Current result:
13225 *
13226 * RAW OUTPUT:
13227 * ===========
13228 * 0020;SPACE;Zs;0;WS;;;;;N;;;;;
13229 * 00A0;NO-BREAK SPACE;Zs;0;CS;<noBreak> 0020;;;;N;NON-BREAKING SPACE;;;;
13230 * 1680;OGHAM SPACE MARK;Zs;0;WS;;;;;N;;;;;
13231 * 180E;MONGOLIAN VOWEL SEPARATOR;Zs;0;WS;;;;;N;;;;;
13232 * 2000;EN QUAD;Zs;0;WS;2002;;;;N;;;;;
13233 * 2001;EM QUAD;Zs;0;WS;2003;;;;N;;;;;
13234 * 2002;EN SPACE;Zs;0;WS;<compat> 0020;;;;N;;;;;
13235 * 2003;EM SPACE;Zs;0;WS;<compat> 0020;;;;N;;;;;
13236 * 2004;THREE-PER-EM SPACE;Zs;0;WS;<compat> 0020;;;;N;;;;;
13237 * 2005;FOUR-PER-EM SPACE;Zs;0;WS;<compat> 0020;;;;N;;;;;
13238 * 2006;SIX-PER-EM SPACE;Zs;0;WS;<compat> 0020;;;;N;;;;;
13239 * 2007;FIGURE SPACE;Zs;0;WS;<noBreak> 0020;;;;N;;;;;
13240 * 2008;PUNCTUATION SPACE;Zs;0;WS;<compat> 0020;;;;N;;;;;
13241 * 2009;THIN SPACE;Zs;0;WS;<compat> 0020;;;;N;;;;;
13242 * 200A;HAIR SPACE;Zs;0;WS;<compat> 0020;;;;N;;;;;
13243 * 202F;NARROW NO-BREAK SPACE;Zs;0;CS;<noBreak> 0020;;;;N;;;;;
13244 * 205F;MEDIUM MATHEMATICAL SPACE;Zs;0;WS;<compat> 0020;;;;N;;;;;
13245 * 3000;IDEOGRAPHIC SPACE;Zs;0;WS;<wide> 0020;;;;N;;;;;
13246 *
13247 * RANGES:
13248 * =======
13249 * 0x0020
13250 * 0x00a0
13251 * 0x1680
13252 * 0x180e
13253 * 0x2000 ... 0x200a
13254 * 0x202f
13255 * 0x205f
13256 * 0x3000
13257 *
13258 * A manual decoder (below) is probably most compact for this.
13259 */
13260
13263
13264 /* cp == -1 (EOF) never matches and causes return value 0 */
13265
13266 lo = (duk_uint_fast8_t) (cp & 0xff);
13267 hi = (duk_uint_fast32_t) (cp >> 8); /* does not fit into an uchar */
13268
13269 if (hi == 0x0000UL) {
13270 if (lo == 0x09U || lo == 0x0bU || lo == 0x0cU || lo == 0x20U || lo == 0xa0U) {
13271 return 1;
13272 }
13273 } else if (hi == 0x0020UL) {
13274 if (lo <= 0x0aU || lo == 0x2fU || lo == 0x5fU) {
13275 return 1;
13277 } else if (cp == 0x1680L || cp == 0x180eL || cp == 0x3000L || cp == 0xfeffL) {
13278 return 1;
13279 }
13280
13281 return 0;
13282}
13283
13284/*
13285 * "LineTerminator" production check.
13286 */
13287
13289 /*
13290 * E5 Section 7.3
13291 *
13292 * A LineTerminatorSequence essentially merges <CR> <LF> sequences
13293 * into a single line terminator. This must be handled by the caller.
13294 */
13296 if (cp == 0x000aL || cp == 0x000dL || cp == 0x2028L || cp == 0x2029L) {
13297 return 1;
13298 }
13299
13300 return 0;
13301}
13302
13303/*
13304 * "IdentifierStart" production check.
13305 */
13306
13308 /*
13309 * E5 Section 7.6:
13310 *
13311 * IdentifierStart:
13312 * UnicodeLetter
13313 * $
13314 * _
13315 * \ UnicodeEscapeSequence
13316 *
13317 * IdentifierStart production has one multi-character production:
13318 *
13319 * \ UnicodeEscapeSequence
13320 *
13321 * The '\' character is -not- matched by this function. Rather, the caller
13322 * should decode the escape and then call this function to check whether the
13323 * decoded character is acceptable (see discussion in E5 Section 7.6).
13324 *
13325 * The "UnicodeLetter" alternative of the production allows letters
13326 * from various Unicode categories. These can be extracted with the
13327 * "tools/extract_chars.py" script.
13328 *
13329 * Because the result has hundreds of Unicode codepoint ranges, matching
13330 * for any values >= 0x80 are done using a very slow range-by-range scan
13331 * and a packed range format.
13332 *
13333 * The ASCII portion (codepoints 0x00 ... 0x7f) is fast-pathed below because
13334 * it matters the most. The ASCII related ranges of IdentifierStart are:
13335 *
13336 * 0x0041 ... 0x005a ['A' ... 'Z']
13337 * 0x0061 ... 0x007a ['a' ... 'z']
13338 * 0x0024 ['$']
13339 * 0x005f ['_']
13340 */
13341
13342 /* ASCII (and EOF) fast path -- quick accept and reject */
13343 if (cp <= 0x7fL) {
13344#if defined(DUK_USE_IDCHAR_FASTPATH)
13345 return (cp >= 0) && (duk_is_idchar_tab[cp] > 0);
13346#else
13347 if ((cp >= 'a' && cp <= 'z') || (cp >= 'A' && cp <= 'Z') || cp == '_' || cp == '$') {
13348 return 1;
13349 }
13350 return 0;
13351#endif
13352 }
13353
13354 /* Non-ASCII slow path (range-by-range linear comparison), very slow */
13355
13356#if defined(DUK_USE_SOURCE_NONBMP)
13358 return 1;
13359 }
13360 return 0;
13361#else
13362 if (cp < 0x10000L) {
13363 if (duk__uni_range_match(duk_unicode_ids_noabmp, sizeof(duk_unicode_ids_noabmp), (duk_codepoint_t) cp)) {
13364 return 1;
13365 }
13366 return 0;
13367 } else {
13368 /* without explicit non-BMP support, assume non-BMP characters
13369 * are always accepted as identifier characters.
13370 */
13371 return 1;
13372 }
13373#endif
13374}
13375
13376/*
13377 * "IdentifierPart" production check.
13378 */
13379
13381 /*
13382 * E5 Section 7.6:
13383 *
13384 * IdentifierPart:
13385 * IdentifierStart
13386 * UnicodeCombiningMark
13387 * UnicodeDigit
13388 * UnicodeConnectorPunctuation
13389 * <ZWNJ> [U+200C]
13390 * <ZWJ> [U+200D]
13391 *
13392 * IdentifierPart production has one multi-character production
13393 * as part of its IdentifierStart alternative. The '\' character
13394 * of an escape sequence is not matched here, see discussion in
13395 * duk_unicode_is_identifier_start().
13396 *
13397 * To match non-ASCII characters (codepoints >= 0x80), a very slow
13398 * linear range-by-range scan is used. The codepoint is first compared
13399 * to the IdentifierStart ranges, and if it doesn't match, then to a
13400 * set consisting of code points in IdentifierPart but not in
13401 * IdentifierStart. This is done to keep the unicode range data small,
13402 * at the expense of speed.
13403 *
13404 * The ASCII fast path consists of:
13405 *
13406 * 0x0030 ... 0x0039 ['0' ... '9', UnicodeDigit]
13407 * 0x0041 ... 0x005a ['A' ... 'Z', IdentifierStart]
13408 * 0x0061 ... 0x007a ['a' ... 'z', IdentifierStart]
13409 * 0x0024 ['$', IdentifierStart]
13410 * 0x005f ['_', IdentifierStart and
13411 * UnicodeConnectorPunctuation]
13412 *
13413 * UnicodeCombiningMark has no code points <= 0x7f.
13414 *
13415 * The matching code reuses the "identifier start" tables, and then
13416 * consults a separate range set for characters in "identifier part"
13417 * but not in "identifier start". These can be extracted with the
13418 * "tools/extract_chars.py" script.
13419 *
13420 * UnicodeCombiningMark -> categories Mn, Mc
13421 * UnicodeDigit -> categories Nd
13422 * UnicodeConnectorPunctuation -> categories Pc
13423 */
13424
13425 /* ASCII (and EOF) fast path -- quick accept and reject */
13426 if (cp <= 0x7fL) {
13427#if defined(DUK_USE_IDCHAR_FASTPATH)
13428 return (cp >= 0) && (duk_is_idchar_tab[cp] != 0);
13429#else
13430 if ((cp >= 'a' && cp <= 'z') || (cp >= 'A' && cp <= 'Z') || (cp >= '0' && cp <= '9') || cp == '_' || cp == '$') {
13431 return 1;
13432 }
13433 return 0;
13434#endif
13435 }
13436
13437 /* Non-ASCII slow path (range-by-range linear comparison), very slow */
13438
13439#if defined(DUK_USE_SOURCE_NONBMP)
13442 return 1;
13443 }
13444 return 0;
13445#else
13446 if (cp < 0x10000L) {
13447 if (duk__uni_range_match(duk_unicode_ids_noabmp, sizeof(duk_unicode_ids_noabmp), (duk_codepoint_t) cp) ||
13448 duk__uni_range_match(duk_unicode_idp_m_ids_noabmp,
13449 sizeof(duk_unicode_idp_m_ids_noabmp),
13450 (duk_codepoint_t) cp)) {
13451 return 1;
13452 }
13453 return 0;
13454 } else {
13455 /* without explicit non-BMP support, assume non-BMP characters
13456 * are always accepted as identifier characters.
13457 */
13458 return 1;
13459 }
13460#endif
13461}
13462
13463/*
13464 * Unicode letter check.
13465 */
13466
13468 /*
13469 * Unicode letter is now taken to be the categories:
13470 *
13471 * Lu, Ll, Lt, Lm, Lo
13472 *
13473 * (Not sure if this is exactly correct.)
13474 *
13475 * The ASCII fast path consists of:
13476 *
13477 * 0x0041 ... 0x005a ['A' ... 'Z']
13478 * 0x0061 ... 0x007a ['a' ... 'z']
13479 */
13480
13481 /* ASCII (and EOF) fast path -- quick accept and reject */
13482 if (cp <= 0x7fL) {
13483 if ((cp >= 'a' && cp <= 'z') || (cp >= 'A' && cp <= 'Z')) {
13484 return 1;
13485 }
13486 return 0;
13487 }
13488
13489 /* Non-ASCII slow path (range-by-range linear comparison), very slow */
13490
13491#if defined(DUK_USE_SOURCE_NONBMP)
13494 return 1;
13495 }
13496 return 0;
13497#else
13498 if (cp < 0x10000L) {
13499 if (duk__uni_range_match(duk_unicode_ids_noabmp, sizeof(duk_unicode_ids_noabmp), (duk_codepoint_t) cp) &&
13500 !duk__uni_range_match(duk_unicode_ids_m_let_noabmp,
13501 sizeof(duk_unicode_ids_m_let_noabmp),
13502 (duk_codepoint_t) cp)) {
13503 return 1;
13504 }
13505 return 0;
13506 } else {
13507 /* without explicit non-BMP support, assume non-BMP characters
13508 * are always accepted as letters.
13509 */
13510 return 1;
13511 }
13512#endif
13513}
13514
13515/*
13516 * Complex case conversion helper which decodes a bit-packed conversion
13517 * control stream generated by tools/extract_caseconv.py. The conversion
13518 * is very slow because it runs through the conversion data in a linear
13519 * fashion to save space (which is why ASCII characters have a special
13520 * fast path before arriving here).
13521 *
13522 * The particular bit counts etc have been determined experimentally to
13523 * be small but still sufficient, and must match the Python script
13524 * (tools/extract_caseconv.py).
13525 *
13526 * The return value is the case converted codepoint or -1 if the conversion
13527 * results in multiple characters (this is useful for regexp Canonicalization
13528 * operation). If 'buf' is not NULL, the result codepoint(s) are also
13529 * appended to the hbuffer.
13530 *
13531 * Context and locale specific rules must be checked before consulting
13532 * this function.
13533 */
13534
13537 duk_small_int_t skip = 0;
13541 duk_codepoint_t tmp_cp;
13542 duk_codepoint_t start_i;
13543 duk_codepoint_t start_o;
13544
13545 DUK_ASSERT(bd_ctx != NULL);
13546 DUK_UNREF(thr);
13547
13548 DUK_DDD(DUK_DDDPRINT("slow case conversion for codepoint: %ld", (long) cp));
13549
13550 /* range conversion with a "skip" */
13551 DUK_DDD(DUK_DDDPRINT("checking ranges"));
13552 for (;;) {
13553 skip++;
13554 n = (duk_small_int_t) duk_bd_decode(bd_ctx, 6);
13555 if (n == 0x3f) {
13556 /* end marker */
13557 break;
13558 }
13559 DUK_DDD(DUK_DDDPRINT("skip=%ld, n=%ld", (long) skip, (long) n));
13560
13561 while (n--) {
13562 start_i = (duk_codepoint_t) duk_bd_decode(bd_ctx, 16);
13563 start_o = (duk_codepoint_t) duk_bd_decode(bd_ctx, 16);
13564 count = (duk_small_int_t) duk_bd_decode(bd_ctx, 7);
13565 DUK_DDD(DUK_DDDPRINT("range: start_i=%ld, start_o=%ld, count=%ld, skip=%ld",
13566 (long) start_i,
13567 (long) start_o,
13568 (long) count,
13569 (long) skip));
13570
13571 if (cp >= start_i) {
13572 tmp_cp = cp - start_i; /* always >= 0 */
13573 if (tmp_cp < (duk_codepoint_t) count * (duk_codepoint_t) skip &&
13574 (tmp_cp % (duk_codepoint_t) skip) == 0) {
13575 DUK_DDD(DUK_DDDPRINT("range matches input codepoint"));
13576 cp = start_o + tmp_cp;
13577 goto single;
13578 }
13579 }
13580 }
13581 }
13582
13583 /* 1:1 conversion */
13584 n = (duk_small_int_t) duk_bd_decode(bd_ctx, 7);
13585 DUK_DDD(DUK_DDDPRINT("checking 1:1 conversions (count %ld)", (long) n));
13586 while (n--) {
13587 start_i = (duk_codepoint_t) duk_bd_decode(bd_ctx, 16);
13588 start_o = (duk_codepoint_t) duk_bd_decode(bd_ctx, 16);
13589 DUK_DDD(DUK_DDDPRINT("1:1 conversion %ld -> %ld", (long) start_i, (long) start_o));
13590 if (cp == start_i) {
13591 DUK_DDD(DUK_DDDPRINT("1:1 matches input codepoint"));
13592 cp = start_o;
13593 goto single;
13594 }
13595 }
13596
13597 /* complex, multicharacter conversion */
13598 n = (duk_small_int_t) duk_bd_decode(bd_ctx, 7);
13599 DUK_DDD(DUK_DDDPRINT("checking 1:n conversions (count %ld)", (long) n));
13600 while (n--) {
13601 start_i = (duk_codepoint_t) duk_bd_decode(bd_ctx, 16);
13602 t = (duk_small_int_t) duk_bd_decode(bd_ctx, 2);
13603 DUK_DDD(DUK_DDDPRINT("1:n conversion %ld -> %ld chars", (long) start_i, (long) t));
13604 if (cp == start_i) {
13605 DUK_DDD(DUK_DDDPRINT("1:n matches input codepoint"));
13606 if (bw != NULL) {
13607 while (t--) {
13608 tmp_cp = (duk_codepoint_t) duk_bd_decode(bd_ctx, 16);
13609 DUK_BW_WRITE_RAW_XUTF8(thr, bw, (duk_ucodepoint_t) tmp_cp);
13610 }
13611 }
13612 return -1;
13613 } else {
13614 while (t--) {
13615 (void) duk_bd_decode(bd_ctx, 16);
13616 }
13617 }
13618 }
13619
13620 /* default: no change */
13621 DUK_DDD(DUK_DDDPRINT("no rule matches, output is same as input"));
13622 /* fall through */
13623
13624single:
13625 if (bw != NULL) {
13627 }
13628 return cp;
13629}
13631/*
13632 * Case conversion helper, with context/local sensitivity.
13633 * For proper case conversion, one needs to know the character
13634 * and the preceding and following characters, as well as
13635 * locale/language.
13636 */
13637
13638/* XXX: add 'language' argument when locale/language sensitive rule
13639 * support added.
13640 */
13644 duk_codepoint_t cp,
13645 duk_codepoint_t prev,
13646 duk_codepoint_t next,
13647 duk_bool_t uppercase) {
13648 duk_bitdecoder_ctx bd_ctx;
13649
13650 /* fast path for ASCII */
13651 if (cp < 0x80L) {
13652 /* XXX: there are language sensitive rules for the ASCII range.
13653 * If/when language/locale support is implemented, they need to
13654 * be implemented here for the fast path. There are no context
13655 * sensitive rules for ASCII range.
13656 */
13657
13658 if (uppercase) {
13659 if (cp >= 'a' && cp <= 'z') {
13660 cp = cp - 'a' + 'A';
13661 }
13662 } else {
13663 if (cp >= 'A' && cp <= 'Z') {
13664 cp = cp - 'A' + 'a';
13665 }
13666 }
13667
13668 if (bw != NULL) {
13669 DUK_BW_WRITE_RAW_U8(thr, bw, (duk_uint8_t) cp);
13670 }
13671 return cp;
13672 }
13673
13674 /* context and locale specific rules which cannot currently be represented
13675 * in the caseconv bitstream: hardcoded rules in C
13676 */
13677 if (uppercase) {
13678 /* XXX: turkish / azeri */
13679 } else {
13680 /*
13681 * Final sigma context specific rule. This is a rather tricky
13682 * rule and this handling is probably not 100% correct now.
13683 * The rule is not locale/language specific so it is supported.
13684 */
13685
13686 if (cp == 0x03a3L && /* U+03A3 = GREEK CAPITAL LETTER SIGMA */
13687 duk_unicode_is_letter(prev) && /* prev exists and is not a letter */
13688 !duk_unicode_is_letter(next)) { /* next does not exist or next is not a letter */
13689 /* Capital sigma occurred at "end of word", lowercase to
13690 * U+03C2 = GREEK SMALL LETTER FINAL SIGMA. Otherwise
13691 * fall through and let the normal rules lowercase it to
13692 * U+03C3 = GREEK SMALL LETTER SIGMA.
13693 */
13694 cp = 0x03c2L;
13695 goto singlechar;
13696 }
13697
13698 /* XXX: lithuanian not implemented */
13699 /* XXX: lithuanian, explicit dot rules */
13700 /* XXX: turkish / azeri, lowercase rules */
13701 }
13702
13703 /* 1:1 or special conversions, but not locale/context specific: script generated rules */
13704 duk_memzero(&bd_ctx, sizeof(bd_ctx));
13705 if (uppercase) {
13706 bd_ctx.data = (const duk_uint8_t *) duk_unicode_caseconv_uc;
13707 bd_ctx.length = (duk_size_t) sizeof(duk_unicode_caseconv_uc);
13708 } else {
13709 bd_ctx.data = (const duk_uint8_t *) duk_unicode_caseconv_lc;
13710 bd_ctx.length = (duk_size_t) sizeof(duk_unicode_caseconv_lc);
13711 }
13712 return duk__slow_case_conversion(thr, bw, cp, &bd_ctx);
13713
13714singlechar:
13715 if (bw != NULL) {
13717 }
13718 return cp;
13720 /* unused now, not needed until Turkish/Azeri */
13721#if 0
13722 nochar:
13723 return -1;
13724#endif
13725}
13726
13727/*
13728 * Replace valstack top with case converted version.
13729 */
13730
13732 duk_hstring *h_input;
13733 duk_bufwriter_ctx bw_alloc;
13735 const duk_uint8_t *p, *p_start, *p_end;
13736 duk_codepoint_t prev, curr, next;
13737
13738 h_input = duk_require_hstring(thr, -1); /* Accept symbols. */
13739 DUK_ASSERT(h_input != NULL);
13740
13741 bw = &bw_alloc;
13743
13744 /* [ ... input buffer ] */
13745
13746 p_start = (const duk_uint8_t *) DUK_HSTRING_GET_DATA(h_input);
13747 p_end = p_start + DUK_HSTRING_GET_BYTELEN(h_input);
13748 p = p_start;
13749
13750 prev = -1;
13751 DUK_UNREF(prev);
13752 curr = -1;
13753 next = -1;
13754 for (;;) {
13755 prev = curr;
13756 curr = next;
13757 next = -1;
13758 if (p < p_end) {
13759 next = (duk_codepoint_t) duk_unicode_decode_xutf8_checked(thr, &p, p_start, p_end);
13760 } else {
13761 /* end of input and last char has been processed */
13762 if (curr < 0) {
13763 break;
13764 }
13765 }
13766
13767 /* on first round, skip */
13768 if (curr >= 0) {
13769 /* XXX: could add a fast path to process chunks of input codepoints,
13770 * but relative benefit would be quite small.
13771 */
13772
13773 /* Ensure space for maximum multi-character result; estimate is overkill. */
13775
13776 duk__case_transform_helper(thr, bw, (duk_codepoint_t) curr, prev, next, uppercase);
13777 }
13778 }
13779
13780 DUK_BW_COMPACT(thr, bw);
13781 (void) duk_buffer_to_string(thr, -1); /* Safe, output is encoded. */
13782 /* invalidates h_buf pointer */
13784}
13785
13786#if defined(DUK_USE_REGEXP_SUPPORT)
13787
13788/*
13789 * Canonicalize() abstract operation needed for canonicalization of individual
13790 * codepoints during regexp compilation and execution, see E5 Section 15.10.2.8.
13791 * Note that codepoints are canonicalized one character at a time, so no context
13792 * specific rules can apply. Locale specific rules can apply, though.
13793 */
13794
13796#if defined(DUK_USE_REGEXP_CANON_WORKAROUND)
13797 /* Fast canonicalization lookup at the cost of 128kB footprint. */
13798 DUK_ASSERT(cp >= 0);
13799 DUK_UNREF(thr);
13800 if (DUK_LIKELY(cp < 0x10000L)) {
13802 }
13803 return cp;
13804#else /* DUK_USE_REGEXP_CANON_WORKAROUND */
13806
13808 NULL, /* NULL is allowed, no output */
13809 cp, /* curr char */
13810 -1, /* prev char */
13811 -1, /* next char */
13812 1); /* uppercase */
13813
13814 if ((y < 0) || (cp >= 0x80 && y < 0x80)) {
13815 /* multiple codepoint conversion or non-ASCII mapped to ASCII
13816 * --> leave as is.
13817 */
13818 return cp;
13819 }
13820
13821 return y;
13822#endif /* DUK_USE_REGEXP_CANON_WORKAROUND */
13823}
13824
13825/*
13826 * E5 Section 15.10.2.6 "IsWordChar" abstract operation. Assume
13827 * x < 0 for characters read outside the string.
13828 */
13829
13831 /*
13832 * Note: the description in E5 Section 15.10.2.6 has a typo, it
13833 * contains 'A' twice and lacks 'a'; the intent is [0-9a-zA-Z_].
13835 if ((x >= '0' && x <= '9') || (x >= 'a' && x <= 'z') || (x >= 'A' && x <= 'Z') || (x == '_')) {
13836 return 1;
13837 }
13838 return 0;
13839}
13840
13841/*
13842 * Regexp range tables
13843 */
13844
13845/* exposed because lexer needs these too */
13846DUK_INTERNAL const duk_uint16_t duk_unicode_re_ranges_digit[2] = {
13847 (duk_uint16_t) 0x0030UL,
13848 (duk_uint16_t) 0x0039UL,
13850DUK_INTERNAL const duk_uint16_t duk_unicode_re_ranges_white[22] = {
13851 (duk_uint16_t) 0x0009UL, (duk_uint16_t) 0x000DUL, (duk_uint16_t) 0x0020UL, (duk_uint16_t) 0x0020UL, (duk_uint16_t) 0x00A0UL,
13852 (duk_uint16_t) 0x00A0UL, (duk_uint16_t) 0x1680UL, (duk_uint16_t) 0x1680UL, (duk_uint16_t) 0x180EUL, (duk_uint16_t) 0x180EUL,
13853 (duk_uint16_t) 0x2000UL, (duk_uint16_t) 0x200AUL, (duk_uint16_t) 0x2028UL, (duk_uint16_t) 0x2029UL, (duk_uint16_t) 0x202FUL,
13854 (duk_uint16_t) 0x202FUL, (duk_uint16_t) 0x205FUL, (duk_uint16_t) 0x205FUL, (duk_uint16_t) 0x3000UL, (duk_uint16_t) 0x3000UL,
13855 (duk_uint16_t) 0xFEFFUL, (duk_uint16_t) 0xFEFFUL,
13856};
13857DUK_INTERNAL const duk_uint16_t duk_unicode_re_ranges_wordchar[8] = {
13858 (duk_uint16_t) 0x0030UL, (duk_uint16_t) 0x0039UL, (duk_uint16_t) 0x0041UL, (duk_uint16_t) 0x005AUL,
13859 (duk_uint16_t) 0x005FUL, (duk_uint16_t) 0x005FUL, (duk_uint16_t) 0x0061UL, (duk_uint16_t) 0x007AUL,
13860};
13861DUK_INTERNAL const duk_uint16_t duk_unicode_re_ranges_not_digit[4] = {
13862 (duk_uint16_t) 0x0000UL,
13863 (duk_uint16_t) 0x002FUL,
13864 (duk_uint16_t) 0x003AUL,
13865 (duk_uint16_t) 0xFFFFUL,
13866};
13867DUK_INTERNAL const duk_uint16_t duk_unicode_re_ranges_not_white[24] = {
13868 (duk_uint16_t) 0x0000UL, (duk_uint16_t) 0x0008UL, (duk_uint16_t) 0x000EUL, (duk_uint16_t) 0x001FUL, (duk_uint16_t) 0x0021UL,
13869 (duk_uint16_t) 0x009FUL, (duk_uint16_t) 0x00A1UL, (duk_uint16_t) 0x167FUL, (duk_uint16_t) 0x1681UL, (duk_uint16_t) 0x180DUL,
13870 (duk_uint16_t) 0x180FUL, (duk_uint16_t) 0x1FFFUL, (duk_uint16_t) 0x200BUL, (duk_uint16_t) 0x2027UL, (duk_uint16_t) 0x202AUL,
13871 (duk_uint16_t) 0x202EUL, (duk_uint16_t) 0x2030UL, (duk_uint16_t) 0x205EUL, (duk_uint16_t) 0x2060UL, (duk_uint16_t) 0x2FFFUL,
13872 (duk_uint16_t) 0x3001UL, (duk_uint16_t) 0xFEFEUL, (duk_uint16_t) 0xFF00UL, (duk_uint16_t) 0xFFFFUL,
13873};
13874DUK_INTERNAL const duk_uint16_t duk_unicode_re_ranges_not_wordchar[10] = {
13875 (duk_uint16_t) 0x0000UL, (duk_uint16_t) 0x002FUL, (duk_uint16_t) 0x003AUL, (duk_uint16_t) 0x0040UL, (duk_uint16_t) 0x005BUL,
13876 (duk_uint16_t) 0x005EUL, (duk_uint16_t) 0x0060UL, (duk_uint16_t) 0x0060UL, (duk_uint16_t) 0x007BUL, (duk_uint16_t) 0xFFFFUL,
13877};
13878
13879#endif /* DUK_USE_REGEXP_SUPPORT */
13881 * Macro support functions for reading/writing raw data.
13882 *
13883 * These are done using memcpy to ensure they're valid even for unaligned
13884 * reads/writes on platforms where alignment counts. On x86 at least gcc
13885 * is able to compile these into a bswap+mov. "Always inline" is used to
13886 * ensure these macros compile to minimal code.
13888
13889/* #include duk_internal.h -> already included */
13890
13891union duk__u16_union {
13892 duk_uint8_t b[2];
13893 duk_uint16_t x;
13894};
13895typedef union duk__u16_union duk__u16_union;
13896
13897union duk__u32_union {
13898 duk_uint8_t b[4];
13899 duk_uint32_t x;
13900};
13901typedef union duk__u32_union duk__u32_union;
13902
13903#if defined(DUK_USE_64BIT_OPS)
13904union duk__u64_union {
13905 duk_uint8_t b[8];
13906 duk_uint64_t x;
13907};
13908typedef union duk__u64_union duk__u64_union;
13909#endif
13910
13911DUK_INTERNAL DUK_ALWAYS_INLINE duk_uint16_t duk_raw_read_u16_be(const duk_uint8_t *p) {
13913 duk_memcpy((void *) u.b, (const void *) p, (size_t) 2);
13914 u.x = DUK_NTOH16(u.x);
13915 return u.x;
13916}
13917
13918DUK_INTERNAL DUK_ALWAYS_INLINE duk_uint32_t duk_raw_read_u32_be(const duk_uint8_t *p) {
13920 duk_memcpy((void *) u.b, (const void *) p, (size_t) 4);
13921 u.x = DUK_NTOH32(u.x);
13922 return u.x;
13923}
13924
13926 duk_float_union fu;
13927 duk_memcpy((void *) fu.uc, (const void *) p, (size_t) 4);
13929 return fu.f;
13930}
13931
13934 duk_memcpy((void *) du.uc, (const void *) p, (size_t) 8);
13936 return du.d;
13937}
13938
13939DUK_INTERNAL DUK_ALWAYS_INLINE duk_uint16_t duk_raw_readinc_u16_be(const duk_uint8_t **p) {
13940 duk_uint16_t res = duk_raw_read_u16_be(*p);
13941 *p += 2;
13942 return res;
13943}
13944
13945DUK_INTERNAL DUK_ALWAYS_INLINE duk_uint32_t duk_raw_readinc_u32_be(const duk_uint8_t **p) {
13946 duk_uint32_t res = duk_raw_read_u32_be(*p);
13947 *p += 4;
13948 return res;
13949}
13950
13953 *p += 4;
13954 return res;
13955}
13956
13959 *p += 8;
13960 return res;
13961}
13962
13963DUK_INTERNAL DUK_ALWAYS_INLINE void duk_raw_write_u16_be(duk_uint8_t *p, duk_uint16_t val) {
13965 u.x = DUK_HTON16(val);
13966 duk_memcpy((void *) p, (const void *) u.b, (size_t) 2);
13967}
13968
13969DUK_INTERNAL DUK_ALWAYS_INLINE void duk_raw_write_u32_be(duk_uint8_t *p, duk_uint32_t val) {
13971 u.x = DUK_HTON32(val);
13972 duk_memcpy((void *) p, (const void *) u.b, (size_t) 4);
13973}
13974
13976 duk_float_union fu;
13977 fu.f = val;
13979 duk_memcpy((void *) p, (const void *) fu.uc, (size_t) 4);
13980}
13981
13984 du.d = val;
13986 duk_memcpy((void *) p, (const void *) du.uc, (size_t) 8);
13988
13991 return len;
13993
13996 return len;
13998
13999DUK_INTERNAL DUK_ALWAYS_INLINE void duk_raw_writeinc_u16_be(duk_uint8_t **p, duk_uint16_t val) {
14000 duk_raw_write_u16_be(*p, val);
14001 *p += 2;
14003
14004DUK_INTERNAL DUK_ALWAYS_INLINE void duk_raw_writeinc_u32_be(duk_uint8_t **p, duk_uint32_t val) {
14005 duk_raw_write_u32_be(*p, val);
14006 *p += 4;
14008
14010 duk_raw_write_float_be(*p, val);
14011 *p += 4;
14013
14015 duk_raw_write_double_be(*p, val);
14016 *p += 8;
14017}
14018
14019DUK_INTERNAL void duk_raw_writeinc_xutf8(duk_uint8_t **p, duk_ucodepoint_t val) {
14021 *p += len;
14022}
14023
14024DUK_INTERNAL void duk_raw_writeinc_cesu8(duk_uint8_t **p, duk_ucodepoint_t val) {
14026 *p += len;
14028/*
14029 * Misc util stuff.
14030 */
14031
14032/* #include duk_internal.h -> already included */
14033
14034/*
14035 * Lowercase digits for radix values 2 to 36. Also doubles as lowercase
14036 * hex nybble table.
14037 */
14038
14039DUK_INTERNAL const duk_uint8_t duk_lc_digits[36] = {
14045};
14046
14051
14052/*
14053 * Table for hex decoding ASCII hex digits
14054 */
14055
14056DUK_INTERNAL const duk_int8_t duk_hex_dectab[256] = {
14057 /* -1 if invalid */
14058 -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, /* 0x00-0x0f */
14059 -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, /* 0x10-0x1f */
14060 -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, /* 0x20-0x2f */
14061 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, -1, -1, -1, -1, -1, -1, /* 0x30-0x3f */
14062 -1, 10, 11, 12, 13, 14, 15, -1, -1, -1, -1, -1, -1, -1, -1, -1, /* 0x40-0x4f */
14063 -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, /* 0x50-0x5f */
14064 -1, 10, 11, 12, 13, 14, 15, -1, -1, -1, -1, -1, -1, -1, -1, -1, /* 0x60-0x6f */
14065 -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, /* 0x70-0x7f */
14066 -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, /* 0x80-0x8f */
14067 -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, /* 0x90-0x9f */
14068 -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, /* 0xa0-0xaf */
14069 -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, /* 0xb0-0xbf */
14070 -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, /* 0xc0-0xcf */
14071 -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, /* 0xd0-0xdf */
14072 -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, /* 0xe0-0xef */
14073 -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 /* 0xf0-0xff */
14074};
14075
14076#if defined(DUK_USE_HEX_FASTPATH)
14077/* Preshifted << 4. Must use 16-bit entry to allow negative value signaling. */
14078DUK_INTERNAL const duk_int16_t duk_hex_dectab_shift4[256] = {
14079 -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, /* 0x00-0x0f */
14080 -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, /* 0x10-0x1f */
14081 -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, /* 0x20-0x2f */
14082 0x00, 0x10, 0x20, 0x30, 0x40, 0x50, 0x60, 0x70, 0x80, 0x90, -1, -1, -1, -1, -1, -1, /* 0x30-0x3f */
14083 -1, 0xa0, 0xb0, 0xc0, 0xd0, 0xe0, 0xf0, -1, -1, -1, -1, -1, -1, -1, -1, -1, /* 0x40-0x4f */
14084 -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, /* 0x50-0x5f */
14085 -1, 0xa0, 0xb0, 0xc0, 0xd0, 0xe0, 0xf0, -1, -1, -1, -1, -1, -1, -1, -1, -1, /* 0x60-0x6f */
14086 -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, /* 0x70-0x7f */
14087 -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, /* 0x80-0x8f */
14088 -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, /* 0x90-0x9f */
14089 -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, /* 0xa0-0xaf */
14090 -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, /* 0xb0-0xbf */
14091 -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, /* 0xc0-0xcf */
14092 -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, /* 0xd0-0xdf */
14093 -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, /* 0xe0-0xef */
14094 -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 /* 0xf0-0xff */
14095};
14096#endif
14097
14098/*
14099 * Table for hex encoding bytes
14100 */
14101
14102#if defined(DUK_USE_HEX_FASTPATH)
14103/* Lookup to encode one byte directly into 2 characters:
14104 *
14105 * def genhextab(bswap):
14106 * for i in xrange(256):
14107 * t = chr(i).encode('hex')
14108 * if bswap:
14109 * t = t[1] + t[0]
14110 * print('0x' + t.encode('hex') + 'U')
14111 * print('big endian'); genhextab(False)
14112 * print('little endian'); genhextab(True)
14113 */
14114DUK_INTERNAL const duk_uint16_t duk_hex_enctab[256] = {
14115#if defined(DUK_USE_INTEGER_BE)
14116 0x3030U, 0x3031U, 0x3032U, 0x3033U, 0x3034U, 0x3035U, 0x3036U, 0x3037U, 0x3038U, 0x3039U, 0x3061U, 0x3062U, 0x3063U,
14117 0x3064U, 0x3065U, 0x3066U, 0x3130U, 0x3131U, 0x3132U, 0x3133U, 0x3134U, 0x3135U, 0x3136U, 0x3137U, 0x3138U, 0x3139U,
14118 0x3161U, 0x3162U, 0x3163U, 0x3164U, 0x3165U, 0x3166U, 0x3230U, 0x3231U, 0x3232U, 0x3233U, 0x3234U, 0x3235U, 0x3236U,
14119 0x3237U, 0x3238U, 0x3239U, 0x3261U, 0x3262U, 0x3263U, 0x3264U, 0x3265U, 0x3266U, 0x3330U, 0x3331U, 0x3332U, 0x3333U,
14120 0x3334U, 0x3335U, 0x3336U, 0x3337U, 0x3338U, 0x3339U, 0x3361U, 0x3362U, 0x3363U, 0x3364U, 0x3365U, 0x3366U, 0x3430U,
14121 0x3431U, 0x3432U, 0x3433U, 0x3434U, 0x3435U, 0x3436U, 0x3437U, 0x3438U, 0x3439U, 0x3461U, 0x3462U, 0x3463U, 0x3464U,
14122 0x3465U, 0x3466U, 0x3530U, 0x3531U, 0x3532U, 0x3533U, 0x3534U, 0x3535U, 0x3536U, 0x3537U, 0x3538U, 0x3539U, 0x3561U,
14123 0x3562U, 0x3563U, 0x3564U, 0x3565U, 0x3566U, 0x3630U, 0x3631U, 0x3632U, 0x3633U, 0x3634U, 0x3635U, 0x3636U, 0x3637U,
14124 0x3638U, 0x3639U, 0x3661U, 0x3662U, 0x3663U, 0x3664U, 0x3665U, 0x3666U, 0x3730U, 0x3731U, 0x3732U, 0x3733U, 0x3734U,
14125 0x3735U, 0x3736U, 0x3737U, 0x3738U, 0x3739U, 0x3761U, 0x3762U, 0x3763U, 0x3764U, 0x3765U, 0x3766U, 0x3830U, 0x3831U,
14126 0x3832U, 0x3833U, 0x3834U, 0x3835U, 0x3836U, 0x3837U, 0x3838U, 0x3839U, 0x3861U, 0x3862U, 0x3863U, 0x3864U, 0x3865U,
14127 0x3866U, 0x3930U, 0x3931U, 0x3932U, 0x3933U, 0x3934U, 0x3935U, 0x3936U, 0x3937U, 0x3938U, 0x3939U, 0x3961U, 0x3962U,
14128 0x3963U, 0x3964U, 0x3965U, 0x3966U, 0x6130U, 0x6131U, 0x6132U, 0x6133U, 0x6134U, 0x6135U, 0x6136U, 0x6137U, 0x6138U,
14129 0x6139U, 0x6161U, 0x6162U, 0x6163U, 0x6164U, 0x6165U, 0x6166U, 0x6230U, 0x6231U, 0x6232U, 0x6233U, 0x6234U, 0x6235U,
14130 0x6236U, 0x6237U, 0x6238U, 0x6239U, 0x6261U, 0x6262U, 0x6263U, 0x6264U, 0x6265U, 0x6266U, 0x6330U, 0x6331U, 0x6332U,
14131 0x6333U, 0x6334U, 0x6335U, 0x6336U, 0x6337U, 0x6338U, 0x6339U, 0x6361U, 0x6362U, 0x6363U, 0x6364U, 0x6365U, 0x6366U,
14132 0x6430U, 0x6431U, 0x6432U, 0x6433U, 0x6434U, 0x6435U, 0x6436U, 0x6437U, 0x6438U, 0x6439U, 0x6461U, 0x6462U, 0x6463U,
14133 0x6464U, 0x6465U, 0x6466U, 0x6530U, 0x6531U, 0x6532U, 0x6533U, 0x6534U, 0x6535U, 0x6536U, 0x6537U, 0x6538U, 0x6539U,
14134 0x6561U, 0x6562U, 0x6563U, 0x6564U, 0x6565U, 0x6566U, 0x6630U, 0x6631U, 0x6632U, 0x6633U, 0x6634U, 0x6635U, 0x6636U,
14135 0x6637U, 0x6638U, 0x6639U, 0x6661U, 0x6662U, 0x6663U, 0x6664U, 0x6665U, 0x6666U
14136#else /* DUK_USE_INTEGER_BE */
14137 0x3030U, 0x3130U, 0x3230U, 0x3330U, 0x3430U, 0x3530U, 0x3630U, 0x3730U, 0x3830U, 0x3930U, 0x6130U, 0x6230U, 0x6330U,
14138 0x6430U, 0x6530U, 0x6630U, 0x3031U, 0x3131U, 0x3231U, 0x3331U, 0x3431U, 0x3531U, 0x3631U, 0x3731U, 0x3831U, 0x3931U,
14139 0x6131U, 0x6231U, 0x6331U, 0x6431U, 0x6531U, 0x6631U, 0x3032U, 0x3132U, 0x3232U, 0x3332U, 0x3432U, 0x3532U, 0x3632U,
14140 0x3732U, 0x3832U, 0x3932U, 0x6132U, 0x6232U, 0x6332U, 0x6432U, 0x6532U, 0x6632U, 0x3033U, 0x3133U, 0x3233U, 0x3333U,
14141 0x3433U, 0x3533U, 0x3633U, 0x3733U, 0x3833U, 0x3933U, 0x6133U, 0x6233U, 0x6333U, 0x6433U, 0x6533U, 0x6633U, 0x3034U,
14142 0x3134U, 0x3234U, 0x3334U, 0x3434U, 0x3534U, 0x3634U, 0x3734U, 0x3834U, 0x3934U, 0x6134U, 0x6234U, 0x6334U, 0x6434U,
14143 0x6534U, 0x6634U, 0x3035U, 0x3135U, 0x3235U, 0x3335U, 0x3435U, 0x3535U, 0x3635U, 0x3735U, 0x3835U, 0x3935U, 0x6135U,
14144 0x6235U, 0x6335U, 0x6435U, 0x6535U, 0x6635U, 0x3036U, 0x3136U, 0x3236U, 0x3336U, 0x3436U, 0x3536U, 0x3636U, 0x3736U,
14145 0x3836U, 0x3936U, 0x6136U, 0x6236U, 0x6336U, 0x6436U, 0x6536U, 0x6636U, 0x3037U, 0x3137U, 0x3237U, 0x3337U, 0x3437U,
14146 0x3537U, 0x3637U, 0x3737U, 0x3837U, 0x3937U, 0x6137U, 0x6237U, 0x6337U, 0x6437U, 0x6537U, 0x6637U, 0x3038U, 0x3138U,
14147 0x3238U, 0x3338U, 0x3438U, 0x3538U, 0x3638U, 0x3738U, 0x3838U, 0x3938U, 0x6138U, 0x6238U, 0x6338U, 0x6438U, 0x6538U,
14148 0x6638U, 0x3039U, 0x3139U, 0x3239U, 0x3339U, 0x3439U, 0x3539U, 0x3639U, 0x3739U, 0x3839U, 0x3939U, 0x6139U, 0x6239U,
14149 0x6339U, 0x6439U, 0x6539U, 0x6639U, 0x3061U, 0x3161U, 0x3261U, 0x3361U, 0x3461U, 0x3561U, 0x3661U, 0x3761U, 0x3861U,
14150 0x3961U, 0x6161U, 0x6261U, 0x6361U, 0x6461U, 0x6561U, 0x6661U, 0x3062U, 0x3162U, 0x3262U, 0x3362U, 0x3462U, 0x3562U,
14151 0x3662U, 0x3762U, 0x3862U, 0x3962U, 0x6162U, 0x6262U, 0x6362U, 0x6462U, 0x6562U, 0x6662U, 0x3063U, 0x3163U, 0x3263U,
14152 0x3363U, 0x3463U, 0x3563U, 0x3663U, 0x3763U, 0x3863U, 0x3963U, 0x6163U, 0x6263U, 0x6363U, 0x6463U, 0x6563U, 0x6663U,
14153 0x3064U, 0x3164U, 0x3264U, 0x3364U, 0x3464U, 0x3564U, 0x3664U, 0x3764U, 0x3864U, 0x3964U, 0x6164U, 0x6264U, 0x6364U,
14154 0x6464U, 0x6564U, 0x6664U, 0x3065U, 0x3165U, 0x3265U, 0x3365U, 0x3465U, 0x3565U, 0x3665U, 0x3765U, 0x3865U, 0x3965U,
14155 0x6165U, 0x6265U, 0x6365U, 0x6465U, 0x6565U, 0x6665U, 0x3066U, 0x3166U, 0x3266U, 0x3366U, 0x3466U, 0x3566U, 0x3666U,
14156 0x3766U, 0x3866U, 0x3966U, 0x6166U, 0x6266U, 0x6366U, 0x6466U, 0x6566U, 0x6666U
14157#endif /* DUK_USE_INTEGER_BE */
14158};
14159#endif /* DUK_USE_HEX_FASTPATH */
14160
14161/*
14162 * Arbitrary byteswap for potentially unaligned values
14163 *
14164 * Used to byteswap pointers e.g. in debugger code.
14165 */
14166
14167#if defined(DUK_USE_DEBUGGER_SUPPORT) /* For now only needed by the debugger. */
14168DUK_INTERNAL void duk_byteswap_bytes(duk_uint8_t *p, duk_small_uint_t len) {
14169 duk_uint8_t tmp;
14170 duk_uint8_t *q = p + len - 1;
14171
14172 while (p - q < 0) {
14173 tmp = *p;
14174 *p = *q;
14175 *q = tmp;
14176 p++;
14177 q--;
14178 }
14179}
14180#endif
14181
14182/*
14183 * Random
14184 */
14185
14187#if defined(DUK_USE_GET_RANDOM_DOUBLE)
14188 return DUK_USE_GET_RANDOM_DOUBLE(thr->heap->heap_udata);
14189#else
14191#endif
14192}
14193/*
14194 * Hobject ECMAScript [[Class]].
14195 */
14196
14197/* #include duk_internal.h -> already included */
14198
14199#if (DUK_STRIDX_UC_ARGUMENTS > 255)
14200#error constant too large
14201#endif
14202#if (DUK_STRIDX_UC_ARRAY > 255)
14203#error constant too large
14204#endif
14205#if (DUK_STRIDX_UC_BOOLEAN > 255)
14206#error constant too large
14207#endif
14208#if (DUK_STRIDX_UC_DATE > 255)
14209#error constant too large
14210#endif
14211#if (DUK_STRIDX_UC_ERROR > 255)
14212#error constant too large
14213#endif
14214#if (DUK_STRIDX_UC_FUNCTION > 255)
14215#error constant too large
14216#endif
14217#if (DUK_STRIDX_JSON > 255)
14218#error constant too large
14219#endif
14220#if (DUK_STRIDX_MATH > 255)
14221#error constant too large
14222#endif
14223#if (DUK_STRIDX_UC_NUMBER > 255)
14224#error constant too large
14225#endif
14226#if (DUK_STRIDX_UC_OBJECT > 255)
14227#error constant too large
14228#endif
14229#if (DUK_STRIDX_REG_EXP > 255)
14230#error constant too large
14231#endif
14232#if (DUK_STRIDX_UC_STRING > 255)
14233#error constant too large
14234#endif
14235#if (DUK_STRIDX_GLOBAL > 255)
14236#error constant too large
14237#endif
14238#if (DUK_STRIDX_OBJ_ENV > 255)
14239#error constant too large
14240#endif
14241#if (DUK_STRIDX_DEC_ENV > 255)
14242#error constant too large
14243#endif
14244#if (DUK_STRIDX_UC_POINTER > 255)
14245#error constant too large
14246#endif
14247#if (DUK_STRIDX_UC_THREAD > 255)
14248#error constant too large
14249#endif
14250#if (DUK_STRIDX_ARRAY_BUFFER > 255)
14251#error constant too large
14252#endif
14253#if (DUK_STRIDX_DATA_VIEW > 255)
14254#error constant too large
14255#endif
14256#if (DUK_STRIDX_INT8_ARRAY > 255)
14257#error constant too large
14258#endif
14259#if (DUK_STRIDX_UINT8_ARRAY > 255)
14260#error constant too large
14261#endif
14262#if (DUK_STRIDX_UINT8_CLAMPED_ARRAY > 255)
14263#error constant too large
14264#endif
14265#if (DUK_STRIDX_INT16_ARRAY > 255)
14266#error constant too large
14267#endif
14268#if (DUK_STRIDX_UINT16_ARRAY > 255)
14269#error constant too large
14270#endif
14271#if (DUK_STRIDX_INT32_ARRAY > 255)
14272#error constant too large
14273#endif
14274#if (DUK_STRIDX_UINT32_ARRAY > 255)
14275#error constant too large
14276#endif
14277#if (DUK_STRIDX_FLOAT32_ARRAY > 255)
14278#error constant too large
14279#endif
14280#if (DUK_STRIDX_FLOAT64_ARRAY > 255)
14281#error constant too large
14282#endif
14283#if (DUK_STRIDX_EMPTY_STRING > 255)
14284#error constant too large
14285#endif
14286
14287/* Note: assumes that these string indexes are 8-bit, genstrings.py must ensure that */
14288DUK_INTERNAL duk_uint8_t duk_class_number_to_stridx[32] = {
14289 DUK_STRIDX_EMPTY_STRING, /* NONE, intentionally empty */
14319 DUK_STRIDX_EMPTY_STRING, /* UNUSED, intentionally empty */
14320 DUK_STRIDX_EMPTY_STRING, /* UNUSED, intentionally empty */
14321};
14322/*
14323 * Default allocation functions.
14324 *
14325 * Assumes behavior such as malloc allowing zero size, yielding
14326 * a NULL or a unique pointer which is a no-op for free.
14327 */
14329/* #include duk_internal.h -> already included */
14330
14331#if defined(DUK_USE_PROVIDE_DEFAULT_ALLOC_FUNCTIONS)
14332DUK_INTERNAL void *duk_default_alloc_function(void *udata, duk_size_t size) {
14333 void *res;
14334 DUK_UNREF(udata);
14335 res = DUK_ANSI_MALLOC(size);
14336 DUK_DDD(DUK_DDDPRINT("default alloc function: %lu -> %p", (unsigned long) size, (void *) res));
14337 return res;
14338}
14339
14340DUK_INTERNAL void *duk_default_realloc_function(void *udata, void *ptr, duk_size_t newsize) {
14341 void *res;
14342 DUK_UNREF(udata);
14343 res = DUK_ANSI_REALLOC(ptr, newsize);
14344 DUK_DDD(DUK_DDDPRINT("default realloc function: %p %lu -> %p", (void *) ptr, (unsigned long) newsize, (void *) res));
14345 return res;
14346}
14347
14348DUK_INTERNAL void duk_default_free_function(void *udata, void *ptr) {
14349 DUK_DDD(DUK_DDDPRINT("default free function: %p", (void *) ptr));
14350 DUK_UNREF(udata);
14351 DUK_ANSI_FREE(ptr);
14352}
14353#endif /* DUK_USE_PROVIDE_DEFAULT_ALLOC_FUNCTIONS */
14354/*
14355 * Buffer
14356 */
14357
14358/* #include duk_internal.h -> already included */
14359
14362
14364
14365 h = (duk_hbuffer_dynamic *) duk_require_hbuffer(thr, idx);
14366 DUK_ASSERT(h != NULL);
14370 DUK_WO_NORETURN(return NULL;);
14371 }
14372
14373 /* Maximum size check is handled by callee. */
14374 duk_hbuffer_resize(thr, h, new_size);
14375
14376 return DUK_HBUFFER_DYNAMIC_GET_DATA_PTR(thr->heap, h);
14377}
14378
14379DUK_EXTERNAL void *duk_steal_buffer(duk_hthread *thr, duk_idx_t idx, duk_size_t *out_size) {
14381 void *ptr;
14382 duk_size_t sz;
14383
14385
14386 h = (duk_hbuffer_dynamic *) duk_require_hbuffer(thr, idx);
14387 DUK_ASSERT(h != NULL);
14388
14391 DUK_WO_NORETURN(return NULL;);
14392 }
14393
14394 /* Forget the previous allocation, setting size to 0 and alloc to
14395 * NULL. Caller is responsible for freeing the previous allocation.
14396 * Getting the allocation and clearing it is done in the same API
14397 * call to avoid any chance of a realloc.
14401 if (out_size) {
14402 *out_size = sz;
14403 }
14406
14407 return ptr;
14408}
14409
14410DUK_EXTERNAL void duk_config_buffer(duk_hthread *thr, duk_idx_t idx, void *ptr, duk_size_t len) {
14412
14414
14415 h = (duk_hbuffer_external *) duk_require_hbuffer(thr, idx);
14416 DUK_ASSERT(h != NULL);
14417
14418 if (!DUK_HBUFFER_HAS_EXTERNAL(h)) {
14420 DUK_WO_NORETURN(return;);
14421 }
14423
14426}
14427/*
14428 * Bytecode dump/load
14429 *
14430 * The bytecode load primitive is more important performance-wise than the
14431 * dump primitive.
14433 * Unlike most Duktape API calls, bytecode dump/load is not guaranteed to be
14434 * memory safe for invalid arguments - caller beware! There's little point
14435 * in trying to achieve memory safety unless bytecode instructions are also
14436 * validated which is not easy to do with indirect register references etc.
14437 */
14438
14439/* #include duk_internal.h -> already included */
14440
14441#if defined(DUK_USE_BYTECODE_DUMP_SUPPORT)
14442
14443#define DUK__SER_MARKER 0xbf
14444#define DUK__SER_STRING 0x00
14445#define DUK__SER_NUMBER 0x01
14446#define DUK__BYTECODE_INITIAL_ALLOC 256
14447#define DUK__NO_FORMALS 0xffffffffUL
14448
14449/*
14450 * Dump/load helpers, xxx_raw() helpers do no buffer checks
14451 */
14452
14453DUK_LOCAL const duk_uint8_t *duk__load_string_raw(duk_hthread *thr, const duk_uint8_t *p) {
14454 duk_uint32_t len;
14455
14456 len = DUK_RAW_READINC_U32_BE(p);
14457 duk_push_lstring(thr, (const char *) p, len);
14458 p += len;
14459 return p;
14460}
14461
14462DUK_LOCAL const duk_uint8_t *duk__load_buffer_raw(duk_hthread *thr, const duk_uint8_t *p) {
14463 duk_uint32_t len;
14464 duk_uint8_t *buf;
14465
14466 len = DUK_RAW_READINC_U32_BE(p);
14467 buf = (duk_uint8_t *) duk_push_fixed_buffer_nozero(thr, (duk_size_t) len);
14468 DUK_ASSERT(buf != NULL);
14469 duk_memcpy((void *) buf, (const void *) p, (size_t) len);
14470 p += len;
14471 return p;
14472}
14473
14474DUK_LOCAL duk_uint8_t *duk__dump_hstring_raw(duk_uint8_t *p, duk_hstring *h) {
14475 duk_size_t len;
14476 duk_uint32_t tmp32;
14478 DUK_ASSERT(h != NULL);
14479
14480 len = DUK_HSTRING_GET_BYTELEN(h);
14481 DUK_ASSERT(len <= 0xffffffffUL); /* string limits */
14482 tmp32 = (duk_uint32_t) len;
14483 DUK_RAW_WRITEINC_U32_BE(p, tmp32);
14484 duk_memcpy((void *) p, (const void *) DUK_HSTRING_GET_DATA(h), len);
14485 p += len;
14486 return p;
14487}
14488
14489DUK_LOCAL duk_uint8_t *duk__dump_hbuffer_raw(duk_hthread *thr, duk_uint8_t *p, duk_hbuffer *h) {
14490 duk_size_t len;
14491 duk_uint32_t tmp32;
14492
14493 DUK_ASSERT(thr != NULL);
14494 DUK_ASSERT(h != NULL);
14496
14497 len = DUK_HBUFFER_GET_SIZE(h);
14498 DUK_ASSERT(len <= 0xffffffffUL); /* buffer limits */
14499 tmp32 = (duk_uint32_t) len;
14500 DUK_RAW_WRITEINC_U32_BE(p, tmp32);
14501 /* When len == 0, buffer data pointer may be NULL. */
14502 duk_memcpy_unsafe((void *) p, (const void *) DUK_HBUFFER_GET_DATA_PTR(thr->heap, h), len);
14503 p += len;
14504 return p;
14505}
14506
14508 duk_uint8_t *p,
14509 duk_bufwriter_ctx *bw_ctx,
14510 duk_hobject *func,
14511 duk_small_uint_t stridx) {
14512 duk_hstring *h_str;
14513 duk_tval *tv;
14514
14515 tv = duk_hobject_find_entry_tval_ptr_stridx(thr->heap, (duk_hobject *) func, stridx);
14516 if (tv != NULL && DUK_TVAL_IS_STRING(tv)) {
14518 DUK_ASSERT(h_str != NULL);
14519 } else {
14521 DUK_ASSERT(h_str != NULL);
14522 }
14523 DUK_ASSERT(DUK_HSTRING_MAX_BYTELEN <= 0x7fffffffUL); /* ensures no overflow */
14524 p = DUK_BW_ENSURE_RAW(thr, bw_ctx, 4U + DUK_HSTRING_GET_BYTELEN(h_str), p);
14525 p = duk__dump_hstring_raw(p, h_str);
14526 return p;
14527}
14528
14530 duk_uint8_t *p,
14531 duk_bufwriter_ctx *bw_ctx,
14532 duk_hobject *func,
14533 duk_small_uint_t stridx) {
14534 duk_tval *tv;
14535
14536 tv = duk_hobject_find_entry_tval_ptr_stridx(thr->heap, (duk_hobject *) func, stridx);
14537 if (tv != NULL && DUK_TVAL_IS_BUFFER(tv)) {
14538 duk_hbuffer *h_buf;
14540 DUK_ASSERT(h_buf != NULL);
14541 DUK_ASSERT(DUK_HBUFFER_MAX_BYTELEN <= 0x7fffffffUL); /* ensures no overflow */
14542 p = DUK_BW_ENSURE_RAW(thr, bw_ctx, 4U + DUK_HBUFFER_GET_SIZE(h_buf), p);
14543 p = duk__dump_hbuffer_raw(thr, p, h_buf);
14544 } else {
14545 p = DUK_BW_ENSURE_RAW(thr, bw_ctx, 4U, p);
14547 }
14548 return p;
14549}
14550
14552 duk_uint8_t *p,
14553 duk_bufwriter_ctx *bw_ctx,
14554 duk_hobject *func,
14555 duk_small_uint_t stridx,
14556 duk_uint32_t def_value) {
14557 duk_tval *tv;
14558 duk_uint32_t val;
14560 tv = duk_hobject_find_entry_tval_ptr_stridx(thr->heap, (duk_hobject *) func, stridx);
14561 if (tv != NULL && DUK_TVAL_IS_NUMBER(tv)) {
14562 val = (duk_uint32_t) DUK_TVAL_GET_NUMBER(tv);
14563 } else {
14564 val = def_value;
14565 }
14566 p = DUK_BW_ENSURE_RAW(thr, bw_ctx, 4U, p);
14568 return p;
14569}
14570
14571DUK_LOCAL duk_uint8_t *duk__dump_varmap(duk_hthread *thr, duk_uint8_t *p, duk_bufwriter_ctx *bw_ctx, duk_hobject *func) {
14572 duk_hobject *h;
14573
14574 h = duk_hobject_get_varmap(thr, (duk_hobject *) func);
14575 if (h != NULL) {
14577
14578 /* We know _Varmap only has own properties so walk property
14579 * table directly. We also know _Varmap is dense and all
14580 * values are numbers; assert for these. GC and finalizers
14581 * shouldn't affect _Varmap so side effects should be fine.
14582 */
14583 for (i = 0; i < (duk_uint_fast32_t) DUK_HOBJECT_GET_ENEXT(h); i++) {
14584 duk_hstring *key;
14585 duk_tval *tv_val;
14586 duk_uint32_t val;
14587
14588 key = DUK_HOBJECT_E_GET_KEY(thr->heap, h, i);
14589 DUK_ASSERT(key != NULL); /* _Varmap is dense */
14591 tv_val = DUK_HOBJECT_E_GET_VALUE_TVAL_PTR(thr->heap, h, i);
14592 DUK_ASSERT(tv_val != NULL);
14593 DUK_ASSERT(DUK_TVAL_IS_NUMBER(tv_val)); /* known to be number; in fact an integer */
14594#if defined(DUK_USE_FASTINT)
14597 (duk_int64_t) DUK_TVAL_GET_FASTINT_U32(tv_val)); /* known to be 32-bit */
14598 val = DUK_TVAL_GET_FASTINT_U32(tv_val);
14599#else
14600 val = (duk_uint32_t) DUK_TVAL_GET_NUMBER(tv_val);
14601#endif
14603 DUK_ASSERT(DUK_HSTRING_MAX_BYTELEN <= 0x7fffffffUL); /* ensures no overflow */
14604 p = DUK_BW_ENSURE_RAW(thr, bw_ctx, 4U + DUK_HSTRING_GET_BYTELEN(key) + 4U, p);
14605 p = duk__dump_hstring_raw(p, key);
14607 }
14608 }
14609 p = DUK_BW_ENSURE_RAW(thr, bw_ctx, 4U, p);
14610 DUK_RAW_WRITEINC_U32_BE(p, 0); /* end of _Varmap */
14611 return p;
14612}
14613
14614DUK_LOCAL duk_uint8_t *duk__dump_formals(duk_hthread *thr, duk_uint8_t *p, duk_bufwriter_ctx *bw_ctx, duk_hobject *func) {
14615 duk_harray *h;
14616
14617 h = duk_hobject_get_formals(thr, (duk_hobject *) func);
14618 if (h != NULL) {
14619 duk_uint32_t i;
14620
14621 /* Here we rely on _Formals being a dense array containing
14622 * strings. This should be the case unless _Formals has been
14623 * tweaked by the application (which we don't support right
14624 * now).
14625 */
14626
14627 p = DUK_BW_ENSURE_RAW(thr, bw_ctx, 4U, p);
14628 DUK_ASSERT(h->length != DUK__NO_FORMALS); /* limits */
14630
14631 for (i = 0; i < h->length; i++) {
14632 duk_tval *tv_val;
14633 duk_hstring *varname;
14634
14635 tv_val = DUK_HOBJECT_A_GET_VALUE_PTR(thr->heap, (duk_hobject *) h, i);
14636 DUK_ASSERT(tv_val != NULL);
14638
14639 varname = DUK_TVAL_GET_STRING(tv_val);
14640 DUK_ASSERT(varname != NULL);
14641 DUK_ASSERT(DUK_HSTRING_GET_BYTELEN(varname) >= 1);
14642
14643 DUK_ASSERT(DUK_HSTRING_MAX_BYTELEN <= 0x7fffffffUL); /* ensures no overflow */
14644 p = DUK_BW_ENSURE_RAW(thr, bw_ctx, 4U + DUK_HSTRING_GET_BYTELEN(varname), p);
14645 p = duk__dump_hstring_raw(p, varname);
14646 }
14647 } else {
14648 DUK_DD(DUK_DDPRINT("dumping function without _Formals, emit marker to indicate missing _Formals"));
14649 p = DUK_BW_ENSURE_RAW(thr, bw_ctx, 4U, p);
14650 DUK_RAW_WRITEINC_U32_BE(p, DUK__NO_FORMALS); /* marker: no formals */
14651 }
14652 return p;
14653}
14654
14655static duk_uint8_t *duk__dump_func(duk_hthread *thr, duk_hcompfunc *func, duk_bufwriter_ctx *bw_ctx, duk_uint8_t *p) {
14656 duk_tval *tv, *tv_end;
14657 duk_instr_t *ins, *ins_end;
14658 duk_hobject **fn, **fn_end;
14659 duk_hstring *h_str;
14660 duk_uint32_t count_instr;
14661 duk_uint32_t tmp32;
14662 duk_uint16_t tmp16;
14663 duk_double_t d;
14664
14665 DUK_DD(DUK_DDPRINT("dumping function %p to %p: "
14666 "consts=[%p,%p[ (%ld bytes, %ld items), "
14667 "funcs=[%p,%p[ (%ld bytes, %ld items), "
14668 "code=[%p,%p[ (%ld bytes, %ld items)",
14669 (void *) func,
14670 (void *) p,
14671 (void *) DUK_HCOMPFUNC_GET_CONSTS_BASE(thr->heap, func),
14672 (void *) DUK_HCOMPFUNC_GET_CONSTS_END(thr->heap, func),
14673 (long) DUK_HCOMPFUNC_GET_CONSTS_SIZE(thr->heap, func),
14674 (long) DUK_HCOMPFUNC_GET_CONSTS_COUNT(thr->heap, func),
14675 (void *) DUK_HCOMPFUNC_GET_FUNCS_BASE(thr->heap, func),
14676 (void *) DUK_HCOMPFUNC_GET_FUNCS_END(thr->heap, func),
14677 (long) DUK_HCOMPFUNC_GET_FUNCS_SIZE(thr->heap, func),
14678 (long) DUK_HCOMPFUNC_GET_FUNCS_COUNT(thr->heap, func),
14679 (void *) DUK_HCOMPFUNC_GET_CODE_BASE(thr->heap, func),
14680 (void *) DUK_HCOMPFUNC_GET_CODE_END(thr->heap, func),
14681 (long) DUK_HCOMPFUNC_GET_CODE_SIZE(thr->heap, func),
14682 (long) DUK_HCOMPFUNC_GET_CODE_COUNT(thr->heap, func)));
14683
14684 DUK_ASSERT(DUK_USE_ESBC_MAX_BYTES <= 0x7fffffffUL); /* ensures no overflow */
14685 count_instr = (duk_uint32_t) DUK_HCOMPFUNC_GET_CODE_COUNT(thr->heap, func);
14686 p = DUK_BW_ENSURE_RAW(thr, bw_ctx, 3U * 4U + 2U * 2U + 3U * 4U + count_instr * 4U, p);
14687
14688 /* Fixed header info. */
14689 tmp32 = count_instr;
14690 DUK_RAW_WRITEINC_U32_BE(p, tmp32);
14691 tmp32 = (duk_uint32_t) DUK_HCOMPFUNC_GET_CONSTS_COUNT(thr->heap, func);
14692 DUK_RAW_WRITEINC_U32_BE(p, tmp32);
14693 tmp32 = (duk_uint32_t) DUK_HCOMPFUNC_GET_FUNCS_COUNT(thr->heap, func);
14694 DUK_RAW_WRITEINC_U32_BE(p, tmp32);
14695 tmp16 = func->nregs;
14696 DUK_RAW_WRITEINC_U16_BE(p, tmp16);
14697 tmp16 = func->nargs;
14698 DUK_RAW_WRITEINC_U16_BE(p, tmp16);
14699#if defined(DUK_USE_DEBUGGER_SUPPORT)
14700 tmp32 = func->start_line;
14701 DUK_RAW_WRITEINC_U32_BE(p, tmp32);
14702 tmp32 = func->end_line;
14703 DUK_RAW_WRITEINC_U32_BE(p, tmp32);
14704#else
14707#endif
14708 tmp32 = DUK_HEAPHDR_GET_FLAGS((duk_heaphdr *) func); /* masks flags, only duk_hobject flags */
14709 tmp32 &= ~(DUK_HOBJECT_FLAG_HAVE_FINALIZER); /* finalizer flag is lost */
14710 DUK_RAW_WRITEINC_U32_BE(p, tmp32);
14711
14712 /* Bytecode instructions: endian conversion needed unless
14713 * platform is big endian.
14714 */
14715 ins = DUK_HCOMPFUNC_GET_CODE_BASE(thr->heap, func);
14716 ins_end = DUK_HCOMPFUNC_GET_CODE_END(thr->heap, func);
14717 DUK_ASSERT((duk_size_t) (ins_end - ins) == (duk_size_t) count_instr);
14718#if defined(DUK_USE_INTEGER_BE)
14719 duk_memcpy_unsafe((void *) p, (const void *) ins, count_instr * sizeof(duk_instr_t));
14720 p += count_instr * sizeof(duk_instr_t);
14721 DUK_UNREF(ins_end);
14722#else
14723 while (ins != ins_end) {
14724 tmp32 = (duk_uint32_t) (*ins);
14725 DUK_RAW_WRITEINC_U32_BE(p, tmp32);
14726 ins++;
14727 }
14728#endif
14729
14730 /* Constants: variable size encoding. */
14731 tv = DUK_HCOMPFUNC_GET_CONSTS_BASE(thr->heap, func);
14732 tv_end = DUK_HCOMPFUNC_GET_CONSTS_END(thr->heap, func);
14733 while (tv != tv_end) {
14734 /* constants are strings or numbers now */
14736
14737 if (DUK_TVAL_IS_STRING(tv)) {
14738 h_str = DUK_TVAL_GET_STRING(tv);
14739 DUK_ASSERT(h_str != NULL);
14740 DUK_ASSERT(DUK_HSTRING_MAX_BYTELEN <= 0x7fffffffUL); /* ensures no overflow */
14741 p = DUK_BW_ENSURE_RAW(thr, bw_ctx, 1U + 4U + DUK_HSTRING_GET_BYTELEN(h_str), p);
14742 *p++ = DUK__SER_STRING;
14743 p = duk__dump_hstring_raw(p, h_str);
14744 } else {
14746 p = DUK_BW_ENSURE_RAW(thr, bw_ctx, 1U + 8U, p);
14747 *p++ = DUK__SER_NUMBER;
14748 d = DUK_TVAL_GET_NUMBER(tv);
14750 }
14751 tv++;
14752 }
14753
14754 /* Inner functions recursively. */
14755 fn = (duk_hobject **) DUK_HCOMPFUNC_GET_FUNCS_BASE(thr->heap, func);
14756 fn_end = (duk_hobject **) DUK_HCOMPFUNC_GET_FUNCS_END(thr->heap, func);
14757 while (fn != fn_end) {
14758 /* XXX: This causes recursion up to inner function depth
14759 * which is normally not an issue, e.g. mark-and-sweep uses
14760 * a recursion limiter to avoid C stack issues. Avoiding
14761 * this would mean some sort of a work list or just refusing
14762 * to serialize deep functions.
14763 */
14765 p = duk__dump_func(thr, (duk_hcompfunc *) *fn, bw_ctx, p);
14766 fn++;
14767 }
14768
14769 /* Lexenv and varenv are not dumped. */
14770
14771 /* Object extra properties.
14772 *
14773 * There are some difference between function templates and functions.
14774 * For example, function templates don't have .length and nargs is
14775 * normally used to instantiate the functions.
14776 */
14777
14778 p = duk__dump_uint32_prop(thr, p, bw_ctx, (duk_hobject *) func, DUK_STRIDX_LENGTH, (duk_uint32_t) func->nargs);
14779#if defined(DUK_USE_FUNC_NAME_PROPERTY)
14780 p = duk__dump_string_prop(thr, p, bw_ctx, (duk_hobject *) func, DUK_STRIDX_NAME);
14781#endif
14782#if defined(DUK_USE_FUNC_FILENAME_PROPERTY)
14783 p = duk__dump_string_prop(thr, p, bw_ctx, (duk_hobject *) func, DUK_STRIDX_FILE_NAME);
14784#endif
14785#if defined(DUK_USE_PC2LINE)
14786 p = duk__dump_buffer_prop(thr, p, bw_ctx, (duk_hobject *) func, DUK_STRIDX_INT_PC2LINE);
14787#endif
14788 p = duk__dump_varmap(thr, p, bw_ctx, (duk_hobject *) func);
14789 p = duk__dump_formals(thr, p, bw_ctx, (duk_hobject *) func);
14790
14791 DUK_DD(DUK_DDPRINT("serialized function %p -> final pointer %p", (void *) func, (void *) p));
14792
14793 return p;
14795
14796/* Load a function from bytecode. The function object returned here must
14797 * match what is created by duk_js_push_closure() with respect to its flags,
14798 * properties, etc.
14800 * NOTE: there are intentionally no input buffer length / bound checks.
14801 * Adding them would be easy but wouldn't ensure memory safety as untrusted
14802 * or broken bytecode is unsafe during execution unless the opcodes themselves
14803 * are validated (which is quite complex, especially for indirect opcodes).
14804 */
14805
14806#define DUK__ASSERT_LEFT(n) \
14807 do { \
14808 DUK_ASSERT((duk_size_t) (p_end - p) >= (duk_size_t) (n)); \
14809 } while (0)
14810
14811static const duk_uint8_t *duk__load_func(duk_hthread *thr, const duk_uint8_t *p, const duk_uint8_t *p_end) {
14812 duk_hcompfunc *h_fun;
14813 duk_hbuffer *h_data;
14814 duk_size_t data_size;
14815 duk_uint32_t count_instr, count_const, count_funcs;
14816 duk_uint32_t n;
14817 duk_uint32_t tmp32;
14818 duk_small_uint_t const_type;
14819 duk_uint8_t *fun_data;
14820 duk_uint8_t *q;
14821 duk_idx_t idx_base;
14822 duk_tval *tv1;
14823 duk_uarridx_t arr_idx;
14824 duk_uarridx_t arr_limit;
14825 duk_hobject *func_env;
14826 duk_bool_t need_pop;
14827
14828 /* XXX: There's some overlap with duk_js_closure() here, but
14829 * seems difficult to share code. Ensure that the final function
14830 * looks the same as created by duk_js_closure().
14831 */
14832
14833 DUK_ASSERT(thr != NULL);
14834
14835 DUK_DD(DUK_DDPRINT("loading function, p=%p, p_end=%p", (const void *) p, (const void *) p_end));
14836
14837 DUK__ASSERT_LEFT(3 * 4);
14838 count_instr = DUK_RAW_READINC_U32_BE(p);
14839 count_const = DUK_RAW_READINC_U32_BE(p);
14840 count_funcs = DUK_RAW_READINC_U32_BE(p);
14841
14842 data_size = sizeof(duk_tval) * count_const + sizeof(duk_hobject *) * count_funcs + sizeof(duk_instr_t) * count_instr;
14843
14844 DUK_DD(DUK_DDPRINT("instr=%ld, const=%ld, funcs=%ld, data_size=%ld",
14845 (long) count_instr,
14846 (long) count_const,
14847 (long) count_const,
14848 (long) data_size));
14849
14850 /* Value stack is used to ensure reachability of constants and
14851 * inner functions being loaded. Require enough space to handle
14852 * large functions correctly.
14853 */
14854 duk_require_stack(thr, (duk_idx_t) (2 + count_const + count_funcs));
14855 idx_base = duk_get_top(thr);
14856
14857 /* Push function object, init flags etc. This must match
14858 * duk_js_push_closure() quite carefully.
14859 */
14860 h_fun = duk_push_hcompfunc(thr);
14861 DUK_ASSERT(h_fun != NULL);
14863 DUK_ASSERT(DUK_HCOMPFUNC_GET_DATA(thr->heap, h_fun) == NULL);
14864 DUK_ASSERT(DUK_HCOMPFUNC_GET_FUNCS(thr->heap, h_fun) == NULL);
14865 DUK_ASSERT(DUK_HCOMPFUNC_GET_BYTECODE(thr->heap, h_fun) == NULL);
14867
14868 h_fun->nregs = DUK_RAW_READINC_U16_BE(p);
14869 h_fun->nargs = DUK_RAW_READINC_U16_BE(p);
14870#if defined(DUK_USE_DEBUGGER_SUPPORT)
14871 h_fun->start_line = DUK_RAW_READINC_U32_BE(p);
14872 h_fun->end_line = DUK_RAW_READINC_U32_BE(p);
14873#else
14874 p += 8; /* skip line info */
14875#endif
14876
14877 /* duk_hcompfunc flags; quite version specific */
14878 tmp32 = DUK_RAW_READINC_U32_BE(p);
14879 DUK_HEAPHDR_SET_FLAGS((duk_heaphdr *) h_fun, tmp32); /* masks flags to only change duk_hobject flags */
14880
14881 /* standard prototype (no need to set here, already set) */
14883#if 0
14885#endif
14886
14887 /* assert just a few critical flags */
14897
14898 /* Create function 'data' buffer but don't attach it yet. */
14899 fun_data = (duk_uint8_t *) duk_push_fixed_buffer_nozero(thr, data_size);
14900 DUK_ASSERT(fun_data != NULL);
14901
14902 /* Load bytecode instructions. */
14903 DUK_ASSERT(sizeof(duk_instr_t) == 4);
14904 DUK__ASSERT_LEFT(count_instr * sizeof(duk_instr_t));
14905#if defined(DUK_USE_INTEGER_BE)
14906 q = fun_data + sizeof(duk_tval) * count_const + sizeof(duk_hobject *) * count_funcs;
14907 duk_memcpy((void *) q, (const void *) p, sizeof(duk_instr_t) * count_instr);
14908 p += sizeof(duk_instr_t) * count_instr;
14909#else
14910 q = fun_data + sizeof(duk_tval) * count_const + sizeof(duk_hobject *) * count_funcs;
14911 for (n = count_instr; n > 0; n--) {
14912 *((duk_instr_t *) (void *) q) = DUK_RAW_READINC_U32_BE(p);
14913 q += sizeof(duk_instr_t);
14914 }
14915#endif
14916
14917 /* Load constants onto value stack but don't yet copy to buffer. */
14918 for (n = count_const; n > 0; n--) {
14920 const_type = DUK_RAW_READINC_U8(p);
14921 switch (const_type) {
14922 case DUK__SER_STRING: {
14923 p = duk__load_string_raw(thr, p);
14924 break;
14925 }
14926 case DUK__SER_NUMBER: {
14927 /* Important to do a fastint check so that constants are
14928 * properly read back as fastints.
14929 */
14930 duk_tval tv_tmp;
14931 duk_double_t val;
14935 duk_push_tval(thr, &tv_tmp);
14936 break;
14937 }
14938 default: {
14939 goto format_error;
14940 }
14941 }
14942 }
14943
14944 /* Load inner functions to value stack, but don't yet copy to buffer. */
14945 for (n = count_funcs; n > 0; n--) {
14946 p = duk__load_func(thr, p, p_end);
14947 if (p == NULL) {
14948 goto format_error;
14949 }
14950 }
14951
14952 /* With constants and inner functions on value stack, we can now
14953 * atomically finish the function 'data' buffer, bump refcounts,
14954 * etc.
14955 *
14956 * Here we take advantage of the value stack being just a duk_tval
14957 * array: we can just memcpy() the constants as long as we incref
14958 * them afterwards.
14959 */
14960
14961 h_data = (duk_hbuffer *) duk_known_hbuffer(thr, idx_base + 1);
14963 DUK_HCOMPFUNC_SET_DATA(thr->heap, h_fun, h_data);
14964 DUK_HBUFFER_INCREF(thr, h_data);
14965
14966 tv1 = duk_get_tval(thr, idx_base + 2); /* may be NULL if no constants or inner funcs */
14967 DUK_ASSERT((count_const == 0 && count_funcs == 0) || tv1 != NULL);
14968
14969 q = fun_data;
14970 duk_memcpy_unsafe((void *) q, (const void *) tv1, sizeof(duk_tval) * count_const);
14971 for (n = count_const; n > 0; n--) {
14972 DUK_TVAL_INCREF_FAST(thr, (duk_tval *) (void *) q); /* no side effects */
14973 q += sizeof(duk_tval);
14974 }
14975 tv1 += count_const;
14976
14977 DUK_HCOMPFUNC_SET_FUNCS(thr->heap, h_fun, (duk_hobject **) (void *) q);
14978 for (n = count_funcs; n > 0; n--) {
14979 duk_hobject *h_obj;
14980
14982 h_obj = DUK_TVAL_GET_OBJECT(tv1);
14983 DUK_ASSERT(h_obj != NULL);
14984 tv1++;
14985 DUK_HOBJECT_INCREF(thr, h_obj);
14986
14987 *((duk_hobject **) (void *) q) = h_obj;
14988 q += sizeof(duk_hobject *);
14989 }
14990
14991 DUK_HCOMPFUNC_SET_BYTECODE(thr->heap, h_fun, (duk_instr_t *) (void *) q);
14992
14993 /* The function object is now reachable and refcounts are fine,
14994 * so we can pop off all the temporaries.
14995 */
14996 DUK_DDD(DUK_DDDPRINT("function is reachable, reset top; func: %!iT", duk_get_tval(thr, idx_base)));
14997 duk_set_top(thr, idx_base + 1);
14998
14999 /* Setup function properties. */
15000 tmp32 = DUK_RAW_READINC_U32_BE(p);
15001 duk_push_u32(thr, tmp32);
15003
15004#if defined(DUK_USE_FUNC_NAME_PROPERTY)
15005 p = duk__load_string_raw(thr, p); /* -> [ func funcname ] */
15006 func_env = thr->builtins[DUK_BIDX_GLOBAL_ENV];
15007 DUK_ASSERT(func_env != NULL);
15008 need_pop = 0;
15010 /* Original function instance/template had NAMEBINDING.
15011 * Must create a lexical environment on loading to allow
15012 * recursive functions like 'function foo() { foo(); }'.
15013 */
15014 duk_hdecenv *new_env;
15015
15016 new_env =
15018 DUK_ASSERT(new_env != NULL);
15019 DUK_ASSERT(new_env->thread == NULL); /* Closed. */
15020 DUK_ASSERT(new_env->varmap == NULL);
15021 DUK_ASSERT(new_env->regbase_byteoff == 0);
15022 DUK_HDECENV_ASSERT_VALID(new_env);
15023 DUK_ASSERT(DUK_HOBJECT_GET_PROTOTYPE(thr->heap, (duk_hobject *) new_env) == NULL);
15024 DUK_HOBJECT_SET_PROTOTYPE(thr->heap, (duk_hobject *) new_env, func_env);
15025 DUK_HOBJECT_INCREF(thr, func_env);
15026
15027 func_env = (duk_hobject *) new_env;
15028
15029 duk_push_hobject(thr, (duk_hobject *) new_env);
15030
15031 duk_dup_m2(thr); /* -> [ func funcname env funcname ] */
15032 duk_dup(thr, idx_base); /* -> [ func funcname env funcname func ] */
15033 duk_xdef_prop(thr, -3, DUK_PROPDESC_FLAGS_NONE); /* -> [ func funcname env ] */
15034
15035 need_pop = 1; /* Need to pop env, but -after- updating h_fun and increfs. */
15036 }
15037 DUK_ASSERT(func_env != NULL);
15038 DUK_HCOMPFUNC_SET_LEXENV(thr->heap, h_fun, func_env);
15039 DUK_HCOMPFUNC_SET_VARENV(thr->heap, h_fun, func_env);
15040 DUK_HOBJECT_INCREF(thr, func_env);
15041 DUK_HOBJECT_INCREF(thr, func_env);
15042 if (need_pop) {
15043 duk_pop(thr);
15044 }
15046#endif /* DUK_USE_FUNC_NAME_PROPERTY */
15047
15048#if defined(DUK_USE_FUNC_FILENAME_PROPERTY)
15049 p = duk__load_string_raw(thr, p);
15051#endif /* DUK_USE_FUNC_FILENAME_PROPERTY */
15052
15054 /* Restore empty external .prototype only for constructable
15055 * functions. The prototype object should inherit from
15056 * Object.prototype.
15057 */
15058 duk_push_object(thr);
15059 DUK_ASSERT(!duk_is_bare_object(thr, -1));
15060 duk_dup_m2(thr);
15062 -2,
15064 DUK_PROPDESC_FLAGS_WC); /* func.prototype.constructor = func */
15065 duk_compact_m1(thr);
15067 }
15068
15069#if defined(DUK_USE_PC2LINE)
15070 p = duk__load_buffer_raw(thr, p);
15072#endif /* DUK_USE_PC2LINE */
15073
15074 duk_push_bare_object(thr); /* _Varmap */
15075 for (;;) {
15076 /* XXX: awkward */
15077 p = duk__load_string_raw(thr, p);
15078 if (duk_get_length(thr, -1) == 0) {
15079 duk_pop(thr);
15080 break;
15081 }
15082 tmp32 = DUK_RAW_READINC_U32_BE(p);
15083 duk_push_u32(thr, tmp32);
15084 duk_put_prop(thr, -3);
15085 }
15086 duk_compact_m1(thr);
15088
15089 /* _Formals may have been missing in the original function, which is
15090 * handled using a marker length.
15091 */
15092 arr_limit = DUK_RAW_READINC_U32_BE(p);
15093 if (arr_limit != DUK__NO_FORMALS) {
15094 duk_push_bare_array(thr); /* _Formals */
15095 for (arr_idx = 0; arr_idx < arr_limit; arr_idx++) {
15096 p = duk__load_string_raw(thr, p);
15097 duk_put_prop_index(thr, -2, arr_idx);
15098 }
15099 duk_compact_m1(thr);
15101 } else {
15102 DUK_DD(DUK_DDPRINT("no _Formals in dumped function"));
15103 }
15104
15105 /* Return with final function pushed on stack top. */
15106 DUK_DD(DUK_DDPRINT("final loaded function: %!iT", duk_get_tval(thr, -1)));
15107 DUK_ASSERT_TOP(thr, idx_base + 1);
15108 return p;
15109
15110format_error:
15111 return NULL;
15112}
15113
15115 duk_hcompfunc *func;
15116 duk_bufwriter_ctx bw_ctx_alloc;
15117 duk_bufwriter_ctx *bw_ctx = &bw_ctx_alloc;
15118 duk_uint8_t *p;
15119
15121
15122 /* Bound functions don't have all properties so we'd either need to
15123 * lookup the non-bound target function or reject bound functions.
15124 * For now, bound functions are rejected with TypeError.
15125 */
15126 func = duk_require_hcompfunc(thr, -1);
15127 DUK_ASSERT(func != NULL);
15129
15130 /* Estimating the result size beforehand would be costly, so
15131 * start with a reasonable size and extend as needed.
15132 */
15134 p = DUK_BW_GET_PTR(thr, bw_ctx);
15135 *p++ = DUK__SER_MARKER;
15136 p = duk__dump_func(thr, func, bw_ctx, p);
15137 DUK_BW_SET_PTR(thr, bw_ctx, p);
15138 DUK_BW_COMPACT(thr, bw_ctx);
15139
15140 DUK_DD(DUK_DDPRINT("serialized result: %!T", duk_get_tval(thr, -1)));
15141
15142 duk_remove_m2(thr); /* [ ... func buf ] -> [ ... buf ] */
15143}
15144
15146 const duk_uint8_t *p_buf, *p, *p_end;
15147 duk_size_t sz;
15148
15150
15151 p_buf = (duk_uint8_t *) duk_require_buffer(thr, -1, &sz);
15152 DUK_ASSERT(p_buf != NULL);
15153
15154 /* The caller is responsible for being sure that bytecode being loaded
15155 * is valid and trusted. Invalid bytecode can cause memory unsafe
15156 * behavior directly during loading or later during bytecode execution
15157 * (instruction validation would be quite complex to implement).
15158 *
15159 * This signature check is the only sanity check for detecting
15160 * accidental invalid inputs. The initial byte ensures no ordinary
15161 * string or Symbol will be accepted by accident.
15162 */
15163 p = p_buf;
15164 p_end = p_buf + sz;
15165 if (sz < 1 || p[0] != DUK__SER_MARKER) {
15166 goto format_error;
15167 }
15168 p++;
15169
15170 p = duk__load_func(thr, p, p_end);
15171 if (p == NULL) {
15172 goto format_error;
15173 }
15174
15175 duk_remove_m2(thr); /* [ ... buf func ] -> [ ... func ] */
15176 return;
15177
15178format_error:
15180 DUK_WO_NORETURN(return;);
15181}
15182
15183#else /* DUK_USE_BYTECODE_DUMP_SUPPORT */
15184
15188 DUK_WO_NORETURN(return;);
15189}
15190
15194 DUK_WO_NORETURN(return;);
15195}
15196
15197#endif /* DUK_USE_BYTECODE_DUMP_SUPPORT */
15198
15199/* automatic undefs */
15200#undef DUK__ASSERT_LEFT
15201#undef DUK__BYTECODE_INITIAL_ALLOC
15202#undef DUK__NO_FORMALS
15203#undef DUK__SER_MARKER
15204#undef DUK__SER_NUMBER
15205#undef DUK__SER_STRING
15206/*
15207 * Calls.
15208 *
15209 * Protected variants should avoid ever throwing an error. Must be careful
15210 * to catch errors related to value stack manipulation and property lookup,
15211 * not just the call itself.
15212 *
15213 * The only exception is when arguments are insane, e.g. nargs/nrets are out
15214 * of bounds; in such cases an error is thrown for two reasons. First, we
15215 * can't always respect the value stack input/output guarantees in such cases
15216 * so the caller would end up with the value stack in an unexpected state.
15217 * Second, an attempt to create an error might itself fail (although this
15218 * could be avoided by pushing a preallocated object/string or a primitive
15219 * value).
15220 */
15222/* #include duk_internal.h -> already included */
15225 * Helpers
15226 */
15228struct duk__pcall_prop_args {
15232};
15234
15238};
15240
15241struct duk__pcall_args {
15244};
15245typedef struct duk__pcall_args duk__pcall_args;
15246
15247/* Compute and validate idx_func for a certain 'nargs' and 'other'
15248 * parameter count (1 or 2, depending on whether 'this' binding is
15249 * present).
15250 */
15252 duk_idx_t idx_func;
15253
15254 /* XXX: byte arithmetic? */
15255
15256 DUK_ASSERT(other >= 0);
15257
15258 idx_func = duk_get_top(thr) - nargs - other;
15259 if (DUK_UNLIKELY((idx_func | nargs) < 0)) { /* idx_func < 0 || nargs < 0; OR sign bits */
15261 DUK_WO_NORETURN(return 0;);
15262 }
15263 DUK_ASSERT(duk_is_valid_index(thr, idx_func));
15264 return idx_func;
15265}
15266
15267/* Compute idx_func, assume index will be valid. This is a valid assumption
15268 * for protected calls: nargs < 0 is checked explicitly and duk_safe_call()
15269 * validates the argument count.
15270 */
15272 duk_idx_t idx_func;
15273
15274 /* XXX: byte arithmetic? */
15275
15277 DUK_ASSERT(other >= 0);
15278
15279 idx_func = duk_get_top(thr) - nargs - other;
15280 DUK_ASSERT(idx_func >= 0);
15281 DUK_ASSERT(duk_is_valid_index(thr, idx_func));
15282 return idx_func;
15283}
15284
15285/* Prepare value stack for a method call through an object property.
15286 * May currently throw an error e.g. when getting the property.
15287 */
15290 DUK_ASSERT(nargs >= 0);
15291
15292 DUK_DDD(DUK_DDDPRINT("duk__call_prop_prep_stack, normalized_obj_idx=%ld, nargs=%ld, stacktop=%ld",
15293 (long) normalized_obj_idx,
15294 (long) nargs,
15295 (long) duk_get_top(thr)));
15296
15297 /* [... key arg1 ... argN] */
15298
15299 /* duplicate key */
15300 duk_dup(thr, -nargs - 1); /* Note: -nargs alone would fail for nargs == 0, this is OK */
15301 (void) duk_get_prop(thr, normalized_obj_idx);
15302
15303 DUK_DDD(DUK_DDDPRINT("func: %!T", (duk_tval *) duk_get_tval(thr, -1)));
15304
15305#if defined(DUK_USE_VERBOSE_ERRORS)
15306 if (DUK_UNLIKELY(!duk_is_callable(thr, -1))) {
15307 duk_tval *tv_base;
15308 duk_tval *tv_key;
15309
15310 /* tv_targ is passed on stack top (at index -1). */
15311 tv_base = DUK_GET_TVAL_POSIDX(thr, normalized_obj_idx);
15312 tv_key = DUK_GET_TVAL_NEGIDX(thr, -nargs - 2);
15313 DUK_ASSERT(tv_base >= thr->valstack_bottom && tv_base < thr->valstack_top);
15314 DUK_ASSERT(tv_key >= thr->valstack_bottom && tv_key < thr->valstack_top);
15315
15316 duk_call_setup_propcall_error(thr, tv_base, tv_key);
15317 }
15318#endif
15319
15320 /* [... key arg1 ... argN func] */
15321
15322 duk_replace(thr, -nargs - 2);
15323
15324 /* [... func arg1 ... argN] */
15325
15326 duk_dup(thr, normalized_obj_idx);
15327 duk_insert(thr, -nargs - 1);
15328
15329 /* [... func this arg1 ... argN] */
15330}
15331
15334 duk_idx_t idx_func;
15337
15338 idx_func = duk__call_get_idx_func(thr, nargs, 1);
15339 DUK_ASSERT(duk_is_valid_index(thr, idx_func));
15340
15341 duk_insert_undefined(thr, idx_func + 1);
15342
15343 call_flags = 0; /* not protected, respect reclimit, not constructor */
15345}
15346
15349 duk_idx_t idx_func;
15350
15352
15353 idx_func = duk__call_get_idx_func(thr, nargs, 2);
15354 DUK_ASSERT(duk_is_valid_index(thr, idx_func));
15355
15356 call_flags = 0; /* not protected, respect reclimit, not constructor */
15358}
15359
15361 /*
15362 * XXX: if duk_handle_call() took values through indices, this could be
15363 * made much more sensible. However, duk_handle_call() needs to fudge
15364 * the 'this' and 'func' values to handle bound functions, which is now
15365 * done "in-place", so this is not a trivial change.
15366 */
15367
15370 obj_idx = duk_require_normalize_index(thr, obj_idx); /* make absolute */
15371 if (DUK_UNLIKELY(nargs < 0)) {
15373 DUK_WO_NORETURN(return;);
15374 }
15375
15376 duk__call_prop_prep_stack(thr, obj_idx, nargs);
15377
15378 duk_call_method(thr, nargs);
15379}
15380
15381DUK_LOCAL duk_ret_t duk__pcall_raw(duk_hthread *thr, void *udata) {
15382 duk__pcall_args *args;
15383 duk_idx_t idx_func;
15384 duk_int_t ret;
15385
15387 DUK_ASSERT(udata != NULL);
15388
15389 args = (duk__pcall_args *) udata;
15391 DUK_ASSERT(duk_is_valid_index(thr, idx_func));
15392
15393 duk_insert_undefined(thr, idx_func + 1);
15394
15395 ret = duk_handle_call_unprotected(thr, idx_func, args->call_flags);
15396 DUK_ASSERT(ret == 0);
15397 DUK_UNREF(ret);
15398
15399 return 1;
15400}
15401
15403 duk__pcall_args args;
15404
15406
15407 args.nargs = nargs;
15408 if (DUK_UNLIKELY(nargs < 0)) {
15411 }
15412 args.call_flags = 0;
15413
15414 return duk_safe_call(thr, duk__pcall_raw, (void *) &args /*udata*/, nargs + 1 /*nargs*/, 1 /*nrets*/);
15415}
15416
15419 duk_idx_t idx_func;
15420 duk_int_t ret;
15421
15423 DUK_ASSERT(udata != NULL);
15424
15425 args = (duk__pcall_method_args *) udata;
15426
15427 idx_func = duk__call_get_idx_func_unvalidated(thr, args->nargs, 2);
15428 DUK_ASSERT(duk_is_valid_index(thr, idx_func));
15429
15430 ret = duk_handle_call_unprotected(thr, idx_func, args->call_flags);
15431 DUK_ASSERT(ret == 0);
15432 DUK_UNREF(ret);
15433
15434 return 1;
15435}
15436
15439
15441
15442 args.nargs = nargs;
15443 if (DUK_UNLIKELY(nargs < 0)) {
15447 args.call_flags = call_flags;
15448
15449 return duk_safe_call(thr, duk__pcall_method_raw, (void *) &args /*udata*/, nargs + 2 /*nargs*/, 1 /*nrets*/);
15450}
15451
15454
15455 return duk_pcall_method_flags(thr, nargs, 0);
15456}
15457
15460 duk_idx_t obj_idx;
15461 duk_int_t ret;
15462
15464 DUK_ASSERT(udata != NULL);
15466 args = (duk__pcall_prop_args *) udata;
15467
15468 obj_idx = duk_require_normalize_index(thr, args->obj_idx); /* make absolute */
15469 duk__call_prop_prep_stack(thr, obj_idx, args->nargs);
15470
15471 ret = duk_handle_call_unprotected_nargs(thr, args->nargs, args->call_flags);
15472 DUK_ASSERT(ret == 0);
15473 DUK_UNREF(ret);
15474 return 1;
15475}
15476
15479
15482 args.obj_idx = obj_idx;
15483 args.nargs = nargs;
15484 if (DUK_UNLIKELY(nargs < 0)) {
15487 }
15488 args.call_flags = 0;
15489
15490 return duk_safe_call(thr, duk__pcall_prop_raw, (void *) &args /*udata*/, nargs + 1 /*nargs*/, 1 /*nrets*/);
15491}
15492
15494 duk_int_t rc;
15495
15497
15498 /* nargs condition; fail if: top - bottom < nargs
15499 * <=> top < bottom + nargs
15500 * nrets condition; fail if: end - (top - nargs) < nrets
15501 * <=> end - top + nargs < nrets
15502 * <=> end + nargs < top + nrets
15503 */
15504 /* XXX: check for any reserve? */
15505
15506 if (DUK_UNLIKELY((nargs | nrets) < 0 || /* nargs < 0 || nrets < 0; OR sign bits */
15507 thr->valstack_top < thr->valstack_bottom + nargs || /* nargs too large compared to top */
15508 thr->valstack_end + nargs < thr->valstack_top + nrets)) { /* nrets too large compared to reserve */
15509 DUK_D(DUK_DPRINT("not enough stack reserve for safe call or invalid arguments: "
15510 "nargs=%ld < 0 (?), nrets=%ld < 0 (?), top=%ld < bottom=%ld + nargs=%ld (?), "
15511 "end=%ld + nargs=%ld < top=%ld + nrets=%ld (?)",
15512 (long) nargs,
15513 (long) nrets,
15514 (long) (thr->valstack_top - thr->valstack),
15515 (long) (thr->valstack_bottom - thr->valstack),
15516 (long) nargs,
15517 (long) (thr->valstack_end - thr->valstack),
15518 (long) nargs,
15519 (long) (thr->valstack_top - thr->valstack),
15520 (long) nrets));
15523 }
15524
15525 rc = duk_handle_safe_call(thr, /* thread */
15526 func, /* func */
15527 udata, /* udata */
15528 nargs, /* num_stack_args */
15529 nrets); /* num_stack_res */
15530
15531 return rc;
15532}
15533
15535 duk_idx_t idx_func;
15538
15539 idx_func = duk__call_get_idx_func(thr, nargs, 1);
15540 DUK_ASSERT(duk_is_valid_index(thr, idx_func));
15541
15542 duk_push_object(thr); /* default instance; internal proto updated by call handling */
15543 duk_insert(thr, idx_func + 1);
15544
15547
15550
15551 DUK_ASSERT(udata != NULL);
15552 nargs = *((duk_idx_t *) udata);
15553
15554 duk_new(thr, nargs);
15555 return 1;
15556}
15557
15559 duk_int_t rc;
15560
15562
15563 /* For now, just use duk_safe_call() to wrap duk_new(). We can't
15564 * simply use a protected duk_handle_call() because pushing the
15565 * default instance might throw.
15566 */
15567
15568 if (DUK_UNLIKELY(nargs < 0)) {
15571 }
15572
15573 rc = duk_safe_call(thr, duk__pnew_helper, (void *) &nargs /*udata*/, nargs + 1 /*nargs*/, 1 /*nrets*/);
15574 return rc;
15575}
15576
15578 duk_activation *act;
15579
15581
15582 act = thr->callstack_curr;
15583 if (act != NULL) {
15584 return ((act->flags & DUK_ACT_FLAG_CONSTRUCT) != 0 ? 1 : 0);
15585 }
15586 return 0;
15587}
15588
15591
15592 if (!duk_is_constructor_call(thr)) {
15594 DUK_WO_NORETURN(return;);
15595 }
15596}
15597
15599 duk_activation *act;
15600
15601 /* For user code this could just return 1 (strict) always
15602 * because all Duktape/C functions are considered strict,
15603 * and strict is also the default when nothing is running.
15604 * However, Duktape may call this function internally when
15605 * the current activation is an ECMAScript function, so
15606 * this cannot be replaced by a 'return 1' without fixing
15607 * the internal call sites.
15608 */
15609
15611
15612 act = thr->callstack_curr;
15613 if (act != NULL) {
15614 return ((act->flags & DUK_ACT_FLAG_STRICT) != 0 ? 1 : 0);
15615 } else {
15616 /* Strict by default. */
15617 return 1;
15618 }
15619}
15620
15621/*
15622 * Duktape/C function magic
15623 */
15624
15626 duk_activation *act;
15627 duk_hobject *func;
15628
15630
15631 act = thr->callstack_curr;
15632 if (act) {
15633 func = DUK_ACT_GET_FUNC(act);
15634 if (!func) {
15635 duk_tval *tv = &act->tv_func;
15636 duk_small_uint_t lf_flags;
15637 lf_flags = DUK_TVAL_GET_LIGHTFUNC_FLAGS(tv);
15639 }
15640 DUK_ASSERT(func != NULL);
15641
15642 if (DUK_HOBJECT_IS_NATFUNC(func)) {
15643 duk_hnatfunc *nf = (duk_hnatfunc *) func;
15644 return (duk_int_t) nf->magic;
15645 }
15646 }
15647 return 0;
15648}
15649
15651 duk_tval *tv;
15652 duk_hobject *h;
15653
15655
15656 tv = duk_require_tval(thr, idx);
15657 if (DUK_TVAL_IS_OBJECT(tv)) {
15658 h = DUK_TVAL_GET_OBJECT(tv);
15659 DUK_ASSERT(h != NULL);
15660 if (!DUK_HOBJECT_HAS_NATFUNC(h)) {
15661 goto type_error;
15662 }
15663 return (duk_int_t) ((duk_hnatfunc *) h)->magic;
15664 } else if (DUK_TVAL_IS_LIGHTFUNC(tv)) {
15666 return (duk_int_t) DUK_LFUNC_FLAGS_GET_MAGIC(lf_flags);
15667 }
15668
15669 /* fall through */
15670type_error:
15672 DUK_WO_NORETURN(return 0;);
15673}
15674
15676 duk_hnatfunc *nf;
15677
15679
15680 nf = duk_require_hnatfunc(thr, idx);
15681 DUK_ASSERT(nf != NULL);
15682 nf->magic = (duk_int16_t) magic;
15683}
15684
15685/*
15686 * Misc helpers
15687 */
15688
15689/* Resolve a bound function on value stack top to a non-bound target
15690 * (leave other values as is).
15691 */
15693 duk_tval *tv;
15694
15696
15697 tv = DUK_GET_TVAL_NEGIDX(thr, -1);
15698 if (DUK_TVAL_IS_OBJECT(tv)) {
15699 duk_hobject *h;
15700
15701 h = DUK_TVAL_GET_OBJECT(tv);
15702 DUK_ASSERT(h != NULL);
15704 duk_push_tval(thr, &((duk_hboundfunc *) (void *) h)->target);
15705 duk_replace(thr, -2);
15706#if 0
15707 DUK_TVAL_SET_TVAL(tv, &((duk_hboundfunc *) h)->target);
15708 DUK_TVAL_INCREF(thr, tv);
15710#endif
15711 /* Rely on Function.prototype.bind() on never creating a bound
15712 * function whose target is not proper. This is now safe
15713 * because the target is not even an internal property but a
15714 * struct member.
15715 */
15716 DUK_ASSERT(duk_is_lightfunc(thr, -1) || duk_is_callable(thr, -1));
15717 }
15718 }
15719
15720 /* Lightfuncs cannot be bound but are always callable and
15721 * constructable.
15722 */
15723}
15724/*
15725 * Encoding and decoding basic formats: hex, base64.
15726 *
15727 * These are in-place operations which may allow an optimized implementation.
15728 *
15729 * Base-64: https://tools.ietf.org/html/rfc4648#section-4
15730 */
15732/* #include duk_internal.h -> already included */
15733
15734/*
15735 * Misc helpers
15736 */
15737
15738/* Shared handling for encode/decode argument. Fast path handling for
15739 * buffer and string values because they're the most common. In particular,
15740 * avoid creating a temporary string or buffer when possible. Return value
15741 * is guaranteed to be non-NULL, even for zero length input.
15742 */
15743DUK_LOCAL const duk_uint8_t *duk__prep_codec_arg(duk_hthread *thr, duk_idx_t idx, duk_size_t *out_len) {
15744 const void *def_ptr = (const void *) out_len; /* Any non-NULL pointer will do. */
15745 const void *ptr;
15746 duk_bool_t isbuffer;
15747
15748 DUK_ASSERT(out_len != NULL);
15749 DUK_ASSERT(def_ptr != NULL);
15750 DUK_ASSERT(duk_is_valid_index(thr, idx)); /* checked by caller */
15751
15752 ptr = (const void *)
15753 duk_get_buffer_data_raw(thr, idx, out_len, NULL /*def_ptr*/, 0 /*def_size*/, 0 /*throw_flag*/, &isbuffer);
15754 if (isbuffer) {
15755 DUK_ASSERT(ptr != NULL || *out_len == 0U);
15756 if (DUK_UNLIKELY(ptr == NULL)) {
15757 ptr = def_ptr;
15758 }
15759 DUK_ASSERT(ptr != NULL);
15760 } else {
15761 /* For strings a non-NULL pointer is always guaranteed because
15762 * at least a NUL will be present.
15763 */
15764 ptr = (const void *) duk_to_lstring(thr, idx, out_len);
15765 DUK_ASSERT(ptr != NULL);
15766 }
15767 DUK_ASSERT(ptr != NULL);
15768 return (const duk_uint8_t *) ptr;
15769}
15770
15771/*
15772 * Base64
15773 */
15775#if defined(DUK_USE_BASE64_SUPPORT)
15776/* Bytes emitted for number of padding characters in range [0,4]. */
15777DUK_LOCAL const duk_int8_t duk__base64_decode_nequal_step[5] = {
15778 3, /* #### -> 24 bits, emit 3 bytes */
15779 2, /* ###= -> 18 bits, emit 2 bytes */
15780 1, /* ##== -> 12 bits, emit 1 byte */
15781 -1, /* #=== -> 6 bits, error */
15782 0, /* ==== -> 0 bits, emit 0 bytes */
15783};
15784
15785#if defined(DUK_USE_BASE64_FASTPATH)
15786DUK_LOCAL const duk_uint8_t duk__base64_enctab_fast[64] = {
15787 0x41U, 0x42U, 0x43U, 0x44U, 0x45U, 0x46U, 0x47U, 0x48U, 0x49U, 0x4aU, 0x4bU, 0x4cU, 0x4dU, 0x4eU, 0x4fU, 0x50U, /* A...P */
15788 0x51U, 0x52U, 0x53U, 0x54U, 0x55U, 0x56U, 0x57U, 0x58U, 0x59U, 0x5aU, 0x61U, 0x62U, 0x63U, 0x64U, 0x65U, 0x66U, /* Q...f */
15789 0x67U, 0x68U, 0x69U, 0x6aU, 0x6bU, 0x6cU, 0x6dU, 0x6eU, 0x6fU, 0x70U, 0x71U, 0x72U, 0x73U, 0x74U, 0x75U, 0x76U, /* g...v */
15790 0x77U, 0x78U, 0x79U, 0x7aU, 0x30U, 0x31U, 0x32U, 0x33U, 0x34U, 0x35U, 0x36U, 0x37U, 0x38U, 0x39U, 0x2bU, 0x2fU /* w.../ */
15791};
15792#endif /* DUK_USE_BASE64_FASTPATH */
15793
15794#if defined(DUK_USE_BASE64_FASTPATH)
15795/* Decode table for one byte of input:
15796 * -1 = allowed whitespace
15797 * -2 = padding
15798 * -3 = error
15799 * 0...63 decoded bytes
15800 */
15801DUK_LOCAL const duk_int8_t duk__base64_dectab_fast[256] = {
15802 -3, -3, -3, -3, -3, -3, -3, -3, -3, -1, -1, -3, -3, -1, -3, -3, /* 0x00...0x0f */
15803 -3, -3, -3, -3, -3, -3, -3, -3, -3, -3, -3, -3, -3, -3, -3, -3, /* 0x10...0x1f */
15804 -1, -3, -3, -3, -3, -3, -3, -3, -3, -3, -3, 62, -3, -3, -3, 63, /* 0x20...0x2f */
15805 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, -3, -3, -3, -2, -3, -3, /* 0x30...0x3f */
15806 -3, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, /* 0x40...0x4f */
15807 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, -3, -3, -3, -3, -3, /* 0x50...0x5f */
15808 -3, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, /* 0x60...0x6f */
15809 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, -3, -3, -3, -3, -3, /* 0x70...0x7f */
15810 -3, -3, -3, -3, -3, -3, -3, -3, -3, -3, -3, -3, -3, -3, -3, -3, /* 0x80...0x8f */
15811 -3, -3, -3, -3, -3, -3, -3, -3, -3, -3, -3, -3, -3, -3, -3, -3, /* 0x90...0x9f */
15812 -3, -3, -3, -3, -3, -3, -3, -3, -3, -3, -3, -3, -3, -3, -3, -3, /* 0xa0...0xaf */
15813 -3, -3, -3, -3, -3, -3, -3, -3, -3, -3, -3, -3, -3, -3, -3, -3, /* 0xb0...0xbf */
15814 -3, -3, -3, -3, -3, -3, -3, -3, -3, -3, -3, -3, -3, -3, -3, -3, /* 0xc0...0xcf */
15815 -3, -3, -3, -3, -3, -3, -3, -3, -3, -3, -3, -3, -3, -3, -3, -3, /* 0xd0...0xdf */
15816 -3, -3, -3, -3, -3, -3, -3, -3, -3, -3, -3, -3, -3, -3, -3, -3, /* 0xe0...0xef */
15817 -3, -3, -3, -3, -3, -3, -3, -3, -3, -3, -3, -3, -3, -3, -3, -3 /* 0xf0...0xff */
15818};
15819#endif /* DUK_USE_BASE64_FASTPATH */
15820
15821#if defined(DUK_USE_BASE64_FASTPATH)
15822DUK_LOCAL DUK_ALWAYS_INLINE void duk__base64_encode_fast_3(const duk_uint8_t *src, duk_uint8_t *dst) {
15823 duk_uint_t t;
15824
15825 t = (duk_uint_t) src[0];
15826 t = (t << 8) + (duk_uint_t) src[1];
15827 t = (t << 8) + (duk_uint_t) src[2];
15828
15829 dst[0] = duk__base64_enctab_fast[t >> 18];
15830 dst[1] = duk__base64_enctab_fast[(t >> 12) & 0x3fU];
15831 dst[2] = duk__base64_enctab_fast[(t >> 6) & 0x3fU];
15832 dst[3] = duk__base64_enctab_fast[t & 0x3fU];
15833
15834#if 0
15835 /* Tested: not faster on x64, most likely due to aliasing between
15836 * output and input index computation.
15837 */
15838 /* aaaaaabb bbbbcccc ccdddddd */
15839 dst[0] = duk__base64_enctab_fast[(src[0] >> 2) & 0x3fU];
15840 dst[1] = duk__base64_enctab_fast[((src[0] << 4) & 0x30U) | ((src[1] >> 4) & 0x0fU)];
15841 dst[2] = duk__base64_enctab_fast[((src[1] << 2) & 0x3fU) | ((src[2] >> 6) & 0x03U)];
15842 dst[3] = duk__base64_enctab_fast[src[2] & 0x3fU];
15843#endif
15844}
15846DUK_LOCAL DUK_ALWAYS_INLINE void duk__base64_encode_fast_2(const duk_uint8_t *src, duk_uint8_t *dst) {
15847 duk_uint_t t;
15848
15849 t = (duk_uint_t) src[0];
15850 t = (t << 8) + (duk_uint_t) src[1];
15851 dst[0] = duk__base64_enctab_fast[t >> 10]; /* XXXXXX-- -------- */
15852 dst[1] = duk__base64_enctab_fast[(t >> 4) & 0x3fU]; /* ------XX XXXX---- */
15853 dst[2] = duk__base64_enctab_fast[(t << 2) & 0x3fU]; /* -------- ----XXXX */
15854 dst[3] = DUK_ASC_EQUALS;
15856
15857DUK_LOCAL DUK_ALWAYS_INLINE void duk__base64_encode_fast_1(const duk_uint8_t *src, duk_uint8_t *dst) {
15858 duk_uint_t t;
15859
15860 t = (duk_uint_t) src[0];
15861 dst[0] = duk__base64_enctab_fast[t >> 2]; /* XXXXXX-- */
15862 dst[1] = duk__base64_enctab_fast[(t << 4) & 0x3fU]; /* ------XX */
15863 dst[2] = DUK_ASC_EQUALS;
15864 dst[3] = DUK_ASC_EQUALS;
15865}
15866
15867DUK_LOCAL void duk__base64_encode_helper(const duk_uint8_t *src, duk_size_t srclen, duk_uint8_t *dst) {
15868 duk_size_t n;
15869 const duk_uint8_t *p;
15870 duk_uint8_t *q;
15871
15872 n = srclen;
15873 p = src;
15874 q = dst;
15875
15876 if (n >= 16U) {
15877 /* Fast path, unrolled by 4, allows interleaving. Process
15878 * 12-byte input chunks which encode to 16-char output chunks.
15879 * Only enter when at least one block is emitted (avoids div+mul
15880 * for short inputs too).
15881 */
15882 const duk_uint8_t *p_end_fast;
15883
15884 p_end_fast = p + ((n / 12U) * 12U);
15885 DUK_ASSERT(p_end_fast >= p + 12);
15886 do {
15888 duk__base64_encode_fast_3(p + 3, q + 4);
15889 duk__base64_encode_fast_3(p + 6, q + 8);
15890 duk__base64_encode_fast_3(p + 9, q + 12);
15891 p += 12;
15892 q += 16;
15893 } while (DUK_LIKELY(p != p_end_fast));
15894
15895 DUK_ASSERT(src + srclen >= p);
15896 n = (duk_size_t) (src + srclen - p);
15897 DUK_ASSERT(n < 12U);
15898 }
15899
15900 /* Remainder. */
15901 while (n >= 3U) {
15903 p += 3;
15904 q += 4;
15905 n -= 3U;
15906 }
15907 DUK_ASSERT(n == 0U || n == 1U || n == 2U);
15908 if (n == 1U) {
15910#if 0 /* Unnecessary. */
15911 p += 1;
15912 q += 4;
15913 n -= 1U;
15914#endif
15915 } else if (n == 2U) {
15917#if 0 /* Unnecessary. */
15918 p += 2;
15919 q += 4;
15920 n -= 2U;
15921#endif
15922 } else {
15923 DUK_ASSERT(n == 0U); /* nothing to do */
15924 ;
15925 }
15926}
15927#else /* DUK_USE_BASE64_FASTPATH */
15928DUK_LOCAL void duk__base64_encode_helper(const duk_uint8_t *src, duk_size_t srclen, duk_uint8_t *dst) {
15929 duk_small_uint_t i, npad;
15930 duk_uint_t t, x, y;
15931 const duk_uint8_t *p;
15932 const duk_uint8_t *p_end;
15933 duk_uint8_t *q;
15934
15935 p = src;
15936 p_end = src + srclen;
15937 q = dst;
15938 npad = 0U;
15939
15940 while (p < p_end) {
15941 /* Read 3 bytes into 't', padded by zero. */
15942 t = 0;
15943 for (i = 0; i < 3; i++) {
15944 t = t << 8;
15945 if (p < p_end) {
15946 t += (duk_uint_t) (*p++);
15947 } else {
15948 /* This only happens on the last loop and we're
15949 * guaranteed to exit on the next loop.
15950 */
15951 npad++;
15952 }
15953 }
15954 DUK_ASSERT(npad <= 2U);
15955
15956 /* Emit 4 encoded characters. If npad > 0, some of the
15957 * chars will be incorrect (zero bits) but we fix up the
15958 * padding after the loop. A straightforward 64-byte
15959 * lookup would be faster and cleaner, but this is shorter.
15960 */
15961 for (i = 0; i < 4; i++) {
15962 x = ((t >> 18) & 0x3fU);
15963 t = t << 6;
15964
15965 if (x <= 51U) {
15966 if (x <= 25) {
15967 y = x + DUK_ASC_UC_A;
15968 } else {
15969 y = x - 26 + DUK_ASC_LC_A;
15970 }
15971 } else {
15972 if (x <= 61U) {
15973 y = x - 52 + DUK_ASC_0;
15974 } else if (x == 62) {
15975 y = DUK_ASC_PLUS;
15976 } else {
15977 DUK_ASSERT(x == 63);
15978 y = DUK_ASC_SLASH;
15979 }
15980 }
15981
15982 *q++ = (duk_uint8_t) y;
15983 }
15984 }
15985
15986 /* Handle padding by rewriting 0-2 bogus characters at the end.
15987 *
15988 * Missing bytes npad base64 example
15989 * 0 0 ####
15990 * 1 1 ###=
15991 * 2 2 ##==
15992 */
15993 DUK_ASSERT(npad <= 2U);
15994 while (npad > 0U) {
15995 *(q - npad) = DUK_ASC_EQUALS;
15996 npad--;
15997 }
15998}
15999#endif /* DUK_USE_BASE64_FASTPATH */
16000
16001#if defined(DUK_USE_BASE64_FASTPATH)
16002DUK_LOCAL duk_bool_t duk__base64_decode_helper(const duk_uint8_t *src,
16003 duk_size_t srclen,
16004 duk_uint8_t *dst,
16005 duk_uint8_t **out_dst_final) {
16006 duk_int_t x;
16007 duk_uint_t t;
16008 duk_small_uint_t n_equal;
16009 duk_int8_t step;
16010 const duk_uint8_t *p;
16011 const duk_uint8_t *p_end;
16012 const duk_uint8_t *p_end_safe;
16013 duk_uint8_t *q;
16014
16015 DUK_ASSERT(src != NULL); /* Required by pointer arithmetic below, which fails for NULL. */
16016
16017 p = src;
16018 p_end = src + srclen;
16019 p_end_safe = p_end - 8; /* If 'src <= src_end_safe', safe to read 8 bytes. */
16020 q = dst;
16021
16022 /* Alternate between a fast path which processes clean groups with no
16023 * padding or whitespace, and a slow path which processes one arbitrary
16024 * group and then re-enters the fast path. This handles e.g. base64
16025 * with newlines reasonably well because the majority of a line is in
16026 * the fast path.
16027 */
16028 for (;;) {
16029 /* Fast path, on each loop handle two 4-char input groups.
16030 * If both are clean, emit 6 bytes and continue. If first
16031 * is clean, emit 3 bytes and drop out; otherwise emit
16032 * nothing and drop out. This approach could be extended to
16033 * more groups per loop, but for inputs with e.g. periodic
16034 * newlines (which are common) it might not be an improvement.
16035 */
16036 while (DUK_LIKELY(p <= p_end_safe)) {
16037 duk_int_t t1, t2;
16038
16039 /* The lookup byte is intentionally sign extended to
16040 * (at least) 32 bits and then ORed. This ensures
16041 * that is at least 1 byte is negative, the highest
16042 * bit of the accumulator will be set at the end and
16043 * we don't need to check every byte.
16044 *
16045 * Read all input bytes first before writing output
16046 * bytes to minimize aliasing.
16047 */
16048 DUK_DDD(DUK_DDDPRINT("fast loop: p=%p, p_end_safe=%p, p_end=%p",
16049 (const void *) p,
16050 (const void *) p_end_safe,
16051 (const void *) p_end));
16052
16054 t1 = (duk_int_t) ((duk_uint_t) t1 << 6) | (duk_int_t) duk__base64_dectab_fast[p[1]];
16055 t1 = (duk_int_t) ((duk_uint_t) t1 << 6) | (duk_int_t) duk__base64_dectab_fast[p[2]];
16056 t1 = (duk_int_t) ((duk_uint_t) t1 << 6) | (duk_int_t) duk__base64_dectab_fast[p[3]];
16057
16059 t2 = (duk_int_t) ((duk_uint_t) t2 << 6) | (duk_int_t) duk__base64_dectab_fast[p[5]];
16060 t2 = (duk_int_t) ((duk_uint_t) t2 << 6) | (duk_int_t) duk__base64_dectab_fast[p[6]];
16061 t2 = (duk_int_t) ((duk_uint_t) t2 << 6) | (duk_int_t) duk__base64_dectab_fast[p[7]];
16062
16063 q[0] = (duk_uint8_t) (((duk_uint_t) t1 >> 16) & 0xffU);
16064 q[1] = (duk_uint8_t) (((duk_uint_t) t1 >> 8) & 0xffU);
16065 q[2] = (duk_uint8_t) ((duk_uint_t) t1 & 0xffU);
16066
16067 q[3] = (duk_uint8_t) (((duk_uint_t) t2 >> 16) & 0xffU);
16068 q[4] = (duk_uint8_t) (((duk_uint_t) t2 >> 8) & 0xffU);
16069 q[5] = (duk_uint8_t) ((duk_uint_t) t2 & 0xffU);
16070
16071 /* Optimistic check using one branch. */
16072 if (DUK_LIKELY((t1 | t2) >= 0)) {
16073 p += 8;
16074 q += 6;
16075 } else if (t1 >= 0) {
16076 DUK_DDD(
16077 DUK_DDDPRINT("fast loop first group was clean, second was not, process one slow path group"));
16078 DUK_ASSERT(t2 < 0);
16079 p += 4;
16080 q += 3;
16081 break;
16082 } else {
16084 "fast loop first group was not clean, second does not matter, process one slow path group"));
16085 DUK_ASSERT(t1 < 0);
16086 break;
16087 }
16088 } /* fast path */
16089
16090 /* Slow path step 1: try to scan a 4-character encoded group,
16091 * end-of-input, or start-of-padding. We exit with:
16092 * 1. n_chars == 4: full group, no padding, no end-of-input.
16093 * 2. n_chars < 4: partial group (may also be 0), encountered
16094 * padding or end of input.
16095 *
16096 * The accumulator is initialized to 1; this allows us to detect
16097 * a full group by comparing >= 0x1000000 without an extra
16098 * counter variable.
16099 */
16100 t = 1UL;
16101 for (;;) {
16102 DUK_DDD(DUK_DDDPRINT("slow loop: p=%p, p_end=%p, t=%lu",
16103 (const void *) p,
16104 (const void *) p_end,
16105 (unsigned long) t));
16106
16107 if (DUK_LIKELY(p < p_end)) {
16108 x = duk__base64_dectab_fast[*p++];
16109 if (DUK_LIKELY(x >= 0)) {
16110 DUK_ASSERT(x >= 0 && x <= 63);
16111 t = (t << 6) + (duk_uint_t) x;
16112 if (t >= 0x1000000UL) {
16113 break;
16114 }
16115 } else if (x == -1) {
16116 continue; /* allowed ascii whitespace */
16117 } else if (x == -2) {
16118 p--;
16119 break; /* start of padding */
16120 } else {
16121 DUK_ASSERT(x == -3);
16122 goto decode_error;
16123 }
16124 } else {
16125 break; /* end of input */
16126 }
16127 } /* slow path step 1 */
16128
16129 /* Complete the padding by simulating pad characters,
16130 * regardless of actual input padding chars.
16131 */
16132 n_equal = 0;
16133 while (t < 0x1000000UL) {
16134 t = (t << 6) + 0U;
16135 n_equal++;
16136 }
16137
16138 /* Slow path step 2: deal with full/partial group, padding,
16139 * etc. Note that for num chars in [0,3] we intentionally emit
16140 * 3 bytes but don't step forward that much, buffer space is
16141 * guaranteed in setup.
16142 *
16143 * num chars:
16144 * 0 #### no output (= step 0)
16145 * 1 #=== reject, 6 bits of data
16146 * 2 ##== 12 bits of data, output 1 byte (= step 1)
16147 * 3 ###= 18 bits of data, output 2 bytes (= step 2)
16148 * 4 #### 24 bits of data, output 3 bytes (= step 3)
16149 */
16150 q[0] = (duk_uint8_t) ((t >> 16) & 0xffU);
16151 q[1] = (duk_uint8_t) ((t >> 8) & 0xffU);
16152 q[2] = (duk_uint8_t) (t & 0xffU);
16153
16154 DUK_ASSERT(n_equal <= 4);
16155 step = duk__base64_decode_nequal_step[n_equal];
16156 if (DUK_UNLIKELY(step < 0)) {
16157 goto decode_error;
16158 }
16159 q += step;
16160
16161 /* Slow path step 3: read and ignore padding and whitespace
16162 * until (a) next non-padding and non-whitespace character
16163 * after which we resume the fast path, or (b) end of input.
16164 * This allows us to accept missing, partial, full, and extra
16165 * padding cases uniformly. We also support concatenated
16166 * base-64 documents because we resume scanning afterwards.
16167 *
16168 * Note that to support concatenated documents well, the '='
16169 * padding found inside the input must also allow for 'extra'
16170 * padding. For example, 'Zm===' decodes to 'f' and has one
16171 * extra padding char. So, 'Zm===Zm' should decode 'ff', even
16172 * though the standard break-up would be 'Zm==' + '=Zm' which
16173 * doesn't make sense.
16174 *
16175 * We also accept prepended padding like '==Zm9', because it
16176 * is equivalent to an empty document with extra padding ('==')
16177 * followed by a valid document.
16178 */
16179
16180 for (;;) {
16181 if (DUK_UNLIKELY(p >= p_end)) {
16182 goto done;
16183 }
16184 x = duk__base64_dectab_fast[*p++];
16185 if (x == -1 || x == -2) {
16186 ; /* padding or whitespace, keep eating */
16187 } else {
16188 p--;
16189 break; /* backtrack and go back to fast path, even for -1 */
16190 }
16191 } /* slow path step 3 */
16192 } /* outer fast+slow path loop */
16193
16194done:
16195 DUK_DDD(DUK_DDDPRINT("done; p=%p, p_end=%p", (const void *) p, (const void *) p_end));
16196
16197 DUK_ASSERT(p == p_end);
16198
16199 *out_dst_final = q;
16200 return 1;
16201
16202decode_error:
16203 return 0;
16204}
16205#else /* DUK_USE_BASE64_FASTPATH */
16206DUK_LOCAL duk_bool_t duk__base64_decode_helper(const duk_uint8_t *src,
16207 duk_size_t srclen,
16208 duk_uint8_t *dst,
16209 duk_uint8_t **out_dst_final) {
16210 duk_uint_t t, x;
16211 duk_int_t y;
16212 duk_int8_t step;
16213 const duk_uint8_t *p;
16214 const duk_uint8_t *p_end;
16215 duk_uint8_t *q;
16216 /* 0x09, 0x0a, or 0x0d */
16217 duk_uint32_t mask_white = (1U << 9) | (1U << 10) | (1U << 13);
16218
16219 /* 't' tracks progress of the decoded group:
16220 *
16221 * t == 1 no valid chars yet
16222 * t >= 0x40 1x6 = 6 bits shifted in
16223 * t >= 0x1000 2x6 = 12 bits shifted in
16224 * t >= 0x40000 3x6 = 18 bits shifted in
16225 * t >= 0x1000000 4x6 = 24 bits shifted in
16226 *
16227 * By initializing t=1 there's no need for a separate counter for
16228 * the number of characters found so far.
16229 */
16230 p = src;
16231 p_end = src + srclen;
16232 q = dst;
16233 t = 1UL;
16234
16235 for (;;) {
16236 duk_small_uint_t n_equal;
16237
16238 DUK_ASSERT(t >= 1U);
16239 if (p >= p_end) {
16240 /* End of input: if input exists, treat like
16241 * start of padding, finish the block, then
16242 * re-enter here to see we're done.
16243 */
16244 if (t == 1U) {
16245 break;
16246 } else {
16247 goto simulate_padding;
16248 }
16249 }
16250
16251 x = *p++;
16252
16253 if (x >= 0x41U) {
16254 /* Valid: a-z and A-Z. */
16255 DUK_ASSERT(x >= 0x41U && x <= 0xffU);
16256 if (x >= 0x61U && x <= 0x7aU) {
16257 y = (duk_int_t) x - 0x61 + 26;
16258 } else if (x <= 0x5aU) {
16259 y = (duk_int_t) x - 0x41;
16260 } else {
16261 goto decode_error;
16262 }
16263 } else if (x >= 0x30U) {
16264 /* Valid: 0-9 and =. */
16265 DUK_ASSERT(x >= 0x30U && x <= 0x40U);
16266 if (x <= 0x39U) {
16267 y = (duk_int_t) x - 0x30 + 52;
16268 } else if (x == 0x3dU) {
16269 /* Skip padding and whitespace unless we're in the
16270 * middle of a block. Otherwise complete group by
16271 * simulating shifting in the correct padding.
16272 */
16273 if (t == 1U) {
16274 continue;
16275 }
16276 goto simulate_padding;
16277 } else {
16278 goto decode_error;
16279 }
16280 } else if (x >= 0x20U) {
16281 /* Valid: +, /, and 0x20 whitespace. */
16282 DUK_ASSERT(x >= 0x20U && x <= 0x2fU);
16283 if (x == 0x2bU) {
16284 y = 62;
16285 } else if (x == 0x2fU) {
16286 y = 63;
16287 } else if (x == 0x20U) {
16288 continue;
16289 } else {
16290 goto decode_error;
16291 }
16292 } else {
16293 /* Valid: whitespace. */
16294 duk_uint32_t m;
16295 DUK_ASSERT(x < 0x20U); /* 0x00 to 0x1f */
16296 m = (1U << x);
16297 if (mask_white & m) {
16298 /* Allow basic ASCII whitespace. */
16299 continue;
16300 } else {
16301 goto decode_error;
16302 }
16303 }
16304
16305 DUK_ASSERT(y >= 0 && y <= 63);
16306 t = (t << 6) + (duk_uint_t) y;
16307 if (t < 0x1000000UL) {
16308 continue;
16309 }
16310 /* fall through; no padding will be added */
16311
16312 simulate_padding:
16313 n_equal = 0;
16314 while (t < 0x1000000UL) {
16315 t = (t << 6) + 0U;
16316 n_equal++;
16317 }
16318
16319 /* Output 3 bytes from 't' and advance as needed. */
16320 q[0] = (duk_uint8_t) ((t >> 16) & 0xffU);
16321 q[1] = (duk_uint8_t) ((t >> 8) & 0xffU);
16322 q[2] = (duk_uint8_t) (t & 0xffU);
16323
16324 DUK_ASSERT(n_equal <= 4U);
16325 step = duk__base64_decode_nequal_step[n_equal];
16326 if (step < 0) {
16327 goto decode_error;
16328 }
16329 q += step;
16330
16331 /* Re-enter loop. The actual padding characters are skipped
16332 * by the main loop. This handles cases like missing, partial,
16333 * full, and extra padding, and allows parsing of concatenated
16334 * documents (with extra padding) like: Zm===Zm. Also extra
16335 * prepended padding is accepted: ===Zm9v.
16336 */
16337 t = 1U;
16338 }
16339 DUK_ASSERT(t == 1UL);
16340
16341 *out_dst_final = q;
16342 return 1;
16343
16344decode_error:
16345 return 0;
16346}
16347#endif /* DUK_USE_BASE64_FASTPATH */
16348
16349DUK_EXTERNAL const char *duk_base64_encode(duk_hthread *thr, duk_idx_t idx) {
16350 const duk_uint8_t *src;
16351 duk_size_t srclen;
16352 duk_size_t dstlen;
16353 duk_uint8_t *dst;
16354 const char *ret;
16355
16357
16358 idx = duk_require_normalize_index(thr, idx);
16359 src = duk__prep_codec_arg(thr, idx, &srclen);
16360 DUK_ASSERT(src != NULL);
16361
16362 /* Compute exact output length. Computation must not wrap; this
16363 * limit works for 32-bit size_t:
16364 * >>> srclen = 3221225469
16365 * >>> '%x' % ((srclen + 2) / 3 * 4)
16366 * 'fffffffc'
16367 */
16368 if (srclen > 3221225469UL) {
16369 goto type_error;
16370 }
16371 dstlen = (srclen + 2U) / 3U * 4U;
16372 dst = (duk_uint8_t *) duk_push_fixed_buffer_nozero(thr, dstlen);
16374 duk__base64_encode_helper((const duk_uint8_t *) src, srclen, dst);
16375
16376 ret = duk_buffer_to_string(thr, -1); /* Safe, result is ASCII. */
16377 duk_replace(thr, idx);
16378 return ret;
16379
16380type_error:
16382 DUK_WO_NORETURN(return NULL;);
16383}
16384
16386 const duk_uint8_t *src;
16387 duk_size_t srclen;
16388 duk_size_t dstlen;
16389 duk_uint8_t *dst;
16390 duk_uint8_t *dst_final;
16391
16393
16394 idx = duk_require_normalize_index(thr, idx);
16395 src = duk__prep_codec_arg(thr, idx, &srclen);
16396 DUK_ASSERT(src != NULL);
16397
16398 /* Round up and add safety margin. Avoid addition before division to
16399 * avoid possibility of wrapping. Margin includes +3 for rounding up,
16400 * and +3 for one extra group: the decoder may emit and then backtrack
16401 * a full group (3 bytes) from zero-sized input for technical reasons.
16402 * Similarly, 'xx' may ecause 1+3 = bytes to be emitted and then
16403 * backtracked.
16404 */
16405 dstlen = (srclen / 4) * 3 + 6; /* upper limit, assuming no whitespace etc */
16406 dst = (duk_uint8_t *) duk_push_dynamic_buffer(thr, dstlen);
16407 /* Note: for dstlen=0, dst may be NULL */
16408
16409 if (!duk__base64_decode_helper((const duk_uint8_t *) src, srclen, dst, &dst_final)) {
16410 goto type_error;
16411 }
16412
16413 /* XXX: convert to fixed buffer? */
16414 (void) duk_resize_buffer(thr, -1, (duk_size_t) (dst_final - dst));
16415 duk_replace(thr, idx);
16416 return;
16417
16418type_error:
16420 DUK_WO_NORETURN(return;);
16421}
16422#else /* DUK_USE_BASE64_SUPPORT */
16423DUK_EXTERNAL const char *duk_base64_encode(duk_hthread *thr, duk_idx_t idx) {
16424 DUK_UNREF(idx);
16426 DUK_WO_NORETURN(return NULL;);
16427}
16428
16430 DUK_UNREF(idx);
16432 DUK_WO_NORETURN(return;);
16433}
16434#endif /* DUK_USE_BASE64_SUPPORT */
16435
16436/*
16437 * Hex
16438 */
16439
16440#if defined(DUK_USE_HEX_SUPPORT)
16441DUK_EXTERNAL const char *duk_hex_encode(duk_hthread *thr, duk_idx_t idx) {
16442 const duk_uint8_t *inp;
16443 duk_size_t len;
16444 duk_size_t i;
16445 duk_uint8_t *buf;
16446 const char *ret;
16447#if defined(DUK_USE_HEX_FASTPATH)
16448 duk_size_t len_safe;
16449 duk_uint16_t *p16;
16450#endif
16451
16453
16454 idx = duk_require_normalize_index(thr, idx);
16455 inp = duk__prep_codec_arg(thr, idx, &len);
16456 DUK_ASSERT(inp != NULL);
16457
16458 /* Fixed buffer, no zeroing because we'll fill all the data. */
16459 buf = (duk_uint8_t *) duk_push_fixed_buffer_nozero(thr, len * 2);
16460 DUK_ASSERT(buf != NULL);
16461
16462#if defined(DUK_USE_HEX_FASTPATH)
16463 DUK_ASSERT((((duk_size_t) buf) & 0x01U) == 0); /* pointer is aligned, guaranteed for fixed buffer */
16464 p16 = (duk_uint16_t *) (void *) buf;
16465 len_safe = len & ~0x03U;
16466 for (i = 0; i < len_safe; i += 4) {
16467 p16[0] = duk_hex_enctab[inp[i]];
16468 p16[1] = duk_hex_enctab[inp[i + 1]];
16469 p16[2] = duk_hex_enctab[inp[i + 2]];
16470 p16[3] = duk_hex_enctab[inp[i + 3]];
16471 p16 += 4;
16472 }
16473 for (; i < len; i++) {
16474 *p16++ = duk_hex_enctab[inp[i]];
16475 }
16476#else /* DUK_USE_HEX_FASTPATH */
16477 for (i = 0; i < len; i++) {
16479 t = (duk_small_uint_t) inp[i];
16480 buf[i * 2 + 0] = duk_lc_digits[t >> 4];
16481 buf[i * 2 + 1] = duk_lc_digits[t & 0x0f];
16482 }
16483#endif /* DUK_USE_HEX_FASTPATH */
16484
16485 /* XXX: Using a string return value forces a string intern which is
16486 * not always necessary. As a rough performance measure, hex encode
16487 * time for tests/perf/test-hex-encode.js dropped from ~35s to ~15s
16488 * without string coercion. Change to returning a buffer and let the
16489 * caller coerce to string if necessary?
16490 */
16491
16492 ret = duk_buffer_to_string(thr, -1); /* Safe, result is ASCII. */
16493 duk_replace(thr, idx);
16494 return ret;
16495}
16496
16498 const duk_uint8_t *inp;
16499 duk_size_t len;
16500 duk_size_t i;
16501 duk_int_t t;
16502 duk_uint8_t *buf;
16503#if defined(DUK_USE_HEX_FASTPATH)
16504 duk_int_t chk;
16505 duk_uint8_t *p;
16506 duk_size_t len_safe;
16507#endif
16508
16510
16511 idx = duk_require_normalize_index(thr, idx);
16512 inp = duk__prep_codec_arg(thr, idx, &len);
16513 DUK_ASSERT(inp != NULL);
16514
16515 if (len & 0x01) {
16516 goto type_error;
16517 }
16518
16519 /* Fixed buffer, no zeroing because we'll fill all the data. */
16520 buf = (duk_uint8_t *) duk_push_fixed_buffer_nozero(thr, len / 2);
16521 DUK_ASSERT(buf != NULL);
16522
16523#if defined(DUK_USE_HEX_FASTPATH)
16524 p = buf;
16525 len_safe = len & ~0x07U;
16526 for (i = 0; i < len_safe; i += 8) {
16527 t = ((duk_int_t) duk_hex_dectab_shift4[inp[i]]) | ((duk_int_t) duk_hex_dectab[inp[i + 1]]);
16528 chk = t;
16529 p[0] = (duk_uint8_t) t;
16530 t = ((duk_int_t) duk_hex_dectab_shift4[inp[i + 2]]) | ((duk_int_t) duk_hex_dectab[inp[i + 3]]);
16531 chk |= t;
16532 p[1] = (duk_uint8_t) t;
16533 t = ((duk_int_t) duk_hex_dectab_shift4[inp[i + 4]]) | ((duk_int_t) duk_hex_dectab[inp[i + 5]]);
16534 chk |= t;
16535 p[2] = (duk_uint8_t) t;
16536 t = ((duk_int_t) duk_hex_dectab_shift4[inp[i + 6]]) | ((duk_int_t) duk_hex_dectab[inp[i + 7]]);
16537 chk |= t;
16538 p[3] = (duk_uint8_t) t;
16539 p += 4;
16540
16541 /* Check if any lookup above had a negative result. */
16542 if (DUK_UNLIKELY(chk < 0)) {
16543 goto type_error;
16544 }
16545 }
16546 for (; i < len; i += 2) {
16547 /* First cast to duk_int_t to sign extend, second cast to
16548 * duk_uint_t to avoid signed left shift, and final cast to
16549 * duk_int_t result type.
16550 */
16551 t = (duk_int_t) ((((duk_uint_t) (duk_int_t) duk_hex_dectab[inp[i]]) << 4U) |
16552 ((duk_uint_t) (duk_int_t) duk_hex_dectab[inp[i + 1]]));
16553 if (DUK_UNLIKELY(t < 0)) {
16554 goto type_error;
16555 }
16556 *p++ = (duk_uint8_t) t;
16557 }
16558#else /* DUK_USE_HEX_FASTPATH */
16559 for (i = 0; i < len; i += 2) {
16560 /* For invalid characters the value -1 gets extended to
16561 * at least 16 bits. If either nybble is invalid, the
16562 * resulting 't' will be < 0.
16563 */
16564 t = (duk_int_t) ((((duk_uint_t) (duk_int_t) duk_hex_dectab[inp[i]]) << 4U) |
16565 ((duk_uint_t) (duk_int_t) duk_hex_dectab[inp[i + 1]]));
16566 if (DUK_UNLIKELY(t < 0)) {
16567 goto type_error;
16568 }
16569 buf[i >> 1] = (duk_uint8_t) t;
16570 }
16571#endif /* DUK_USE_HEX_FASTPATH */
16572
16573 duk_replace(thr, idx);
16574 return;
16575
16576type_error:
16578 DUK_WO_NORETURN(return;);
16579}
16580#else /* DUK_USE_HEX_SUPPORT */
16581DUK_EXTERNAL const char *duk_hex_encode(duk_hthread *thr, duk_idx_t idx) {
16582 DUK_UNREF(idx);
16584 DUK_WO_NORETURN(return NULL;);
16585}
16587 DUK_UNREF(idx);
16589 DUK_WO_NORETURN(return;);
16590}
16591#endif /* DUK_USE_HEX_SUPPORT */
16592
16593/*
16594 * JSON
16595 */
16596
16597#if defined(DUK_USE_JSON_SUPPORT)
16598DUK_EXTERNAL const char *duk_json_encode(duk_hthread *thr, duk_idx_t idx) {
16599#if defined(DUK_USE_ASSERTIONS)
16600 duk_idx_t top_at_entry;
16601#endif
16602 const char *ret;
16603
16605#if defined(DUK_USE_ASSERTIONS)
16606 top_at_entry = duk_get_top(thr);
16607#endif
16608
16609 idx = duk_require_normalize_index(thr, idx);
16611 idx /*idx_value*/,
16612 DUK_INVALID_INDEX /*idx_replacer*/,
16613 DUK_INVALID_INDEX /*idx_space*/,
16614 0 /*flags*/);
16615 DUK_ASSERT(duk_is_string(thr, -1));
16616 duk_replace(thr, idx);
16617 ret = duk_get_string(thr, idx);
16618
16619 DUK_ASSERT(duk_get_top(thr) == top_at_entry);
16620
16621 return ret;
16622}
16623
16625#if defined(DUK_USE_ASSERTIONS)
16626 duk_idx_t top_at_entry;
16627#endif
16628
16630#if defined(DUK_USE_ASSERTIONS)
16631 top_at_entry = duk_get_top(thr);
16632#endif
16633
16634 idx = duk_require_normalize_index(thr, idx);
16635 duk_bi_json_parse_helper(thr, idx /*idx_value*/, DUK_INVALID_INDEX /*idx_reviver*/, 0 /*flags*/);
16636 duk_replace(thr, idx);
16637
16638 DUK_ASSERT(duk_get_top(thr) == top_at_entry);
16639}
16640#else /* DUK_USE_JSON_SUPPORT */
16641DUK_EXTERNAL const char *duk_json_encode(duk_hthread *thr, duk_idx_t idx) {
16643 DUK_UNREF(idx);
16645 DUK_WO_NORETURN(return NULL;);
16646}
16647
16654#endif /* DUK_USE_JSON_SUPPORT */
16655/*
16656 * Compilation and evaluation
16658
16659/* #include duk_internal.h -> already included */
16660
16662struct duk__compile_raw_args {
16663 duk_size_t src_length; /* should be first on 64-bit platforms */
16664 const duk_uint8_t *src_buffer;
16666};
16667
16668/* Eval is just a wrapper now. */
16669DUK_EXTERNAL duk_int_t duk_eval_raw(duk_hthread *thr, const char *src_buffer, duk_size_t src_length, duk_uint_t flags) {
16670 duk_int_t rc;
16671
16673
16674 /* Note: strictness is *not* inherited from the current Duktape/C.
16675 * This would be confusing because the current strictness state
16676 * depends on whether we're running inside a Duktape/C activation
16677 * (= strict mode) or outside of any activation (= non-strict mode).
16678 * See tests/api/test-eval-strictness.c for more discussion.
16679 */
16680
16681 /* [ ... source? filename? ] (depends on flags) */
16682
16683 rc = duk_compile_raw(thr,
16684 src_buffer,
16685 src_length,
16686 flags | DUK_COMPILE_EVAL); /* may be safe, or non-safe depending on flags */
16687
16688 /* [ ... closure/error ] */
16689
16690 if (rc != DUK_EXEC_SUCCESS) {
16691 rc = DUK_EXEC_ERROR;
16692 goto got_rc;
16693 }
16694
16695 duk_push_global_object(thr); /* explicit 'this' binding, see GH-164 */
16696
16697 if (flags & DUK_COMPILE_SAFE) {
16698 rc = duk_pcall_method(thr, 0);
16699 } else {
16700 duk_call_method(thr, 0);
16701 rc = DUK_EXEC_SUCCESS;
16702 }
16704 /* [ ... result/error ] */
16705
16706got_rc:
16707 if (flags & DUK_COMPILE_NORESULT) {
16708 duk_pop(thr);
16709 }
16710
16711 return rc;
16712}
16713
16714/* Helper which can be called both directly and with duk_safe_call(). */
16716 duk__compile_raw_args *comp_args;
16717 duk_uint_t flags;
16718 duk_hcompfunc *h_templ;
16719
16721 DUK_ASSERT(udata != NULL);
16722
16723 /* Note: strictness is not inherited from the current Duktape/C
16724 * context. Otherwise it would not be possible to compile
16725 * non-strict code inside a Duktape/C activation (which is
16726 * always strict now). See tests/api/test-eval-strictness.c
16727 * for discussion.
16728 */
16729
16730 /* [ ... source? filename? ] (depends on flags) */
16731
16732 comp_args = (duk__compile_raw_args *) udata;
16733 flags = comp_args->flags;
16734
16735 if (flags & DUK_COMPILE_NOFILENAME) {
16736 /* Automatic filename: 'eval' or 'input'. */
16738 }
16739
16740 /* [ ... source? filename ] */
16741
16742 if (!comp_args->src_buffer) {
16743 duk_hstring *h_sourcecode;
16744
16745 h_sourcecode = duk_get_hstring(thr, -2);
16746 if ((flags & DUK_COMPILE_NOSOURCE) || /* args incorrect */
16747 (h_sourcecode == NULL)) { /* e.g. duk_push_string_file_raw() pushed undefined */
16749 DUK_WO_NORETURN(return 0;);
16750 }
16751 DUK_ASSERT(h_sourcecode != NULL);
16752 comp_args->src_buffer = (const duk_uint8_t *) DUK_HSTRING_GET_DATA(h_sourcecode);
16753 comp_args->src_length = (duk_size_t) DUK_HSTRING_GET_BYTELEN(h_sourcecode);
16754 }
16755 DUK_ASSERT(comp_args->src_buffer != NULL);
16756
16757 if (flags & DUK_COMPILE_FUNCTION) {
16759 }
16760
16761 /* [ ... source? filename ] */
16762
16763 duk_js_compile(thr, comp_args->src_buffer, comp_args->src_length, flags);
16764
16765 /* [ ... source? func_template ] */
16766
16767 if (flags & DUK_COMPILE_NOSOURCE) {
16768 ;
16769 } else {
16770 duk_remove_m2(thr);
16771 }
16772
16773 /* [ ... func_template ] */
16774
16775 h_templ = (duk_hcompfunc *) duk_known_hobject(thr, -1);
16777 h_templ,
16780 1 /*add_auto_proto*/);
16781 duk_remove_m2(thr); /* -> [ ... closure ] */
16782
16783 /* [ ... closure ] */
16784
16785 return 1;
16786}
16787
16788DUK_EXTERNAL duk_int_t duk_compile_raw(duk_hthread *thr, const char *src_buffer, duk_size_t src_length, duk_uint_t flags) {
16789 duk__compile_raw_args comp_args_alloc;
16790 duk__compile_raw_args *comp_args = &comp_args_alloc;
16791
16793
16794 if ((flags & DUK_COMPILE_STRLEN) && (src_buffer != NULL)) {
16795 /* String length is computed here to avoid multiple evaluation
16796 * of a macro argument in the calling side.
16797 */
16798 src_length = DUK_STRLEN(src_buffer);
16799 }
16800
16801 comp_args->src_buffer = (const duk_uint8_t *) src_buffer;
16802 comp_args->src_length = src_length;
16803 comp_args->flags = flags;
16804
16805 /* [ ... source? filename? ] (depends on flags) */
16806
16807 if (flags & DUK_COMPILE_SAFE) {
16808 duk_int_t rc;
16809 duk_int_t nargs;
16810 duk_int_t nrets = 1;
16811
16812 /* Arguments can be: [ source? filename? &comp_args] so that
16813 * nargs is 1 to 3. Call site encodes the correct nargs count
16814 * directly into flags.
16815 */
16816 nargs = flags & 0x07;
16817 DUK_ASSERT(nargs == ((flags & DUK_COMPILE_NOSOURCE) ? 0 : 1) + ((flags & DUK_COMPILE_NOFILENAME) ? 0 : 1));
16818 rc = duk_safe_call(thr, duk__do_compile, (void *) comp_args, nargs, nrets);
16819
16820 /* [ ... closure ] */
16821 return rc;
16822 }
16823
16824 (void) duk__do_compile(thr, (void *) comp_args);
16825
16826 /* [ ... closure ] */
16827 return DUK_EXEC_SUCCESS;
16828}
16829/*
16830 * Debugging related API calls
16831 */
16832
16833/* #include duk_internal.h -> already included */
16834
16835#if defined(DUK_USE_JSON_SUPPORT)
16837 duk_idx_t idx;
16838 duk_idx_t top;
16839
16841
16842 /* We don't duk_require_stack() here now, but rely on the caller having
16843 * enough space.
16844 */
16845
16846 top = duk_get_top(thr);
16848 for (idx = 0; idx < top; idx++) {
16849 duk_dup(thr, idx);
16850 duk_put_prop_index(thr, -2, (duk_uarridx_t) idx);
16851 }
16852
16853 /* XXX: conversion errors should not propagate outwards.
16854 * Perhaps values need to be coerced individually?
16855 */
16857 duk_get_top_index(thr), /*idx_value*/
16858 DUK_INVALID_INDEX, /*idx_replacer*/
16859 DUK_INVALID_INDEX, /*idx_space*/
16862
16863 duk_push_sprintf(thr, "ctx: top=%ld, stack=%s", (long) top, (const char *) duk_safe_to_string(thr, -1));
16864 duk_replace(thr, -3); /* [ ... arr jsonx(arr) res ] -> [ ... res jsonx(arr) ] */
16865 duk_pop(thr);
16866 DUK_ASSERT(duk_is_string(thr, -1));
16867}
16868#else /* DUK_USE_JSON_SUPPORT */
16872 DUK_WO_NORETURN(return;);
16873}
16874#endif /* DUK_USE_JSON_SUPPORT */
16875
16876#if defined(DUK_USE_DEBUGGER_SUPPORT)
16877
16880 duk_debug_write_function write_cb,
16882 duk_debug_read_flush_function read_flush_cb,
16883 duk_debug_write_flush_function write_flush_cb,
16884 duk_debug_request_function request_cb,
16885 duk_debug_detached_function detached_cb,
16886 void *udata) {
16887 duk_heap *heap;
16888 const char *str;
16889 duk_size_t len;
16890
16891 /* XXX: should there be an error or an automatic detach if
16892 * already attached?
16893 */
16894
16895 DUK_D(DUK_DPRINT("application called duk_debugger_attach()"));
16896
16898 DUK_ASSERT(read_cb != NULL);
16899 DUK_ASSERT(write_cb != NULL);
16900 /* Other callbacks are optional. */
16901
16902 heap = thr->heap;
16903 heap->dbg_read_cb = read_cb;
16904 heap->dbg_write_cb = write_cb;
16905 heap->dbg_peek_cb = peek_cb;
16906 heap->dbg_read_flush_cb = read_flush_cb;
16907 heap->dbg_write_flush_cb = write_flush_cb;
16908 heap->dbg_request_cb = request_cb;
16909 heap->dbg_detached_cb = detached_cb;
16910 heap->dbg_udata = udata;
16911 heap->dbg_have_next_byte = 0;
16912
16913 /* Start in paused state. */
16914 heap->dbg_processing = 0;
16915 heap->dbg_state_dirty = 0;
16916 heap->dbg_force_restart = 0;
16917 heap->dbg_pause_flags = 0;
16918 heap->dbg_pause_act = NULL;
16919 heap->dbg_pause_startline = 0;
16920 heap->dbg_exec_counter = 0;
16921 heap->dbg_last_counter = 0;
16922 heap->dbg_last_time = 0.0;
16923 duk_debug_set_paused(heap); /* XXX: overlap with fields above */
16924
16925 /* Send version identification and flush right afterwards. Note that
16926 * we must write raw, unframed bytes here.
16927 */
16928 duk_push_sprintf(thr,
16929 "%ld %ld %s %s\n",
16931 (long) DUK_VERSION,
16932 (const char *) DUK_GIT_DESCRIBE,
16933 (const char *) DUK_USE_TARGET_INFO);
16934 str = duk_get_lstring(thr, -1, &len);
16935 DUK_ASSERT(str != NULL);
16936 duk_debug_write_bytes(thr, (const duk_uint8_t *) str, len);
16937 duk_debug_write_flush(thr);
16938 duk_pop(thr);
16939}
16940
16942 DUK_D(DUK_DPRINT("application called duk_debugger_detach()"));
16943
16945 DUK_ASSERT(thr->heap != NULL);
16946
16947 /* Can be called multiple times with no harm. */
16948 duk_debug_do_detach(thr->heap);
16949}
16950
16952 duk_bool_t processed_messages;
16953
16955 DUK_ASSERT(thr->heap != NULL);
16956
16957 if (!duk_debug_is_attached(thr->heap)) {
16958 return;
16959 }
16960 if (thr->callstack_curr != NULL || thr->heap->dbg_processing) {
16961 /* Calling duk_debugger_cooperate() while Duktape is being
16962 * called into is not supported. This is not a 100% check
16963 * but prevents any damage in most cases.
16964 */
16965 return;
16966 }
16967
16968 processed_messages = duk_debug_process_messages(thr, 1 /*no_block*/);
16969 DUK_UNREF(processed_messages);
16970}
16971
16973 duk_idx_t top;
16974 duk_idx_t idx;
16975 duk_bool_t ret = 0;
16976
16978 DUK_ASSERT(thr->heap != NULL);
16979
16980 DUK_D(DUK_DPRINT("application called duk_debugger_notify() with nvalues=%ld", (long) nvalues));
16981
16982 top = duk_get_top(thr);
16983 if (top < nvalues) {
16984 DUK_ERROR_RANGE(thr, "not enough stack values for notify");
16985 DUK_WO_NORETURN(return 0;);
16986 }
16987 if (duk_debug_is_attached(thr->heap)) {
16988 duk_debug_write_notify(thr, DUK_DBG_CMD_APPNOTIFY);
16989 for (idx = top - nvalues; idx < top; idx++) {
16990 duk_tval *tv = DUK_GET_TVAL_POSIDX(thr, idx);
16991 duk_debug_write_tval(thr, tv);
16992 }
16993 duk_debug_write_eom(thr);
16994
16995 /* Return non-zero (true) if we have a good reason to believe
16996 * the notify was delivered; if we're still attached at least
16997 * a transport error was not indicated by the transport write
16998 * callback. This is not a 100% guarantee of course.
16999 */
17000 if (duk_debug_is_attached(thr->heap)) {
17001 ret = 1;
17002 }
17003 }
17004 duk_pop_n(thr, nvalues);
17005 return ret;
17006}
17007
17010 DUK_ASSERT(thr->heap != NULL);
17011
17012 DUK_D(DUK_DPRINT("application called duk_debugger_pause()"));
17013
17014 /* Treat like a debugger statement: ignore when not attached. */
17015 if (duk_debug_is_attached(thr->heap)) {
17016 if (duk_debug_is_paused(thr->heap)) {
17017 DUK_D(DUK_DPRINT("duk_debugger_pause() called when already paused; ignoring"));
17018 } else {
17019 duk_debug_set_paused(thr->heap);
17020
17021 /* Pause on the next opcode executed. This is always safe to do even
17022 * inside the debugger message loop: the interrupt counter will be reset
17023 * to its proper value when the message loop exits.
17024 */
17025 thr->interrupt_init = 1;
17026 thr->interrupt_counter = 0;
17027 }
17028 }
17029}
17030
17031#else /* DUK_USE_DEBUGGER_SUPPORT */
17032
17035 duk_debug_write_function write_cb,
17037 duk_debug_read_flush_function read_flush_cb,
17038 duk_debug_write_flush_function write_flush_cb,
17039 duk_debug_request_function request_cb,
17040 duk_debug_detached_function detached_cb,
17041 void *udata) {
17043 DUK_UNREF(read_cb);
17044 DUK_UNREF(write_cb);
17045 DUK_UNREF(peek_cb);
17046 DUK_UNREF(read_flush_cb);
17047 DUK_UNREF(write_flush_cb);
17048 DUK_UNREF(request_cb);
17049 DUK_UNREF(detached_cb);
17050 DUK_UNREF(udata);
17051 DUK_ERROR_TYPE(thr, "no debugger support");
17052 DUK_WO_NORETURN(return;);
17053}
17054
17057 DUK_ERROR_TYPE(thr, "no debugger support");
17058 DUK_WO_NORETURN(return;);
17059}
17060
17062 /* nop */
17064 DUK_UNREF(thr);
17065}
17066
17068 duk_idx_t top;
17069
17072 top = duk_get_top(thr);
17073 if (top < nvalues) {
17075 DUK_WO_NORETURN(return 0;);
17076 }
17077
17078 /* No debugger support, just pop values. */
17079 duk_pop_n(thr, nvalues);
17080 return 0;
17081}
17082
17084 /* Treat like debugger statement: nop */
17089#endif /* DUK_USE_DEBUGGER_SUPPORT */
17091 * Heap creation and destruction
17092 */
17093
17094/* #include duk_internal.h -> already included */
17095
17097
17102 duk_uint8_t thread_state;
17104};
17105
17107 duk_realloc_function realloc_func,
17108 duk_free_function free_func,
17109 void *heap_udata,
17110 duk_fatal_function fatal_handler) {
17111 duk_heap *heap = NULL;
17112 duk_hthread *thr;
17113
17114 /* Assume that either all memory funcs are NULL or non-NULL, mixed
17115 * cases will now be unsafe.
17116 */
17117
17118 /* XXX: just assert non-NULL values here and make caller arguments
17119 * do the defaulting to the default implementations (smaller code)?
17120 */
17121
17122 if (!alloc_func) {
17123 DUK_ASSERT(realloc_func == NULL);
17124 DUK_ASSERT(free_func == NULL);
17125#if defined(DUK_USE_PROVIDE_DEFAULT_ALLOC_FUNCTIONS)
17126 alloc_func = duk_default_alloc_function;
17127 realloc_func = duk_default_realloc_function;
17128 free_func = duk_default_free_function;
17129#else
17130 DUK_D(DUK_DPRINT("no allocation functions given and no default providers"));
17131 return NULL;
17132#endif
17133 } else {
17134 DUK_ASSERT(realloc_func != NULL);
17135 DUK_ASSERT(free_func != NULL);
17136 }
17137
17138 if (!fatal_handler) {
17139 fatal_handler = duk_default_fatal_handler;
17140 }
17141
17142 DUK_ASSERT(alloc_func != NULL);
17143 DUK_ASSERT(realloc_func != NULL);
17144 DUK_ASSERT(free_func != NULL);
17145 DUK_ASSERT(fatal_handler != NULL);
17146
17147 heap = duk_heap_alloc(alloc_func, realloc_func, free_func, heap_udata, fatal_handler);
17148 if (!heap) {
17149 return NULL;
17150 }
17151 thr = heap->heap_thread;
17152 DUK_ASSERT(thr != NULL);
17153 DUK_ASSERT(thr->heap != NULL);
17154 return thr;
17155}
17156
17159
17160 if (!thr) {
17161 return;
17162 }
17164 heap = thr->heap;
17165 DUK_ASSERT(heap != NULL);
17166
17167 duk_heap_free(heap);
17168}
17169
17172 duk_heap *heap;
17173 duk_ljstate *lj;
17174
17176 DUK_ASSERT(thr->heap != NULL);
17177 DUK_ASSERT(state != NULL); /* unvalidated */
17178
17179 /* Currently not supported when called from within a finalizer.
17180 * If that is done, the finalizer will remain running indefinitely,
17181 * preventing other finalizers from executing. The assert is a bit
17182 * wider, checking that it would be OK to run pending finalizers.
17183 */
17184 DUK_ASSERT(thr->heap->pf_prevent_count == 0);
17185
17186 /* Currently not supported to duk_suspend() from an errCreate()
17187 * call.
17188 */
17189 DUK_ASSERT(thr->heap->creating_error == 0);
17190
17191 heap = thr->heap;
17192 lj = &heap->lj;
17193
17194 duk_push_tval(thr, &lj->value1);
17195 duk_push_tval(thr, &lj->value2);
17196
17197 /* XXX: creating_error == 0 is asserted above, so no need to store. */
17198 duk_memcpy((void *) &snapshot->lj, (const void *) lj, sizeof(duk_ljstate));
17199 snapshot->creating_error = heap->creating_error;
17200 snapshot->curr_thread = heap->curr_thread;
17201 snapshot->thread_state = thr->state;
17202 snapshot->call_recursion_depth = heap->call_recursion_depth;
17204 lj->jmpbuf_ptr = NULL;
17208 heap->creating_error = 0;
17209 heap->curr_thread = NULL;
17210 heap->call_recursion_depth = 0;
17211
17213}
17214
17215DUK_EXTERNAL void duk_resume(duk_hthread *thr, const duk_thread_state *state) {
17216 const duk_internal_thread_state *snapshot = (const duk_internal_thread_state *) (const void *) state;
17217 duk_heap *heap;
17218
17220 DUK_ASSERT(thr->heap != NULL);
17221 DUK_ASSERT(state != NULL); /* unvalidated */
17222
17223 /* Shouldn't be necessary if duk_suspend() is called before
17224 * duk_resume(), but assert in case API sequence is incorrect.
17225 */
17226 DUK_ASSERT(thr->heap->pf_prevent_count == 0);
17227 DUK_ASSERT(thr->heap->creating_error == 0);
17228
17229 thr->state = snapshot->thread_state;
17231 heap = thr->heap;
17232
17233 duk_memcpy((void *) &heap->lj, (const void *) &snapshot->lj, sizeof(duk_ljstate));
17234 heap->creating_error = snapshot->creating_error;
17235 heap->curr_thread = snapshot->curr_thread;
17236 heap->call_recursion_depth = snapshot->call_recursion_depth;
17237
17238 duk_pop_2(thr);
17239}
17240
17241/* XXX: better place for this */
17243 duk_hobject *h_glob;
17244 duk_hobject *h_prev_glob;
17245 duk_hobjenv *h_env;
17246 duk_hobject *h_prev_env;
17247
17249
17250 DUK_D(DUK_DPRINT("replace global object with: %!T", duk_get_tval(thr, -1)));
17251
17252 h_glob = duk_require_hobject(thr, -1);
17253 DUK_ASSERT(h_glob != NULL);
17254
17255 /*
17256 * Replace global object.
17257 */
17258
17259 h_prev_glob = thr->builtins[DUK_BIDX_GLOBAL];
17260 DUK_UNREF(h_prev_glob);
17261 thr->builtins[DUK_BIDX_GLOBAL] = h_glob;
17262 DUK_HOBJECT_INCREF(thr, h_glob);
17263 DUK_HOBJECT_DECREF_ALLOWNULL(thr, h_prev_glob); /* side effects, in theory (referenced by global env) */
17264
17265 /*
17266 * Replace lexical environment for global scope
17267 *
17268 * Create a new object environment for the global lexical scope.
17269 * We can't just reset the _Target property of the current one,
17270 * because the lexical scope is shared by other threads with the
17271 * same (initial) built-ins.
17272 */
17273
17275 DUK_ASSERT(h_env != NULL);
17276 DUK_ASSERT(DUK_HOBJECT_GET_PROTOTYPE(thr->heap, (duk_hobject *) h_env) == NULL);
17277
17278 DUK_ASSERT(h_env->target == NULL);
17279 DUK_ASSERT(h_glob != NULL);
17280 h_env->target = h_glob;
17281 DUK_HOBJECT_INCREF(thr, h_glob);
17282 DUK_ASSERT(h_env->has_this == 0);
17283
17284 /* [ ... new_glob ] */
17285
17286 h_prev_env = thr->builtins[DUK_BIDX_GLOBAL_ENV];
17287 thr->builtins[DUK_BIDX_GLOBAL_ENV] = (duk_hobject *) h_env;
17288 DUK_HOBJECT_INCREF(thr, (duk_hobject *) h_env);
17289 DUK_HOBJECT_DECREF_ALLOWNULL(thr, h_prev_env); /* side effects */
17290 DUK_UNREF(h_env); /* without refcounts */
17291 DUK_UNREF(h_prev_env);
17292
17293 /* [ ... new_glob ] */
17294
17295 duk_pop(thr);
17297 /* [ ... ] */
17298}
17299/*
17300 * Inspection
17301 */
17302
17303/* #include duk_internal.h -> already included */
17304
17305/* For footprint efficient multiple value setting: arrays are much better than
17306 * varargs, format string with parsing is often better than string pointer arrays.
17307 */
17308DUK_LOCAL void duk__inspect_multiple_uint(duk_hthread *thr, const char *fmt, duk_int_t *vals) {
17309 duk_int_t val;
17310 const char *p;
17311 const char *p_curr;
17312 duk_size_t len;
17313
17314 for (p = fmt;;) {
17315 len = DUK_STRLEN(p);
17316 p_curr = p;
17317 p += len + 1;
17318 if (len == 0) {
17319 /* Double NUL (= empty key) terminates. */
17320 break;
17321 }
17322 val = *vals++;
17323 if (val >= 0) {
17324 /* Negative values are markers to skip key. */
17325 duk_push_string(thr, p_curr);
17326 duk_push_int(thr, val);
17327 duk_put_prop(thr, -3);
17332/* Raw helper to extract internal information / statistics about a value.
17333 * The return value is an object with properties that are version specific.
17334 * The properties must not expose anything that would lead to security
17335 * issues (e.g. exposing compiled function 'data' buffer might be an issue).
17336 * Currently only counts and sizes and such are given so there shouldn't
17337 * be security implications.
17340#define DUK__IDX_TYPE 0
17341#define DUK__IDX_ITAG 1
17342#define DUK__IDX_REFC 2
17343#define DUK__IDX_HBYTES 3
17344#define DUK__IDX_CLASS 4
17345#define DUK__IDX_PBYTES 5
17346#define DUK__IDX_ESIZE 6
17347#define DUK__IDX_ENEXT 7
17348#define DUK__IDX_ASIZE 8
17349#define DUK__IDX_HSIZE 9
17350#define DUK__IDX_BCBYTES 10
17351#define DUK__IDX_DBYTES 11
17352#define DUK__IDX_TSTATE 12
17353#define DUK__IDX_VARIANT 13
17354
17356 duk_tval *tv;
17357 duk_heaphdr *h;
17358 /* The temporary values should be in an array rather than individual
17359 * variables which (in practice) ensures that the compiler won't map
17360 * them to registers and emit a lot of unnecessary shuffling code.
17361 */
17362 duk_int_t vals[14];
17363
17365
17366 /* Assume two's complement and set everything to -1. */
17367 duk_memset((void *) &vals, (int) 0xff, sizeof(vals));
17368 DUK_ASSERT(vals[DUK__IDX_TYPE] == -1); /* spot check one */
17369
17370 tv = duk_get_tval_or_unused(thr, idx);
17371 h = (DUK_TVAL_IS_HEAP_ALLOCATED(tv) ? DUK_TVAL_GET_HEAPHDR(tv) : NULL);
17372
17373 vals[DUK__IDX_TYPE] = duk_get_type_tval(tv);
17375
17376 duk_push_bare_object(thr); /* Invalidates 'tv'. */
17377 tv = NULL;
17378
17379 if (h == NULL) {
17380 goto finish;
17381 }
17382 duk_push_pointer(thr, (void *) h);
17383 duk_put_prop_literal(thr, -2, "hptr");
17384
17385#if 0
17386 /* Covers a lot of information, e.g. buffer and string variants. */
17388 duk_put_prop_literal(thr, -2, "hflags");
17389#endif
17390
17391#if defined(DUK_USE_REFERENCE_COUNTING)
17393#endif
17394 vals[DUK__IDX_VARIANT] = 0;
17395
17396 /* Heaphdr size and additional allocation size, followed by
17397 * type specific stuff (with varying value count).
17398 */
17400 case DUK_HTYPE_STRING: {
17401 duk_hstring *h_str = (duk_hstring *) h;
17402 vals[DUK__IDX_HBYTES] = (duk_int_t) (sizeof(duk_hstring) + DUK_HSTRING_GET_BYTELEN(h_str) + 1);
17403#if defined(DUK_USE_HSTRING_EXTDATA)
17404 if (DUK_HSTRING_HAS_EXTDATA(h_str)) {
17405 vals[DUK__IDX_VARIANT] = 1;
17406 }
17407#endif
17408 break;
17409 }
17410 case DUK_HTYPE_OBJECT: {
17411 duk_hobject *h_obj = (duk_hobject *) h;
17412
17413 /* XXX: variants here are maybe pointless; class is enough? */
17414 if (DUK_HOBJECT_IS_ARRAY(h_obj)) {
17415 vals[DUK__IDX_HBYTES] = sizeof(duk_harray);
17416 } else if (DUK_HOBJECT_IS_COMPFUNC(h_obj)) {
17417 vals[DUK__IDX_HBYTES] = sizeof(duk_hcompfunc);
17418 } else if (DUK_HOBJECT_IS_NATFUNC(h_obj)) {
17419 vals[DUK__IDX_HBYTES] = sizeof(duk_hnatfunc);
17420 } else if (DUK_HOBJECT_IS_THREAD(h_obj)) {
17421 vals[DUK__IDX_HBYTES] = sizeof(duk_hthread);
17422 vals[DUK__IDX_TSTATE] = ((duk_hthread *) h_obj)->state;
17423#if defined(DUK_USE_BUFFEROBJECT_SUPPORT)
17424 } else if (DUK_HOBJECT_IS_BUFOBJ(h_obj)) {
17425 vals[DUK__IDX_HBYTES] = sizeof(duk_hbufobj);
17426 /* XXX: some size information */
17427#endif
17428 } else {
17430 }
17431
17438
17439 /* Note: e_next indicates the number of gc-reachable entries
17440 * in the entry part, and also indicates the index where the
17441 * next new property would be inserted. It does *not* indicate
17442 * the number of non-NULL keys present in the object. That
17443 * value could be counted separately but requires a pass through
17444 * the key list.
17445 */
17446
17447 if (DUK_HOBJECT_IS_COMPFUNC(h_obj)) {
17448 duk_hbuffer *h_data = (duk_hbuffer *) DUK_HCOMPFUNC_GET_DATA(thr->heap, (duk_hcompfunc *) h_obj);
17449 vals[DUK__IDX_BCBYTES] = (duk_int_t) (h_data ? DUK_HBUFFER_GET_SIZE(h_data) : 0);
17450 }
17451 break;
17452 }
17453 case DUK_HTYPE_BUFFER: {
17454 duk_hbuffer *h_buf = (duk_hbuffer *) h;
17455
17456 if (DUK_HBUFFER_HAS_DYNAMIC(h_buf)) {
17457 if (DUK_HBUFFER_HAS_EXTERNAL(h_buf)) {
17458 vals[DUK__IDX_VARIANT] = 2; /* buffer variant 2: external */
17460 } else {
17461 /* When alloc_size == 0 the second allocation may not
17462 * actually exist.
17463 */
17464 vals[DUK__IDX_VARIANT] = 1; /* buffer variant 1: dynamic */
17466 }
17468 } else {
17469 DUK_ASSERT(vals[DUK__IDX_VARIANT] == 0); /* buffer variant 0: fixed */
17471 }
17472 break;
17473 }
17474 }
17475
17476finish:
17478 "type"
17479 "\x00"
17480 "itag"
17481 "\x00"
17482 "refc"
17483 "\x00"
17484 "hbytes"
17485 "\x00"
17486 "class"
17487 "\x00"
17488 "pbytes"
17489 "\x00"
17490 "esize"
17491 "\x00"
17492 "enext"
17493 "\x00"
17494 "asize"
17495 "\x00"
17496 "hsize"
17497 "\x00"
17498 "bcbytes"
17499 "\x00"
17500 "dbytes"
17501 "\x00"
17502 "tstate"
17503 "\x00"
17504 "variant"
17505 "\x00"
17506 "\x00",
17507 (duk_int_t *) &vals);
17508}
17509
17511 duk_activation *act;
17514
17516
17517 /* -1 = top callstack entry
17518 * -2 = caller of level -1
17519 * etc
17520 */
17521 act = duk_hthread_get_activation_for_level(thr, level);
17522 if (act == NULL) {
17523 duk_push_undefined(thr);
17524 return;
17525 }
17527
17528 /* Relevant PC is just before current one because PC is
17529 * post-incremented. This should match what error augment
17530 * code does.
17531 */
17532 pc = duk_hthread_get_act_prev_pc(thr, act);
17533
17534 duk_push_tval(thr, &act->tv_func);
17535
17536 duk_push_uint(thr, (duk_uint_t) pc);
17538
17539#if defined(DUK_USE_PC2LINE)
17540 line = duk_hobject_pc2line_query(thr, -1, pc);
17541#else
17542 line = 0;
17543#endif
17546
17548 /* Providing access to e.g. act->lex_env would be dangerous: these
17549 * internal structures must never be accessible to the application.
17550 * Duktape relies on them having consistent data, and this consistency
17551 * is only asserted for, not checked for.
17552 */
17553}
17554
17555/* automatic undefs */
17556#undef DUK__IDX_ASIZE
17557#undef DUK__IDX_BCBYTES
17558#undef DUK__IDX_CLASS
17559#undef DUK__IDX_DBYTES
17560#undef DUK__IDX_ENEXT
17561#undef DUK__IDX_ESIZE
17562#undef DUK__IDX_HBYTES
17563#undef DUK__IDX_HSIZE
17564#undef DUK__IDX_ITAG
17565#undef DUK__IDX_PBYTES
17566#undef DUK__IDX_REFC
17567#undef DUK__IDX_TSTATE
17568#undef DUK__IDX_TYPE
17569#undef DUK__IDX_VARIANT
17571 * Memory calls.
17572 */
17573
17574/* #include duk_internal.h -> already included */
17575
17578
17579 return DUK_ALLOC_RAW(thr->heap, size);
17580}
17581
17584
17585 DUK_FREE_RAW(thr->heap, ptr);
17586}
17587
17590
17591 return DUK_REALLOC_RAW(thr->heap, ptr, size);
17592}
17593
17596
17597 return DUK_ALLOC(thr->heap, size);
17598}
17599
17600DUK_EXTERNAL void duk_free(duk_hthread *thr, void *ptr) {
17602
17603 DUK_FREE_CHECKED(thr, ptr);
17604}
17605
17606DUK_EXTERNAL void *duk_realloc(duk_hthread *thr, void *ptr, duk_size_t size) {
17608
17609 /*
17610 * Note: since this is an exposed API call, there should be
17611 * no way a mark-and-sweep could have a side effect on the
17612 * memory allocation behind 'ptr'; the pointer should never
17613 * be something that Duktape wants to change.
17614 *
17615 * Thus, no need to use DUK_REALLOC_INDIRECT (and we don't
17616 * have the storage location here anyway).
17617 */
17618
17619 return DUK_REALLOC(thr->heap, ptr, size);
17620}
17621
17623 duk_heap *heap;
17624
17626 DUK_ASSERT(out_funcs != NULL);
17627 DUK_ASSERT(thr != NULL);
17628 DUK_ASSERT(thr->heap != NULL);
17629
17630 heap = thr->heap;
17631 out_funcs->alloc_func = heap->alloc_func;
17632 out_funcs->realloc_func = heap->realloc_func;
17633 out_funcs->free_func = heap->free_func;
17634 out_funcs->udata = heap->heap_udata;
17635}
17636
17637DUK_EXTERNAL void duk_gc(duk_hthread *thr, duk_uint_t flags) {
17638 duk_heap *heap;
17639 duk_small_uint_t ms_flags;
17640
17642 heap = thr->heap;
17643 DUK_ASSERT(heap != NULL);
17644
17645 DUK_D(DUK_DPRINT("mark-and-sweep requested by application"));
17646 DUK_ASSERT(DUK_GC_COMPACT == DUK_MS_FLAG_EMERGENCY); /* Compact flag is 1:1 with emergency flag which forces compaction. */
17647 ms_flags = (duk_small_uint_t) flags;
17648 duk_heap_mark_and_sweep(heap, ms_flags);
17649}
17650/*
17651 * Object handling: property access and other support functions.
17653
17654/* #include duk_internal.h -> already included */
17655
17656/*
17657 * Property handling
17658 *
17659 * The API exposes only the most common property handling functions.
17660 * The caller can invoke ECMAScript built-ins for full control (e.g.
17661 * defineProperty, getOwnPropertyDescriptor).
17662 */
17663
17665 duk_tval *tv_obj;
17666 duk_tval *tv_key;
17667 duk_bool_t rc;
17668
17670
17671 /* Note: copying tv_obj and tv_key to locals to shield against a valstack
17672 * resize is not necessary for a property get right now.
17673 */
17674
17675 tv_obj = duk_require_tval(thr, obj_idx);
17676 tv_key = duk_require_tval(thr, -1);
17677
17678 rc = duk_hobject_getprop(thr, tv_obj, tv_key);
17679 DUK_ASSERT(rc == 0 || rc == 1);
17680 /* a value is left on stack regardless of rc */
17681
17682 duk_remove_m2(thr); /* remove key */
17683 DUK_ASSERT(duk_is_undefined(thr, -1) || rc == 1);
17684 return rc; /* 1 if property found, 0 otherwise */
17685}
17686
17687DUK_EXTERNAL duk_bool_t duk_get_prop_string(duk_hthread *thr, duk_idx_t obj_idx, const char *key) {
17689 DUK_ASSERT(key != NULL);
17690
17691 obj_idx = duk_require_normalize_index(thr, obj_idx);
17692 (void) duk_push_string(thr, key);
17693 return duk_get_prop(thr, obj_idx);
17695
17696DUK_EXTERNAL duk_bool_t duk_get_prop_lstring(duk_hthread *thr, duk_idx_t obj_idx, const char *key, duk_size_t key_len) {
17698 DUK_ASSERT(key != NULL);
17699
17700 obj_idx = duk_require_normalize_index(thr, obj_idx);
17701 (void) duk_push_lstring(thr, key, key_len);
17702 return duk_get_prop(thr, obj_idx);
17703}
17704
17705#if !defined(DUK_USE_PREFER_SIZE)
17706DUK_EXTERNAL duk_bool_t duk_get_prop_literal_raw(duk_hthread *thr, duk_idx_t obj_idx, const char *key, duk_size_t key_len) {
17708 DUK_ASSERT(key != NULL);
17709 DUK_ASSERT(key[key_len] == (char) 0);
17710
17711 obj_idx = duk_require_normalize_index(thr, obj_idx);
17712 (void) duk_push_literal_raw(thr, key, key_len);
17713 return duk_get_prop(thr, obj_idx);
17714}
17715#endif
17716
17719
17720 obj_idx = duk_require_normalize_index(thr, obj_idx);
17721 duk_push_uarridx(thr, arr_idx);
17722 return duk_get_prop(thr, obj_idx);
17723}
17724
17727
17728 obj_idx = duk_require_normalize_index(thr, obj_idx);
17729 (void) duk_push_heapptr(thr, ptr); /* NULL -> 'undefined' */
17730 return duk_get_prop(thr, obj_idx);
17731}
17732
17736
17737 obj_idx = duk_require_normalize_index(thr, obj_idx);
17738 (void) duk_push_hstring(thr, DUK_HTHREAD_GET_STRING(thr, stridx));
17739 return duk_get_prop(thr, obj_idx);
17740}
17741
17743 return duk_get_prop_stridx(thr, (duk_idx_t) (duk_int16_t) (packed_args >> 16), (duk_small_uint_t) (packed_args & 0xffffUL));
17744}
17745
17747 duk_idx_t obj_idx,
17748 duk_small_uint_t stridx,
17749 duk_bool_t *out_has_prop) {
17750 duk_bool_t rc;
17751
17754
17755 rc = duk_get_prop_stridx(thr, obj_idx, stridx);
17756 if (out_has_prop) {
17757 *out_has_prop = rc;
17758 }
17760}
17761
17762/* This get variant is for internal use, it differs from standard
17763 * duk_get_prop() in that:
17764 * - Object argument must be an object (primitive values not supported).
17765 * - Key argument must be a string (no coercion).
17766 * - Only own properties are checked (no inheritance). Only "entry part"
17767 * properties are checked (not array index properties).
17768 * - Property must be a plain data property, not a getter.
17769 * - Proxy traps are not triggered.
17770 */
17772 duk_hobject *h_obj;
17773 duk_hstring *h_key;
17774 duk_tval *tv_val;
17775
17777
17778 /* Note: copying tv_obj and tv_key to locals to shield against a valstack
17779 * resize is not necessary for a property get right now.
17780 */
17781
17782 h_obj = duk_get_hobject(thr, obj_idx);
17783 if (h_obj == NULL) {
17784 return 0;
17785 }
17786 h_key = duk_require_hstring(thr, -1);
17788 tv_val = duk_hobject_find_entry_tval_ptr(thr->heap, h_obj, h_key);
17789 if (tv_val == NULL) {
17790 return 0;
17791 }
17792
17793 duk_push_tval(thr, tv_val);
17794 duk_remove_m2(thr); /* remove key */
17795
17796 return 1;
17797}
17798
17803 obj_idx = duk_require_normalize_index(thr, obj_idx);
17804 (void) duk_push_hstring(thr, DUK_HTHREAD_GET_STRING(thr, stridx));
17805 return duk_xget_owndataprop(thr, obj_idx);
17806}
17807
17809 return duk_xget_owndataprop_stridx(thr,
17810 (duk_idx_t) (duk_int16_t) (packed_args >> 16),
17811 (duk_small_uint_t) (packed_args & 0xffffUL));
17812}
17813
17815 duk_tval *tv_obj;
17816 duk_tval *tv_key;
17817 duk_tval *tv_val;
17818 duk_bool_t throw_flag;
17819 duk_bool_t rc;
17820
17821 /* Note: copying tv_obj and tv_key to locals to shield against a valstack
17822 * resize is not necessary for a property put right now (putprop protects
17823 * against it internally).
17824 */
17825
17826 /* Key and value indices are either (-2, -1) or (-1, -2). Given idx_key,
17827 * idx_val is always (idx_key ^ 0x01).
17828 */
17829 DUK_ASSERT((idx_key == -2 && (idx_key ^ 1) == -1) || (idx_key == -1 && (idx_key ^ 1) == -2));
17830 /* XXX: Direct access; faster validation. */
17831 tv_obj = duk_require_tval(thr, obj_idx);
17832 tv_key = duk_require_tval(thr, idx_key);
17833 tv_val = duk_require_tval(thr, idx_key ^ 1);
17834 throw_flag = duk_is_strict_call(thr);
17835
17836 rc = duk_hobject_putprop(thr, tv_obj, tv_key, tv_val, throw_flag);
17837 DUK_ASSERT(rc == 0 || rc == 1);
17838
17839 duk_pop_2(thr); /* remove key and value */
17840 return rc; /* 1 if property found, 0 otherwise */
17841}
17842
17845 return duk__put_prop_shared(thr, obj_idx, -2);
17846}
17847
17848DUK_EXTERNAL duk_bool_t duk_put_prop_string(duk_hthread *thr, duk_idx_t obj_idx, const char *key) {
17850 DUK_ASSERT(key != NULL);
17851
17852 /* Careful here and with other duk_put_prop_xxx() helpers: the
17853 * target object and the property value may be in the same value
17854 * stack slot (unusual, but still conceptually clear).
17855 */
17856 obj_idx = duk_normalize_index(thr, obj_idx);
17857 (void) duk_push_string(thr, key);
17858 return duk__put_prop_shared(thr, obj_idx, -1);
17860
17861DUK_EXTERNAL duk_bool_t duk_put_prop_lstring(duk_hthread *thr, duk_idx_t obj_idx, const char *key, duk_size_t key_len) {
17863 DUK_ASSERT(key != NULL);
17864
17865 obj_idx = duk_normalize_index(thr, obj_idx);
17866 (void) duk_push_lstring(thr, key, key_len);
17867 return duk__put_prop_shared(thr, obj_idx, -1);
17868}
17869
17870#if !defined(DUK_USE_PREFER_SIZE)
17871DUK_EXTERNAL duk_bool_t duk_put_prop_literal_raw(duk_hthread *thr, duk_idx_t obj_idx, const char *key, duk_size_t key_len) {
17873 DUK_ASSERT(key != NULL);
17874 DUK_ASSERT(key[key_len] == (char) 0);
17875
17876 obj_idx = duk_normalize_index(thr, obj_idx);
17877 (void) duk_push_literal_raw(thr, key, key_len);
17878 return duk__put_prop_shared(thr, obj_idx, -1);
17879}
17880#endif
17881
17884
17885 obj_idx = duk_require_normalize_index(thr, obj_idx);
17886 duk_push_uarridx(thr, arr_idx);
17887 return duk__put_prop_shared(thr, obj_idx, -1);
17888}
17889
17892
17893 obj_idx = duk_require_normalize_index(thr, obj_idx);
17894 (void) duk_push_heapptr(thr, ptr); /* NULL -> 'undefined' */
17895 return duk__put_prop_shared(thr, obj_idx, -1);
17896}
17897
17901
17902 obj_idx = duk_require_normalize_index(thr, obj_idx);
17903 duk_push_hstring(thr, DUK_HTHREAD_GET_STRING(thr, stridx));
17904 return duk__put_prop_shared(thr, obj_idx, -1);
17905}
17906
17908 return duk_put_prop_stridx(thr, (duk_idx_t) (duk_int16_t) (packed_args >> 16), (duk_small_uint_t) (packed_args & 0xffffUL));
17909}
17910
17912 duk_tval *tv_obj;
17913 duk_tval *tv_key;
17914 duk_bool_t throw_flag;
17915 duk_bool_t rc;
17916
17918
17919 /* Note: copying tv_obj and tv_key to locals to shield against a valstack
17920 * resize is not necessary for a property delete right now.
17921 */
17923 tv_obj = duk_require_tval(thr, obj_idx);
17924 tv_key = duk_require_tval(thr, -1);
17925 throw_flag = duk_is_strict_call(thr);
17926
17927 rc = duk_hobject_delprop(thr, tv_obj, tv_key, throw_flag);
17928 DUK_ASSERT(rc == 0 || rc == 1);
17929
17930 duk_pop(thr); /* remove key */
17931 return rc;
17932}
17933
17934DUK_EXTERNAL duk_bool_t duk_del_prop_string(duk_hthread *thr, duk_idx_t obj_idx, const char *key) {
17936 DUK_ASSERT(key != NULL);
17937
17938 obj_idx = duk_require_normalize_index(thr, obj_idx);
17939 (void) duk_push_string(thr, key);
17940 return duk_del_prop(thr, obj_idx);
17942
17943DUK_EXTERNAL duk_bool_t duk_del_prop_lstring(duk_hthread *thr, duk_idx_t obj_idx, const char *key, duk_size_t key_len) {
17945 DUK_ASSERT(key != NULL);
17946
17947 obj_idx = duk_require_normalize_index(thr, obj_idx);
17948 (void) duk_push_lstring(thr, key, key_len);
17949 return duk_del_prop(thr, obj_idx);
17950}
17951
17952#if !defined(DUK_USE_PREFER_SIZE)
17953DUK_EXTERNAL duk_bool_t duk_del_prop_literal_raw(duk_hthread *thr, duk_idx_t obj_idx, const char *key, duk_size_t key_len) {
17955 DUK_ASSERT(key != NULL);
17956 DUK_ASSERT(key[key_len] == (char) 0);
17957
17958 obj_idx = duk_require_normalize_index(thr, obj_idx);
17959 (void) duk_push_literal_raw(thr, key, key_len);
17960 return duk_del_prop(thr, obj_idx);
17961}
17962#endif
17963
17966
17967 obj_idx = duk_require_normalize_index(thr, obj_idx);
17968 duk_push_uarridx(thr, arr_idx);
17969 return duk_del_prop(thr, obj_idx);
17970}
17971
17974
17975 obj_idx = duk_require_normalize_index(thr, obj_idx);
17976 (void) duk_push_heapptr(thr, ptr); /* NULL -> 'undefined' */
17977 return duk_del_prop(thr, obj_idx);
17978}
17979
17983
17984 obj_idx = duk_require_normalize_index(thr, obj_idx);
17985 duk_push_hstring(thr, DUK_HTHREAD_GET_STRING(thr, stridx));
17986 return duk_del_prop(thr, obj_idx);
17987}
17988
17989#if 0
17990DUK_INTERNAL duk_bool_t duk_del_prop_stridx_short_raw(duk_hthread *thr, duk_uint_t packed_args) {
17991 return duk_del_prop_stridx(thr, (duk_idx_t) (duk_int16_t) (packed_args >> 16),
17992 (duk_small_uint_t) (packed_args & 0xffffUL));
17993}
17994#endif
17995
17997 duk_tval *tv_obj;
17998 duk_tval *tv_key;
17999 duk_bool_t rc;
18000
18002
18003 /* Note: copying tv_obj and tv_key to locals to shield against a valstack
18004 * resize is not necessary for a property existence check right now.
18006
18007 tv_obj = duk_require_tval(thr, obj_idx);
18008 tv_key = duk_require_tval(thr, -1);
18009
18010 rc = duk_hobject_hasprop(thr, tv_obj, tv_key);
18011 DUK_ASSERT(rc == 0 || rc == 1);
18012
18013 duk_pop(thr); /* remove key */
18014 return rc; /* 1 if property found, 0 otherwise */
18015}
18016
18017DUK_EXTERNAL duk_bool_t duk_has_prop_string(duk_hthread *thr, duk_idx_t obj_idx, const char *key) {
18019 DUK_ASSERT(key != NULL);
18020
18021 obj_idx = duk_require_normalize_index(thr, obj_idx);
18022 (void) duk_push_string(thr, key);
18023 return duk_has_prop(thr, obj_idx);
18025
18026DUK_EXTERNAL duk_bool_t duk_has_prop_lstring(duk_hthread *thr, duk_idx_t obj_idx, const char *key, duk_size_t key_len) {
18028 DUK_ASSERT(key != NULL);
18029
18030 obj_idx = duk_require_normalize_index(thr, obj_idx);
18031 (void) duk_push_lstring(thr, key, key_len);
18032 return duk_has_prop(thr, obj_idx);
18033}
18034
18035#if !defined(DUK_USE_PREFER_SIZE)
18036DUK_EXTERNAL duk_bool_t duk_has_prop_literal_raw(duk_hthread *thr, duk_idx_t obj_idx, const char *key, duk_size_t key_len) {
18038 DUK_ASSERT(key != NULL);
18039 DUK_ASSERT(key[key_len] == (char) 0);
18040
18041 obj_idx = duk_require_normalize_index(thr, obj_idx);
18042 (void) duk_push_literal_raw(thr, key, key_len);
18043 return duk_has_prop(thr, obj_idx);
18044}
18045#endif
18046
18049
18050 obj_idx = duk_require_normalize_index(thr, obj_idx);
18051 duk_push_uarridx(thr, arr_idx);
18052 return duk_has_prop(thr, obj_idx);
18053}
18054
18057
18058 obj_idx = duk_require_normalize_index(thr, obj_idx);
18059 (void) duk_push_heapptr(thr, ptr); /* NULL -> 'undefined' */
18060 return duk_has_prop(thr, obj_idx);
18061}
18062
18066
18067 obj_idx = duk_require_normalize_index(thr, obj_idx);
18068 duk_push_hstring(thr, DUK_HTHREAD_GET_STRING(thr, stridx));
18069 return duk_has_prop(thr, obj_idx);
18070}
18071
18072#if 0
18073DUK_INTERNAL duk_bool_t duk_has_prop_stridx_short_raw(duk_hthread *thr, duk_uint_t packed_args) {
18074 return duk_has_prop_stridx(thr, (duk_idx_t) (duk_int16_t) (packed_args >> 16),
18075 (duk_small_uint_t) (packed_args & 0xffffUL));
18076}
18077#endif
18078
18079/* Define own property without inheritance lookups and such. This differs from
18080 * [[DefineOwnProperty]] because special behaviors (like Array 'length') are
18081 * not invoked by this method. The caller must be careful to invoke any such
18082 * behaviors if necessary.
18083 */
18084DUK_INTERNAL void duk_xdef_prop(duk_hthread *thr, duk_idx_t obj_idx, duk_small_uint_t desc_flags) {
18085 duk_hobject *obj;
18086 duk_hstring *key;
18087
18090 obj = duk_require_hobject(thr, obj_idx);
18091 DUK_ASSERT(obj != NULL);
18092 key = duk_to_property_key_hstring(thr, -2);
18093 DUK_ASSERT(key != NULL);
18094 DUK_ASSERT(duk_require_tval(thr, -1) != NULL);
18095
18096 duk_hobject_define_property_internal(thr, obj, key, desc_flags);
18097
18098 duk_pop(thr); /* pop key */
18099}
18100
18102 duk_hobject *obj;
18103
18105
18106 obj = duk_require_hobject(thr, obj_idx);
18107 DUK_ASSERT(obj != NULL);
18108
18109 duk_hobject_define_property_internal_arridx(thr, obj, arr_idx, desc_flags);
18110 /* value popped by call */
18111}
18112
18114 duk_hobject *obj;
18115 duk_hstring *key;
18116
18119
18120 obj = duk_require_hobject(thr, obj_idx);
18121 DUK_ASSERT(obj != NULL);
18122 key = DUK_HTHREAD_GET_STRING(thr, stridx);
18123 DUK_ASSERT(key != NULL);
18124 DUK_ASSERT(duk_require_tval(thr, -1) != NULL);
18125
18126 duk_hobject_define_property_internal(thr, obj, key, desc_flags);
18127 /* value popped by call */
18128}
18129
18132 (duk_idx_t) (duk_int8_t) (packed_args >> 24),
18133 (duk_small_uint_t) (packed_args >> 8) & 0xffffUL,
18134 (duk_small_uint_t) (packed_args & 0xffL));
18135}
18136
18137#if 0 /*unused*/
18138DUK_INTERNAL void duk_xdef_prop_stridx_builtin(duk_hthread *thr, duk_idx_t obj_idx, duk_small_uint_t stridx, duk_small_int_t builtin_idx, duk_small_uint_t desc_flags) {
18139 duk_hobject *obj;
18140 duk_hstring *key;
18141
18144 DUK_ASSERT_BIDX_VALID(builtin_idx);
18145
18146 obj = duk_require_hobject(thr, obj_idx);
18147 DUK_ASSERT(obj != NULL);
18148 key = DUK_HTHREAD_GET_STRING(thr, stridx);
18149 DUK_ASSERT(key != NULL);
18151 duk_push_hobject(thr, thr->builtins[builtin_idx]);
18152 duk_hobject_define_property_internal(thr, obj, key, desc_flags);
18153 /* value popped by call */
18154}
18155#endif
18156
18157/* This is a rare property helper; it sets the global thrower (E5 Section 13.2.3)
18158 * setter/getter into an object property. This is needed by the 'arguments'
18159 * object creation code, function instance creation code, and Function.prototype.bind().
18160 */
18164
18165 obj_idx = duk_require_normalize_index(thr, obj_idx);
18166 duk_push_hstring_stridx(thr, stridx);
18168 duk_dup_top(thr);
18170}
18171
18172/* Object.getOwnPropertyDescriptor() equivalent C binding. */
18175 DUK_UNREF(flags); /* no flags defined yet */
18176
18177 duk_hobject_object_get_own_property_descriptor(thr, obj_idx); /* [ ... key ] -> [ ... desc ] */
18178}
18179
18180/* Object.defineProperty() equivalent C binding. */
18181DUK_EXTERNAL void duk_def_prop(duk_hthread *thr, duk_idx_t obj_idx, duk_uint_t flags) {
18182 duk_idx_t idx_base;
18183 duk_hobject *obj;
18184 duk_hstring *key;
18185 duk_idx_t idx_value;
18186 duk_hobject *get;
18187 duk_hobject *set;
18188 duk_uint_t is_data_desc;
18189 duk_uint_t is_acc_desc;
18190
18192
18193 obj = duk_require_hobject(thr, obj_idx);
18194
18195 is_data_desc = flags & (DUK_DEFPROP_HAVE_VALUE | DUK_DEFPROP_HAVE_WRITABLE);
18196 is_acc_desc = flags & (DUK_DEFPROP_HAVE_GETTER | DUK_DEFPROP_HAVE_SETTER);
18197 if (is_data_desc && is_acc_desc) {
18198 /* "Have" flags must not be conflicting so that they would
18199 * apply to both a plain property and an accessor at the same
18200 * time.
18201 */
18202 goto fail_invalid_desc;
18203 }
18204
18205 idx_base = duk_get_top_index(thr);
18206 if (flags & DUK_DEFPROP_HAVE_SETTER) {
18208 set = duk_get_hobject_promote_lfunc(thr, idx_base);
18209 if (set != NULL && !DUK_HOBJECT_IS_CALLABLE(set)) {
18210 goto fail_not_callable;
18211 }
18212 idx_base--;
18213 } else {
18214 set = NULL;
18215 }
18216 if (flags & DUK_DEFPROP_HAVE_GETTER) {
18218 get = duk_get_hobject_promote_lfunc(thr, idx_base);
18219 if (get != NULL && !DUK_HOBJECT_IS_CALLABLE(get)) {
18220 goto fail_not_callable;
18221 }
18222 idx_base--;
18223 } else {
18224 get = NULL;
18225 }
18226 if (flags & DUK_DEFPROP_HAVE_VALUE) {
18227 idx_value = idx_base;
18228 idx_base--;
18229 } else {
18230 idx_value = (duk_idx_t) -1;
18231 }
18232 key = duk_to_property_key_hstring(thr, idx_base);
18233 DUK_ASSERT(key != NULL);
18234
18235 duk_require_valid_index(thr, idx_base);
18236
18237 duk_hobject_define_property_helper(thr, flags /*defprop_flags*/, obj, key, idx_value, get, set, 1 /*throw_flag*/);
18238
18239 /* Clean up stack */
18240
18241 duk_set_top(thr, idx_base);
18242
18243 /* [ ... obj ... ] */
18244
18245 return;
18246
18247fail_invalid_desc:
18249 DUK_WO_NORETURN(return;);
18250
18251fail_not_callable:
18253 DUK_WO_NORETURN(return;);
18254}
18255
18256/*
18257 * Object related
18258 */
18259
18261 duk_hobject *obj;
18262
18264
18265 obj = duk_get_hobject(thr, obj_idx);
18266 if (obj) {
18267 /* Note: this may fail, caller should protect the call if necessary */
18269 }
18270}
18271
18274
18275 duk_compact(thr, -1);
18277
18278/* XXX: the duk_hobject_enum.c stack APIs should be reworked */
18279
18280DUK_EXTERNAL void duk_enum(duk_hthread *thr, duk_idx_t obj_idx, duk_uint_t enum_flags) {
18282
18283 duk_dup(thr, obj_idx);
18285 duk_hobject_enumerator_create(thr, enum_flags); /* [target] -> [enum] */
18286}
18287
18288DUK_EXTERNAL duk_bool_t duk_next(duk_hthread *thr, duk_idx_t enum_index, duk_bool_t get_value) {
18290
18291 duk_require_hobject(thr, enum_index);
18292 duk_dup(thr, enum_index);
18293 return duk_hobject_enumerator_next(thr, get_value);
18294}
18295
18296DUK_INTERNAL void duk_seal_freeze_raw(duk_hthread *thr, duk_idx_t obj_idx, duk_bool_t is_freeze) {
18297 duk_tval *tv;
18298 duk_hobject *h;
18299
18301
18302 tv = duk_require_tval(thr, obj_idx);
18303 DUK_ASSERT(tv != NULL);
18304
18305 /* Seal/freeze are quite rare in practice so it'd be nice to get the
18306 * correct behavior simply via automatic promotion (at the cost of some
18307 * memory churn). However, the promoted objects don't behave the same,
18308 * e.g. promoted lightfuncs are extensible.
18309 */
18310
18311 switch (DUK_TVAL_GET_TAG(tv)) {
18312 case DUK_TAG_BUFFER:
18313 /* Plain buffer: already sealed, but not frozen (and can't be frozen
18314 * because index properties can't be made non-writable.
18315 */
18316 if (is_freeze) {
18317 goto fail_cannot_freeze;
18318 }
18319 break;
18320 case DUK_TAG_LIGHTFUNC:
18321 /* Lightfunc: already sealed and frozen, success. */
18322 break;
18323 case DUK_TAG_OBJECT:
18324 h = DUK_TVAL_GET_OBJECT(tv);
18325 DUK_ASSERT(h != NULL);
18326 if (is_freeze && DUK_HOBJECT_IS_BUFOBJ(h)) {
18327 /* Buffer objects cannot be frozen because there's no internal
18328 * support for making virtual array indices non-writable.
18329 */
18330 DUK_DD(DUK_DDPRINT("cannot freeze a buffer object"));
18331 goto fail_cannot_freeze;
18332 }
18333 duk_hobject_object_seal_freeze_helper(thr, h, is_freeze);
18334
18335 /* Sealed and frozen objects cannot gain any more properties,
18336 * so this is a good time to compact them.
18337 */
18339 break;
18340 default:
18341 /* ES2015 Sections 19.1.2.5, 19.1.2.17 */
18342 break;
18343 }
18344 return;
18346fail_cannot_freeze:
18347 DUK_ERROR_TYPE_INVALID_ARGS(thr); /* XXX: proper error message */
18348 DUK_WO_NORETURN(return;);
18349}
18350
18351DUK_EXTERNAL void duk_seal(duk_hthread *thr, duk_idx_t obj_idx) {
18353
18354 duk_seal_freeze_raw(thr, obj_idx, 0 /*is_freeze*/);
18356
18357DUK_EXTERNAL void duk_freeze(duk_hthread *thr, duk_idx_t obj_idx) {
18359
18360 duk_seal_freeze_raw(thr, obj_idx, 1 /*is_freeze*/);
18361}
18362
18363/*
18364 * Helpers for writing multiple properties
18365 */
18366
18368 const duk_function_list_entry *ent = funcs;
18369
18371
18372 obj_idx = duk_require_normalize_index(thr, obj_idx);
18373 if (ent != NULL) {
18374 while (ent->key != NULL) {
18375 duk_push_c_function(thr, ent->value, ent->nargs);
18376 duk_put_prop_string(thr, obj_idx, ent->key);
18377 ent++;
18378 }
18379 }
18380}
18381
18383 const duk_number_list_entry *ent = numbers;
18384 duk_tval *tv;
18385
18387
18388 obj_idx = duk_require_normalize_index(thr, obj_idx);
18389 if (ent != NULL) {
18390 while (ent->key != NULL) {
18391 tv = thr->valstack_top++;
18392 DUK_ASSERT(DUK_TVAL_IS_UNDEFINED(tv)); /* value stack init policy */
18393 DUK_TVAL_SET_NUMBER_CHKFAST_SLOW(tv, ent->value); /* no need for decref/incref */
18394 duk_put_prop_string(thr, obj_idx, ent->key);
18395 ent++;
18396 }
18397 }
18398}
18399
18400/*
18401 * Shortcut for accessing global object properties
18402 */
18403
18405 duk_bool_t ret;
18408 DUK_ASSERT(thr->builtins[DUK_BIDX_GLOBAL] != NULL);
18409
18410 /* XXX: direct implementation */
18411
18413 ret = duk_get_prop_string(thr, -1, key);
18414 duk_remove_m2(thr);
18415 return ret;
18416}
18417
18419 duk_bool_t ret;
18420
18422 DUK_ASSERT(thr->builtins[DUK_BIDX_GLOBAL] != NULL);
18423
18424 /* XXX: direct implementation */
18425
18427 ret = duk_get_prop_lstring(thr, -1, key, key_len);
18428 duk_remove_m2(thr);
18429 return ret;
18430}
18431
18432#if !defined(DUK_USE_PREFER_SIZE)
18434 duk_bool_t ret;
18435
18438 DUK_ASSERT(key[key_len] == (char) 0);
18439
18440 /* XXX: direct implementation */
18441
18443 ret = duk_get_prop_literal_raw(thr, -1, key, key_len);
18444 duk_remove_m2(thr);
18445 return ret;
18446}
18447#endif
18448
18450 duk_bool_t ret;
18453 DUK_ASSERT(thr->builtins[DUK_BIDX_GLOBAL] != NULL);
18454
18455 /* XXX: direct implementation */
18456
18458 ret = duk_get_prop_heapptr(thr, -1, ptr);
18459 duk_remove_m2(thr);
18460 return ret;
18461}
18462
18464 duk_bool_t ret;
18465
18467 DUK_ASSERT(thr->builtins[DUK_BIDX_GLOBAL] != NULL);
18468
18469 /* XXX: direct implementation */
18470
18472 duk_insert(thr, -2);
18473 ret = duk_put_prop_string(thr, -2, key); /* [ ... global val ] -> [ ... global ] */
18474 duk_pop(thr);
18475 return ret;
18476}
18477
18479 duk_bool_t ret;
18480
18483
18484 /* XXX: direct implementation */
18485
18487 duk_insert(thr, -2);
18488 ret = duk_put_prop_lstring(thr, -2, key, key_len); /* [ ... global val ] -> [ ... global ] */
18489 duk_pop(thr);
18490 return ret;
18491}
18492
18493#if !defined(DUK_USE_PREFER_SIZE)
18495 duk_bool_t ret;
18496
18498 DUK_ASSERT(thr->builtins[DUK_BIDX_GLOBAL] != NULL);
18499 DUK_ASSERT(key[key_len] == (char) 0);
18500
18501 /* XXX: direct implementation */
18502
18504 duk_insert(thr, -2);
18505 ret = duk_put_prop_literal_raw(thr, -2, key, key_len); /* [ ... global val ] -> [ ... global ] */
18506 duk_pop(thr);
18507 return ret;
18508}
18509#endif
18510
18512 duk_bool_t ret;
18513
18515 DUK_ASSERT(thr->builtins[DUK_BIDX_GLOBAL] != NULL);
18516
18517 /* XXX: direct implementation */
18520 duk_insert(thr, -2);
18521 ret = duk_put_prop_heapptr(thr, -2, ptr); /* [ ... global val ] -> [ ... global ] */
18522 duk_pop(thr);
18523 return ret;
18524}
18525
18526/*
18527 * ES2015 GetMethod()
18528 */
18529
18531 (void) duk_get_prop_stridx(thr, idx, stridx);
18532 if (duk_is_null_or_undefined(thr, -1)) {
18534 return 0;
18536 if (!duk_is_callable(thr, -1)) {
18538 DUK_WO_NORETURN(return 0;);
18539 }
18540 return 1;
18541}
18542
18543/*
18544 * Object prototype
18545 */
18546
18548 duk_hobject *obj;
18549 duk_hobject *proto;
18550
18552
18553 obj = duk_require_hobject(thr, idx);
18554 DUK_ASSERT(obj != NULL);
18555
18556 /* XXX: shared helper for duk_push_hobject_or_undefined()? */
18557 proto = DUK_HOBJECT_GET_PROTOTYPE(thr->heap, obj);
18558 if (proto) {
18559 duk_push_hobject(thr, proto);
18560 } else {
18561 duk_push_undefined(thr);
18562 }
18563}
18564
18566 duk_hobject *obj;
18567 duk_hobject *proto;
18568
18570
18571 obj = duk_require_hobject(thr, idx);
18572 DUK_ASSERT(obj != NULL);
18574 proto = duk_get_hobject(thr, -1);
18575 /* proto can also be NULL here (allowed explicitly) */
18576
18577#if defined(DUK_USE_ROM_OBJECTS)
18579 DUK_ERROR_TYPE(thr, DUK_STR_NOT_CONFIGURABLE); /* XXX: "read only object"? */
18580 DUK_WO_NORETURN(return;);
18581 }
18582#endif
18583
18584 DUK_HOBJECT_SET_PROTOTYPE_UPDREF(thr, obj, proto);
18585
18586 duk_pop(thr);
18587}
18588
18590 duk_hobject *obj;
18591
18593
18594 obj = duk_require_hobject(thr, idx);
18595 DUK_ASSERT(obj != NULL);
18596
18597#if defined(DUK_USE_ROM_OBJECTS)
18599 DUK_ERROR_TYPE(thr, DUK_STR_NOT_CONFIGURABLE); /* XXX: "read only object"? */
18600 DUK_WO_NORETURN(return;);
18601 }
18602#endif
18603
18604 DUK_HOBJECT_SET_PROTOTYPE_UPDREF(thr, obj, NULL);
18605}
18606
18608 duk_hobject *obj;
18609 duk_hobject *proto;
18610
18612
18613 obj = duk_require_hobject(thr, idx);
18614 DUK_ASSERT(obj != NULL);
18615
18616 proto = DUK_HOBJECT_GET_PROTOTYPE(thr->heap, obj);
18617 return (proto == NULL);
18619
18620/*
18621 * Object finalizer
18622 */
18623
18624#if defined(DUK_USE_FINALIZER_SUPPORT)
18625/* XXX: these could be implemented as macros calling an internal function
18626 * directly.
18627 * XXX: same issue as with Duktape.fin: there's no way to delete the property
18628 * now (just set it to undefined).
18629 */
18632
18633 /* This get intentionally walks the inheritance chain at present,
18634 * which matches how the effective finalizer property is also
18635 * looked up in GC.
18636 */
18638}
18639
18641 duk_hobject *h;
18642 duk_bool_t callable;
18643
18645
18646 h = duk_require_hobject(thr, idx); /* Get before 'put' so that 'idx' is correct. */
18647 callable = duk_is_callable(thr, -1);
18648
18649 /* At present finalizer is stored as a hidden Symbol, with normal
18650 * inheritance and access control. As a result, finalizer cannot
18651 * currently be set on a non-extensible (sealed or frozen) object.
18652 * It might be useful to allow it.
18653 */
18655
18656 /* In addition to setting the finalizer property, keep a "have
18657 * finalizer" flag in duk_hobject in sync so that refzero can do
18658 * a very quick finalizer check by walking the prototype chain
18659 * and checking the flag alone. (Note that this means that just
18660 * setting _Finalizer on an object won't affect finalizer checks.)
18661 *
18662 * NOTE: if the argument is a Proxy object, this flag will be set
18663 * on the Proxy, not the target. As a result, the target won't get
18664 * a finalizer flag and the Proxy also won't be finalized as there's
18665 * an explicit Proxy check in finalization now.
18666 */
18667 if (callable) {
18669 } else {
18671 }
18672}
18673#else /* DUK_USE_FINALIZER_SUPPORT */
18676 DUK_UNREF(idx);
18678 DUK_WO_NORETURN(return;);
18679}
18680
18683 DUK_UNREF(idx);
18685 DUK_WO_NORETURN(return;);
18686}
18687#endif /* DUK_USE_FINALIZER_SUPPORT */
18688/*
18689 * Random numbers
18690 */
18691
18692/* #include duk_internal.h -> already included */
18693
18696}
18697/*
18698 * API calls related to general value stack manipulation: resizing the value
18699 * stack, pushing and popping values, type checking and reading values,
18700 * coercing values, etc.
18701 *
18702 * Also contains internal functions (such as duk_get_tval()), defined
18703 * in duk_api_internal.h, with semantics similar to the public API.
18704 */
18705
18706/* XXX: repetition of stack pre-checks -> helper or macro or inline */
18707/* XXX: shared api error strings, and perhaps even throw code for rare cases? */
18708
18709/* #include duk_internal.h -> already included */
18710
18712 * Forward declarations
18713 */
18714
18717
18718/*
18719 * Global state for working around missing variadic macros
18720 */
18721
18722#if !defined(DUK_USE_VARIADIC_MACROS)
18723DUK_EXTERNAL const char *duk_api_global_filename = NULL;
18725#endif
18726
18728 * Misc helpers
18729 */
18730
18731DUK_LOCAL const char * const duk__symbol_type_strings[4] = { "hidden", "global", "local", "wellknown" };
18732
18733#if !defined(DUK_USE_PACKED_TVAL)
18738};
18743};
18744#endif /* !DUK_USE_PACKED_TVAL */
18746/* Assert that there's room for one value. */
18747#define DUK__ASSERT_SPACE() \
18748 do { \
18749 DUK_ASSERT(!(thr->valstack_top >= thr->valstack_end)); \
18750 } while (0)
18751
18752/* Check that there's room to push one value. */
18753#if defined(DUK_USE_VALSTACK_UNSAFE)
18754/* Faster but value stack overruns are memory unsafe. */
18755#define DUK__CHECK_SPACE() DUK__ASSERT_SPACE()
18756#else
18757#define DUK__CHECK_SPACE() \
18758 do { \
18759 if (DUK_UNLIKELY(thr->valstack_top >= thr->valstack_end)) { \
18760 DUK_ERROR_RANGE_PUSH_BEYOND(thr); \
18761 } \
18762 } while (0)
18763#endif
18764
18766 const duk_uint8_t *data;
18767 duk_size_t len;
18768
18769 DUK_ASSERT(h != NULL);
18771 DUK_ASSERT(DUK_HSTRING_GET_BYTELEN(h) >= 1); /* always true, symbol prefix */
18772
18773 data = (const duk_uint8_t *) DUK_HSTRING_GET_DATA(h);
18774 len = DUK_HSTRING_GET_BYTELEN(h);
18775 DUK_ASSERT(len >= 1);
18776
18777 /* XXX: differentiate between 0x82 and 0xff (hidden vs. internal?)? */
18778
18779 if (data[0] == 0xffU) {
18781 } else if (data[0] == 0x82U) {
18783 } else if (data[0] == 0x80U) {
18785 } else if (data[len - 1] != 0xffU) {
18786 return DUK_SYMBOL_TYPE_LOCAL;
18787 } else {
18790}
18791
18793 duk_small_uint_t idx;
18794 idx = duk__get_symbol_type(h);
18795 DUK_ASSERT(idx < sizeof(duk__symbol_type_strings));
18796 return duk__symbol_type_strings[idx];
18797}
18798
18800
18802 duk_tval *tv;
18804 duk_double_t d;
18805
18806 tv = duk_get_tval_or_unused(thr, idx);
18807 DUK_ASSERT(tv != NULL);
18808
18809 /*
18810 * Special cases like NaN and +/- Infinity are handled explicitly
18811 * because a plain C coercion from double to int handles these cases
18812 * in undesirable ways. For instance, NaN may coerce to INT_MIN
18813 * (not zero), and INT_MAX + 1 may coerce to INT_MIN (not INT_MAX).
18814 *
18815 * This double-to-int coercion differs from ToInteger() because it
18816 * has a finite range (ToInteger() allows e.g. +/- Infinity). It
18817 * also differs from ToInt32() because the INT_MIN/INT_MAX clamping
18818 * depends on the size of the int type on the platform. In particular,
18819 * on platforms with a 64-bit int type, the full range is allowed.
18820 */
18821
18822#if defined(DUK_USE_FASTINT)
18823 if (DUK_TVAL_IS_FASTINT(tv)) {
18824 duk_int64_t t = DUK_TVAL_GET_FASTINT(tv);
18825#if (DUK_INT_MAX <= 0x7fffffffL)
18826 /* Clamping only necessary for 32-bit ints. */
18827 if (t < DUK_INT_MIN) {
18828 t = DUK_INT_MIN;
18829 } else if (t > DUK_INT_MAX) {
18830 t = DUK_INT_MAX;
18831 }
18832#endif
18833 return (duk_int_t) t;
18834 }
18835#endif
18836
18837 if (DUK_TVAL_IS_NUMBER(tv)) {
18838 d = DUK_TVAL_GET_NUMBER(tv);
18840 if (c == DUK_FP_NAN) {
18841 return 0;
18842 } else if (d < (duk_double_t) DUK_INT_MIN) {
18843 /* covers -Infinity */
18844 return DUK_INT_MIN;
18845 } else if (d > (duk_double_t) DUK_INT_MAX) {
18846 /* covers +Infinity */
18847 return DUK_INT_MAX;
18848 } else {
18849 /* coerce towards zero */
18850 return (duk_int_t) d;
18851 }
18852 }
18853
18854 if (require) {
18856 DUK_WO_NORETURN(return 0;);
18857 }
18858
18859 return def_value;
18860}
18861
18863 duk_tval *tv;
18865 duk_double_t d;
18866
18867 /* Same as above but for unsigned int range. */
18868
18869 tv = duk_get_tval_or_unused(thr, idx);
18870 DUK_ASSERT(tv != NULL);
18871
18872#if defined(DUK_USE_FASTINT)
18873 if (DUK_TVAL_IS_FASTINT(tv)) {
18874 duk_int64_t t = DUK_TVAL_GET_FASTINT(tv);
18875 if (t < 0) {
18876 t = 0;
18877 }
18878#if (DUK_UINT_MAX <= 0xffffffffUL)
18879 /* Clamping only necessary for 32-bit ints. */
18880 else if (t > DUK_UINT_MAX) {
18881 t = DUK_UINT_MAX;
18882 }
18883#endif
18884 return (duk_uint_t) t;
18885 }
18886#endif
18887
18888 if (DUK_TVAL_IS_NUMBER(tv)) {
18889 d = DUK_TVAL_GET_NUMBER(tv);
18891 if (c == DUK_FP_NAN) {
18892 return 0;
18893 } else if (d < 0.0) {
18894 /* covers -Infinity */
18895 return (duk_uint_t) 0;
18896 } else if (d > (duk_double_t) DUK_UINT_MAX) {
18897 /* covers +Infinity */
18898 return (duk_uint_t) DUK_UINT_MAX;
18899 } else {
18900 /* coerce towards zero */
18901 return (duk_uint_t) d;
18902 }
18903 }
18904
18905 if (require) {
18907 DUK_WO_NORETURN(return 0;);
18908 }
18909
18910 return def_value;
18911}
18912
18913/*
18914 * Stack index validation/normalization and getting a stack duk_tval ptr.
18915 *
18916 * These are called by many API entrypoints so the implementations must be
18917 * fast and "inlined".
18918 *
18919 * There's some repetition because of this; keep the functions in sync.
18920 */
18921
18923 duk_uidx_t vs_size;
18924 duk_uidx_t uidx;
18925
18928
18929 /* Care must be taken to avoid pointer wrapping in the index
18930 * validation. For instance, on a 32-bit platform with 8-byte
18931 * duk_tval the index 0x20000000UL would wrap the memory space
18932 * once.
18933 */
18934
18935 /* Assume value stack sizes (in elements) fits into duk_idx_t. */
18937 vs_size = (duk_uidx_t) (thr->valstack_top - thr->valstack_bottom);
18938 DUK_ASSERT_DISABLE(vs_size >= 0); /* unsigned */
18939
18940 if (idx < 0) {
18941 uidx = vs_size + (duk_uidx_t) idx;
18942 } else {
18943 /* since index non-negative */
18945 uidx = (duk_uidx_t) idx;
18946 }
18947
18948 /* DUK_INVALID_INDEX won't be accepted as a valid index. */
18949 DUK_ASSERT(vs_size + (duk_uidx_t) DUK_INVALID_INDEX >= vs_size);
18950
18951 if (DUK_LIKELY(uidx < vs_size)) {
18952 return (duk_idx_t) uidx;
18953 }
18954 return DUK_INVALID_INDEX;
18955}
18956
18958 duk_uidx_t vs_size;
18959 duk_uidx_t uidx;
18960
18963
18965 vs_size = (duk_uidx_t) (thr->valstack_top - thr->valstack_bottom);
18966 DUK_ASSERT_DISABLE(vs_size >= 0); /* unsigned */
18967
18968 if (idx < 0) {
18969 uidx = vs_size + (duk_uidx_t) idx;
18970 } else {
18972 uidx = (duk_uidx_t) idx;
18974
18975 /* DUK_INVALID_INDEX won't be accepted as a valid index. */
18976 DUK_ASSERT(vs_size + (duk_uidx_t) DUK_INVALID_INDEX >= vs_size);
18977
18978 if (DUK_LIKELY(uidx < vs_size)) {
18979 return (duk_idx_t) uidx;
18980 }
18981 DUK_ERROR_RANGE_INDEX(thr, idx);
18982 DUK_WO_NORETURN(return 0;);
18983}
18984
18986 duk_uidx_t vs_size;
18987 duk_uidx_t uidx;
18988
18991
18993 vs_size = (duk_uidx_t) (thr->valstack_top - thr->valstack_bottom);
18994 DUK_ASSERT_DISABLE(vs_size >= 0); /* unsigned */
18995
18996 if (idx < 0) {
18997 uidx = vs_size + (duk_uidx_t) idx;
18998 } else {
19000 uidx = (duk_uidx_t) idx;
19001 }
19002
19003 /* DUK_INVALID_INDEX won't be accepted as a valid index. */
19004 DUK_ASSERT(vs_size + (duk_uidx_t) DUK_INVALID_INDEX >= vs_size);
19005
19006 if (DUK_LIKELY(uidx < vs_size)) {
19007 return thr->valstack_bottom + uidx;
19009 return NULL;
19010}
19011
19012/* Variant of duk_get_tval() which is guaranteed to return a valid duk_tval
19013 * pointer. When duk_get_tval() would return NULL, this variant returns a
19014 * pointer to a duk_tval with tag DUK_TAG_UNUSED. This allows the call site
19015 * to avoid an unnecessary NULL check which sometimes leads to better code.
19016 * The return duk_tval is read only (at least for the UNUSED value).
19017 */
19019
19021 duk_tval *tv;
19022
19024
19025 tv = duk_get_tval(thr, idx);
19026 if (tv != NULL) {
19027 return tv;
19028 }
19030}
19031
19033 duk_uidx_t vs_size;
19034 duk_uidx_t uidx;
19035
19038
19040 vs_size = (duk_uidx_t) (thr->valstack_top - thr->valstack_bottom);
19041 DUK_ASSERT_DISABLE(vs_size >= 0); /* unsigned */
19042
19043 /* Use unsigned arithmetic to optimize comparison. */
19044 if (idx < 0) {
19045 uidx = vs_size + (duk_uidx_t) idx;
19046 } else {
19048 uidx = (duk_uidx_t) idx;
19049 }
19051 /* DUK_INVALID_INDEX won't be accepted as a valid index. */
19052 DUK_ASSERT(vs_size + (duk_uidx_t) DUK_INVALID_INDEX >= vs_size);
19053
19054 if (DUK_LIKELY(uidx < vs_size)) {
19055 return thr->valstack_bottom + uidx;
19056 }
19057 DUK_ERROR_RANGE_INDEX(thr, idx);
19058 DUK_WO_NORETURN(return NULL;);
19059}
19060
19061/* Non-critical. */
19065
19066 return (duk_normalize_index(thr, idx) >= 0);
19067}
19068
19069/* Non-critical. */
19073
19074 if (DUK_UNLIKELY(duk_normalize_index(thr, idx) < 0)) {
19075 DUK_ERROR_RANGE_INDEX(thr, idx);
19076 DUK_WO_NORETURN(return;);
19077 }
19078}
19079
19080/*
19081 * Value stack top handling
19082 */
19083
19086
19087 return (duk_idx_t) (thr->valstack_top - thr->valstack_bottom);
19088}
19089
19090/* Internal helper to get current top but to require a minimum top value
19091 * (TypeError if not met).
19092 */
19094 duk_idx_t ret;
19095
19097
19099 if (DUK_UNLIKELY(ret < min_top)) {
19101 DUK_WO_NORETURN(return 0;);
19102 }
19103 return ret;
19104}
19105
19106/* Set stack top within currently allocated range, but don't reallocate.
19107 * This is performance critical especially for call handling, so whenever
19108 * changing, profile and look at generated code.
19109 */
19111 duk_uidx_t vs_size;
19112 duk_uidx_t vs_limit;
19113 duk_uidx_t uidx;
19114 duk_tval *tv;
19115
19118
19121 vs_size = (duk_uidx_t) (thr->valstack_top - thr->valstack_bottom);
19122 vs_limit = (duk_uidx_t) (thr->valstack_end - thr->valstack_bottom);
19123
19124 if (idx < 0) {
19125 /* Negative indices are always within allocated stack but
19126 * must not go below zero index.
19127 */
19128 uidx = vs_size + (duk_uidx_t) idx;
19129 } else {
19130 /* Positive index can be higher than valstack top but must
19131 * not go above allocated stack (equality is OK).
19132 */
19133 uidx = (duk_uidx_t) idx;
19134 }
19135
19136 /* DUK_INVALID_INDEX won't be accepted as a valid index. */
19137 DUK_ASSERT(vs_size + (duk_uidx_t) DUK_INVALID_INDEX >= vs_size);
19138 DUK_ASSERT(vs_size + (duk_uidx_t) DUK_INVALID_INDEX >= vs_limit);
19139
19140#if defined(DUK_USE_VALSTACK_UNSAFE)
19141 DUK_ASSERT(uidx <= vs_limit);
19142 DUK_UNREF(vs_limit);
19143#else
19144 if (DUK_UNLIKELY(uidx > vs_limit)) {
19145 DUK_ERROR_RANGE_INDEX(thr, idx);
19146 DUK_WO_NORETURN(return;);
19147 }
19148#endif
19149 DUK_ASSERT(uidx <= vs_limit);
19150
19151 /* Handle change in value stack top. Respect value stack
19152 * initialization policy: 'undefined' above top. Note that
19153 * DECREF may cause a side effect that reallocates valstack,
19154 * so must relookup after DECREF.
19155 */
19156
19157 if (uidx >= vs_size) {
19158 /* Stack size increases or stays the same. */
19159#if defined(DUK_USE_ASSERTIONS)
19161
19162 count = uidx - vs_size;
19163 while (count != 0) {
19164 count--;
19165 tv = thr->valstack_top + count;
19167 }
19168#endif
19169 thr->valstack_top = thr->valstack_bottom + uidx;
19170 } else {
19171 /* Stack size decreases. */
19172#if defined(DUK_USE_REFERENCE_COUNTING)
19174 duk_tval *tv_end;
19175
19176 count = vs_size - uidx;
19177 DUK_ASSERT(count > 0);
19178 tv = thr->valstack_top;
19179 tv_end = tv - count;
19180 DUK_ASSERT(tv > tv_end); /* Because count > 0. */
19181 do {
19182 tv--;
19183 DUK_ASSERT(tv >= thr->valstack_bottom);
19185 } while (tv != tv_end);
19186 thr->valstack_top = tv_end;
19188#else /* DUK_USE_REFERENCE_COUNTING */
19190 duk_tval *tv_end;
19191
19192 count = vs_size - uidx;
19193 tv = thr->valstack_top;
19194 tv_end = tv - count;
19195 DUK_ASSERT(tv > tv_end);
19196 do {
19197 tv--;
19199 } while (tv != tv_end);
19200 thr->valstack_top = tv_end;
19201#endif /* DUK_USE_REFERENCE_COUNTING */
19202 }
19203}
19204
19205/* Internal variant with a non-negative index and no runtime size checks. */
19206#if defined(DUK_USE_PREFER_SIZE)
19209
19210 duk_set_top(thr, idx);
19211}
19212#else /* DUK_USE_PREFER_SIZE */
19214 duk_uidx_t uidx;
19215 duk_uidx_t vs_size;
19216 duk_tval *tv;
19217
19221 DUK_ASSERT(idx >= 0);
19222 DUK_ASSERT(idx <= (duk_idx_t) (thr->valstack_end - thr->valstack_bottom));
19223
19224 /* XXX: byte arithmetic */
19225 uidx = (duk_uidx_t) idx;
19226 vs_size = (duk_uidx_t) (thr->valstack_top - thr->valstack_bottom);
19227
19228 if (uidx >= vs_size) {
19229 /* Stack size increases or stays the same. */
19230#if defined(DUK_USE_ASSERTIONS)
19232
19233 count = uidx - vs_size;
19234 while (count != 0) {
19235 count--;
19236 tv = thr->valstack_top + count;
19238 }
19239#endif
19240 thr->valstack_top = thr->valstack_bottom + uidx;
19241 } else {
19242 /* Stack size decreases. */
19243#if defined(DUK_USE_REFERENCE_COUNTING)
19245 duk_tval *tv_end;
19246
19247 count = vs_size - uidx;
19248 DUK_ASSERT(count > 0);
19249 tv = thr->valstack_top;
19250 tv_end = tv - count;
19251 DUK_ASSERT(tv > tv_end); /* Because count > 0. */
19252 do {
19253 tv--;
19254 DUK_ASSERT(tv >= thr->valstack_bottom);
19256 } while (tv != tv_end);
19257 thr->valstack_top = tv_end;
19259#else /* DUK_USE_REFERENCE_COUNTING */
19261 duk_tval *tv_end;
19262
19263 count = vs_size - uidx;
19264 tv = thr->valstack_top;
19265 tv_end = tv - count;
19266 DUK_ASSERT(tv > tv_end);
19267 do {
19268 tv--;
19270 } while (tv != tv_end);
19271 thr->valstack_top = tv_end;
19272#endif /* DUK_USE_REFERENCE_COUNTING */
19273 }
19274}
19275#endif /* DUK_USE_PREFER_SIZE */
19276
19277/* Internal helper: set top to 'top', and set [idx_wipe_start,top[ to
19278 * 'undefined' (doing nothing if idx_wipe_start == top). Indices are
19279 * positive and within value stack reserve. This is used by call handling.
19280 */
19283 DUK_ASSERT(top >= 0);
19284 DUK_ASSERT(idx_wipe_start >= 0);
19285 DUK_ASSERT(idx_wipe_start <= top);
19286 DUK_ASSERT(thr->valstack_bottom + top <= thr->valstack_end);
19287 DUK_ASSERT(thr->valstack_bottom + idx_wipe_start <= thr->valstack_end);
19288
19289 duk_set_top_unsafe(thr, idx_wipe_start);
19290 duk_set_top_unsafe(thr, top);
19291}
19292
19294 duk_idx_t ret;
19295
19297
19298 ret = (duk_idx_t) (thr->valstack_top - thr->valstack_bottom) - 1;
19299 if (DUK_UNLIKELY(ret < 0)) {
19300 /* Return invalid index; if caller uses this without checking
19301 * in another API call, the index won't map to a valid stack
19302 * entry.
19303 */
19304 return DUK_INVALID_INDEX;
19305 }
19306 return ret;
19307}
19308
19309/* Internal variant: call assumes there is at least one element on the value
19310 * stack frame; this is only asserted for.
19311 */
19313 duk_idx_t ret;
19314
19316
19317 ret = (duk_idx_t) (thr->valstack_top - thr->valstack_bottom) - 1;
19318 return ret;
19319}
19320
19322 duk_idx_t ret;
19323
19325
19326 ret = (duk_idx_t) (thr->valstack_top - thr->valstack_bottom) - 1;
19327 if (DUK_UNLIKELY(ret < 0)) {
19328 DUK_ERROR_RANGE_INDEX(thr, -1);
19329 DUK_WO_NORETURN(return 0;);
19330 }
19331 return ret;
19332}
19333
19334/*
19335 * Value stack resizing.
19336 *
19337 * This resizing happens above the current "top": the value stack can be
19338 * grown or shrunk, but the "top" is not affected. The value stack cannot
19339 * be resized to a size below the current reserve.
19340 *
19341 * The low level reallocation primitive must carefully recompute all value
19342 * stack pointers, and must also work if ALL pointers are NULL. The resize
19343 * is quite tricky because the valstack realloc may cause a mark-and-sweep,
19344 * which may run finalizers. Running finalizers may resize the valstack
19345 * recursively (the same value stack we're working on). So, after realloc
19346 * returns, we know that the valstack bottom, top, and reserve should still
19347 * be the same (there should not be live values above the "top"), but its
19348 * underlying size, alloc_end, and base pointer may have changed.
19349 *
19350 * 'new_size' is known to be <= DUK_USE_VALSTACK_LIMIT, which ensures that
19351 * size_t and pointer arithmetic won't wrap in duk__resize_valstack().
19352 */
19353
19354/* Low level valstack resize primitive, used for both grow and shrink. All
19355 * adjustments for slack etc have already been done. Doesn't throw but does
19356 * have allocation side effects.
19357 */
19359 duk_tval *pre_valstack;
19360 duk_tval *pre_bottom;
19361 duk_tval *pre_top;
19362 duk_tval *pre_end;
19363 duk_tval *pre_alloc_end;
19364 duk_ptrdiff_t ptr_diff;
19365 duk_tval *new_valstack;
19366 duk_size_t new_alloc_size;
19367 duk_tval *tv_prev_alloc_end;
19368 duk_tval *p;
19369
19371 DUK_ASSERT(thr->valstack_bottom >= thr->valstack);
19373 DUK_ASSERT(thr->valstack_end >= thr->valstack_top);
19375 DUK_ASSERT((duk_size_t) (thr->valstack_top - thr->valstack) <= new_size); /* can't resize below 'top' */
19376 DUK_ASSERT(new_size <= DUK_USE_VALSTACK_LIMIT); /* valstack limit caller has check, prevents wrapping */
19377 DUK_ASSERT(new_size <= DUK_SIZE_MAX / sizeof(duk_tval)); /* specific assert for wrapping */
19378
19379 /* Pre-realloc pointer copies for asserts and debug logs. */
19380 pre_valstack = thr->valstack;
19381 pre_bottom = thr->valstack_bottom;
19382 pre_top = thr->valstack_top;
19383 pre_end = thr->valstack_end;
19384 pre_alloc_end = thr->valstack_alloc_end;
19385
19386 DUK_UNREF(pre_valstack);
19387 DUK_UNREF(pre_bottom);
19388 DUK_UNREF(pre_top);
19389 DUK_UNREF(pre_end);
19390 DUK_UNREF(pre_alloc_end);
19391
19392 /* If finalizer torture enabled, force base pointer change every time
19393 * when it would be allowed.
19394 */
19395#if defined(DUK_USE_FINALIZER_TORTURE)
19396 if (thr->heap->pf_prevent_count == 0) {
19397 duk_hthread_valstack_torture_realloc(thr);
19398 }
19399#endif
19400
19401 /* Allocate a new valstack using DUK_REALLOC_DIRECT() to deal with
19402 * a side effect changing the base pointer.
19403 */
19404 new_alloc_size = sizeof(duk_tval) * new_size;
19405 new_valstack = (duk_tval *) DUK_REALLOC_INDIRECT(thr->heap, duk_hthread_get_valstack_ptr, (void *) thr, new_alloc_size);
19406 if (DUK_UNLIKELY(new_valstack == NULL)) {
19407 /* Because new_size != 0, if condition doesn't need to be
19408 * (new_valstack != NULL || new_size == 0).
19409 */
19410 DUK_ASSERT(new_size != 0);
19411 DUK_D(DUK_DPRINT("failed to resize valstack to %lu entries (%lu bytes)",
19412 (unsigned long) new_size,
19413 (unsigned long) new_alloc_size));
19414 return 0;
19415 }
19416
19417 /* Debug log any changes in pointer(s) by side effects. These don't
19418 * necessarily imply any incorrect behavior, but should be rare in
19419 * practice.
19420 */
19421#if defined(DUK_USE_DEBUG)
19422 if (thr->valstack != pre_valstack) {
19423 DUK_D(DUK_DPRINT("valstack base pointer changed during valstack resize: %p -> %p",
19424 (void *) pre_valstack,
19425 (void *) thr->valstack));
19426 }
19427 if (thr->valstack_bottom != pre_bottom) {
19428 DUK_D(DUK_DPRINT("valstack bottom pointer changed during valstack resize: %p -> %p",
19429 (void *) pre_bottom,
19430 (void *) thr->valstack_bottom));
19431 }
19432 if (thr->valstack_top != pre_top) {
19433 DUK_D(DUK_DPRINT("valstack top pointer changed during valstack resize: %p -> %p",
19434 (void *) pre_top,
19435 (void *) thr->valstack_top));
19436 }
19437 if (thr->valstack_end != pre_end) {
19438 DUK_D(DUK_DPRINT("valstack end pointer changed during valstack resize: %p -> %p",
19439 (void *) pre_end,
19440 (void *) thr->valstack_end));
19441 }
19442 if (thr->valstack_alloc_end != pre_alloc_end) {
19443 DUK_D(DUK_DPRINT("valstack alloc_end pointer changed during valstack resize: %p -> %p",
19444 (void *) pre_alloc_end,
19445 (void *) thr->valstack_alloc_end));
19446 }
19447#endif
19448
19449 /* Assertions: offsets for bottom, top, and end (reserve) must not
19450 * have changed even with side effects because they are always
19451 * restored in unwind. For alloc_end there's no guarantee: it may
19452 * have grown or shrunk (but remain above 'end').
19453 */
19454 DUK_ASSERT(thr->valstack_bottom - thr->valstack == pre_bottom - pre_valstack);
19455 DUK_ASSERT(thr->valstack_top - thr->valstack == pre_top - pre_valstack);
19456 DUK_ASSERT(thr->valstack_end - thr->valstack == pre_end - pre_valstack);
19458
19459 /* Write new pointers. Most pointers can be handled as a pointer
19460 * difference.
19461 */
19462 ptr_diff = (duk_ptrdiff_t) ((duk_uint8_t *) new_valstack - (duk_uint8_t *) thr->valstack);
19463 tv_prev_alloc_end = (duk_tval *) (void *) ((duk_uint8_t *) thr->valstack_alloc_end + ptr_diff);
19464 thr->valstack = new_valstack;
19465 thr->valstack_bottom = (duk_tval *) (void *) ((duk_uint8_t *) thr->valstack_bottom + ptr_diff);
19466 thr->valstack_top = (duk_tval *) (void *) ((duk_uint8_t *) thr->valstack_top + ptr_diff);
19467 thr->valstack_end = (duk_tval *) (void *) ((duk_uint8_t *) thr->valstack_end + ptr_diff);
19468 thr->valstack_alloc_end = (duk_tval *) (void *) ((duk_uint8_t *) new_valstack + new_alloc_size);
19469
19470 /* Assertions: pointer sanity after pointer updates. */
19471 DUK_ASSERT(thr->valstack_bottom >= thr->valstack);
19473 DUK_ASSERT(thr->valstack_end >= thr->valstack_top);
19475
19476 DUK_D(DUK_DPRINT("resized valstack %lu -> %lu elements (%lu -> %lu bytes): "
19477 "base=%p -> %p, bottom=%p -> %p (%ld), top=%p -> %p (%ld), "
19478 "end=%p -> %p (%ld), alloc_end=%p -> %p (%ld);"
19479 " tv_prev_alloc_end=%p (-> %ld inits; <0 means shrink)",
19480 (unsigned long) (pre_alloc_end - pre_valstack),
19481 (unsigned long) new_size,
19482 (unsigned long) ((duk_uint8_t *) pre_alloc_end - (duk_uint8_t *) pre_valstack),
19483 (unsigned long) new_alloc_size,
19484 (void *) pre_valstack,
19485 (void *) thr->valstack,
19486 (void *) pre_bottom,
19487 (void *) thr->valstack_bottom,
19488 (long) (thr->valstack_bottom - thr->valstack),
19489 (void *) pre_top,
19490 (void *) thr->valstack_top,
19491 (long) (thr->valstack_top - thr->valstack),
19492 (void *) pre_end,
19493 (void *) thr->valstack_end,
19494 (long) (thr->valstack_end - thr->valstack),
19495 (void *) pre_alloc_end,
19496 (void *) thr->valstack_alloc_end,
19497 (long) (thr->valstack_alloc_end - thr->valstack),
19498 (void *) tv_prev_alloc_end,
19499 (long) (thr->valstack_alloc_end - tv_prev_alloc_end)));
19500
19501 /* If allocation grew, init any new slots to 'undefined'. */
19502 p = tv_prev_alloc_end;
19503 while (p < thr->valstack_alloc_end) {
19504 /* Never executed if new size is smaller. */
19506 p++;
19507 }
19508
19509 /* Assert for value stack initialization policy. */
19510#if defined(DUK_USE_ASSERTIONS)
19511 p = thr->valstack_top;
19512 while (p < thr->valstack_alloc_end) {
19514 p++;
19515 }
19516#endif
19517
19518 return 1;
19519}
19520
19522 duk_size_t min_size;
19523 duk_size_t new_size;
19524
19525 DUK_ASSERT(min_bytes / sizeof(duk_tval) * sizeof(duk_tval) == min_bytes);
19526 min_size = min_bytes / sizeof(duk_tval); /* from bytes to slots */
19527
19528#if defined(DUK_USE_VALSTACK_GROW_SHIFT)
19529 /* New size is minimum size plus a proportional slack, e.g. shift of
19530 * 2 means a 25% slack.
19531 */
19532 new_size = min_size + (min_size >> DUK_USE_VALSTACK_GROW_SHIFT);
19533#else
19534 /* New size is tight with no slack. This is sometimes preferred in
19535 * low memory environments.
19536 */
19537 new_size = min_size;
19538#endif
19539
19540 if (DUK_UNLIKELY(new_size > DUK_USE_VALSTACK_LIMIT || new_size < min_size /*wrap*/)) {
19541 /* Note: may be triggered even if minimal new_size would not reach the limit,
19542 * plan limit accordingly.
19543 */
19544 if (throw_on_error) {
19546 DUK_WO_NORETURN(return 0;);
19547 }
19548 return 0;
19549 }
19550
19551 if (duk__resize_valstack(thr, new_size) == 0) {
19552 if (throw_on_error) {
19554 DUK_WO_NORETURN(return 0;);
19555 }
19556 return 0;
19557 }
19558
19559 thr->valstack_end = thr->valstack + min_size;
19561
19562 return 1;
19563}
19564
19565/* Hot, inlined value stack grow check. Because value stack almost never
19566 * grows, the actual resize call is in a NOINLINE helper.
19567 */
19569 duk_tval *tv;
19570
19571 tv = (duk_tval *) (void *) ((duk_uint8_t *) thr->valstack + min_bytes);
19572 if (DUK_LIKELY(thr->valstack_end >= tv)) {
19573 return;
19575 if (DUK_LIKELY(thr->valstack_alloc_end >= tv)) {
19576 /* Values in [valstack_top,valstack_alloc_end[ are initialized
19577 * to 'undefined' so we can just move the end pointer.
19578 */
19579 thr->valstack_end = tv;
19580 return;
19581 }
19582 (void) duk__valstack_grow(thr, min_bytes, 1 /*throw_on_error*/);
19583}
19584
19585/* Hot, inlined value stack grow check which doesn't throw. */
19587 duk_tval *tv;
19588
19589 tv = (duk_tval *) (void *) ((duk_uint8_t *) thr->valstack + min_bytes);
19590 if (DUK_LIKELY(thr->valstack_end >= tv)) {
19591 return 1;
19592 }
19593 if (DUK_LIKELY(thr->valstack_alloc_end >= tv)) {
19594 thr->valstack_end = tv;
19595 return 1;
19596 }
19597 return duk__valstack_grow(thr, min_bytes, 0 /*throw_on_error*/);
19598}
19599
19600/* Value stack shrink check, called from mark-and-sweep. */
19602 duk_size_t alloc_bytes;
19603 duk_size_t reserve_bytes;
19604 duk_size_t shrink_bytes;
19605
19606 alloc_bytes = (duk_size_t) ((duk_uint8_t *) thr->valstack_alloc_end - (duk_uint8_t *) thr->valstack);
19607 reserve_bytes = (duk_size_t) ((duk_uint8_t *) thr->valstack_end - (duk_uint8_t *) thr->valstack);
19608 DUK_ASSERT(alloc_bytes >= reserve_bytes);
19609
19610 /* We're free to shrink the value stack allocation down to
19611 * reserve_bytes but not more. If 'snug' (emergency GC)
19612 * shrink whatever we can. Otherwise only shrink if the new
19613 * size would be considerably smaller.
19614 */
19615
19616#if defined(DUK_USE_VALSTACK_SHRINK_CHECK_SHIFT)
19617 if (snug) {
19618 shrink_bytes = reserve_bytes;
19619 } else {
19620 duk_size_t proportion, slack;
19621
19622 /* Require that value stack shrinks by at least X% of its
19623 * current size. For example, shift of 2 means at least
19624 * 25%. The proportion is computed as bytes and may not
19625 * be a multiple of sizeof(duk_tval); that's OK here.
19626 */
19627 proportion = alloc_bytes >> DUK_USE_VALSTACK_SHRINK_CHECK_SHIFT;
19628 if (alloc_bytes - reserve_bytes < proportion) {
19629 /* Too little would be freed, do nothing. */
19630 return;
19631 }
19632
19633 /* Keep a slack after shrinking. The slack is again a
19634 * proportion of the current size (the proportion should
19635 * of course be smaller than the check proportion above).
19636 */
19637#if defined(DUK_USE_VALSTACK_SHRINK_SLACK_SHIFT)
19639 slack = alloc_bytes >> DUK_USE_VALSTACK_SHRINK_SLACK_SHIFT;
19640#else
19641 slack = 0;
19642#endif
19643 shrink_bytes = reserve_bytes + slack / sizeof(duk_tval) * sizeof(duk_tval); /* multiple of duk_tval */
19644 }
19645#else /* DUK_USE_VALSTACK_SHRINK_CHECK_SHIFT */
19646 /* Always snug, useful in some low memory environments. */
19647 DUK_UNREF(snug);
19648 shrink_bytes = reserve_bytes;
19649#endif /* DUK_USE_VALSTACK_SHRINK_CHECK_SHIFT */
19650
19651 DUK_D(DUK_DPRINT("valstack shrink check: alloc_bytes=%ld, reserve_bytes=%ld, shrink_bytes=%ld (unvalidated)",
19652 (long) alloc_bytes,
19653 (long) reserve_bytes,
19654 (long) shrink_bytes));
19655 DUK_ASSERT(shrink_bytes >= reserve_bytes);
19656 if (shrink_bytes >= alloc_bytes) {
19657 /* Skip if shrink target is same as current one (or higher,
19658 * though that shouldn't happen in practice).
19659 */
19660 return;
19661 }
19662 DUK_ASSERT(shrink_bytes / sizeof(duk_tval) * sizeof(duk_tval) == shrink_bytes);
19663
19664 DUK_D(DUK_DPRINT("valstack shrink check: decided to shrink, snug: %ld", (long) snug));
19665
19666 duk__resize_valstack(thr, shrink_bytes / sizeof(duk_tval));
19667}
19668
19670 duk_size_t min_new_bytes;
19671
19673 DUK_ASSERT(thr != NULL);
19674
19675 if (DUK_UNLIKELY(extra < 0 || extra > DUK_USE_VALSTACK_LIMIT)) {
19676 if (extra < 0) {
19677 /* Clamping to zero makes the API more robust to calling code
19678 * calculation errors.
19679 */
19680 extra = 0;
19681 } else {
19682 /* Cause grow check to fail without wrapping arithmetic. */
19683 extra = DUK_USE_VALSTACK_LIMIT;
19684 }
19685 }
19686
19687 min_new_bytes = (duk_size_t) ((duk_uint8_t *) thr->valstack_top - (duk_uint8_t *) thr->valstack) +
19688 sizeof(duk_tval) * ((duk_size_t) extra + DUK_VALSTACK_INTERNAL_EXTRA);
19689 return duk_valstack_grow_check_nothrow(thr, min_new_bytes);
19690}
19691
19693 duk_size_t min_new_bytes;
19694
19696 DUK_ASSERT(thr != NULL);
19697
19698 if (DUK_UNLIKELY(extra < 0 || extra > DUK_USE_VALSTACK_LIMIT)) {
19699 if (extra < 0) {
19700 /* Clamping to zero makes the API more robust to calling code
19701 * calculation errors.
19702 */
19703 extra = 0;
19704 } else {
19705 /* Cause grow check to fail without wrapping arithmetic. */
19706 extra = DUK_USE_VALSTACK_LIMIT;
19707 }
19708 }
19709
19710 min_new_bytes = (duk_size_t) ((duk_uint8_t *) thr->valstack_top - (duk_uint8_t *) thr->valstack) +
19711 sizeof(duk_tval) * ((duk_size_t) extra + DUK_VALSTACK_INTERNAL_EXTRA);
19712 duk_valstack_grow_check_throw(thr, min_new_bytes);
19713}
19714
19716 duk_size_t min_new_bytes;
19717
19719
19720 if (DUK_UNLIKELY(top < 0 || top > DUK_USE_VALSTACK_LIMIT)) {
19721 if (top < 0) {
19722 /* Clamping to zero makes the API more robust to calling code
19723 * calculation errors.
19724 */
19725 top = 0;
19726 } else {
19727 /* Cause grow check to fail without wrapping arithmetic. */
19729 }
19730 }
19731
19732 DUK_ASSERT(top >= 0);
19733 min_new_bytes = (duk_size_t) ((duk_uint8_t *) thr->valstack_bottom - (duk_uint8_t *) thr->valstack) +
19735 return duk_valstack_grow_check_nothrow(thr, min_new_bytes);
19736}
19737
19739 duk_size_t min_new_bytes;
19740
19742
19743 if (DUK_UNLIKELY(top < 0 || top > DUK_USE_VALSTACK_LIMIT)) {
19744 if (top < 0) {
19745 /* Clamping to zero makes the API more robust to calling code
19746 * calculation errors.
19747 */
19748 top = 0;
19749 } else {
19750 /* Cause grow check to fail without wrapping arithmetic. */
19752 }
19754
19755 DUK_ASSERT(top >= 0);
19756 min_new_bytes = (duk_size_t) ((duk_uint8_t *) thr->valstack_bottom - (duk_uint8_t *) thr->valstack) +
19758 duk_valstack_grow_check_throw(thr, min_new_bytes);
19759}
19760
19761/*
19762 * Basic stack manipulation: swap, dup, insert, replace, etc
19763 */
19764
19765DUK_EXTERNAL void duk_swap(duk_hthread *thr, duk_idx_t idx1, duk_idx_t idx2) {
19766 duk_tval *tv1;
19767 duk_tval *tv2;
19768 duk_tval tv_tmp;
19769
19772 tv1 = duk_require_tval(thr, idx1);
19773 DUK_ASSERT(tv1 != NULL);
19774 tv2 = duk_require_tval(thr, idx2);
19775 DUK_ASSERT(tv2 != NULL);
19776
19777 /* If tv1==tv2 this is a NOP, no check is needed */
19778 DUK_TVAL_SET_TVAL(&tv_tmp, tv1);
19779 DUK_TVAL_SET_TVAL(tv1, tv2);
19780 DUK_TVAL_SET_TVAL(tv2, &tv_tmp);
19781}
19782
19785
19786 duk_swap(thr, idx, -1);
19787}
19788
19789DUK_EXTERNAL void duk_dup(duk_hthread *thr, duk_idx_t from_idx) {
19790 duk_tval *tv_from;
19791 duk_tval *tv_to;
19795
19796 tv_from = duk_require_tval(thr, from_idx);
19797 tv_to = thr->valstack_top++;
19798 DUK_ASSERT(tv_from != NULL);
19799 DUK_ASSERT(tv_to != NULL);
19800 DUK_TVAL_SET_TVAL(tv_to, tv_from);
19801 DUK_TVAL_INCREF(thr, tv_to); /* no side effects */
19802}
19803
19805#if defined(DUK_USE_PREFER_SIZE)
19806 duk_dup(thr, -1);
19807#else
19808 duk_tval *tv_from;
19809 duk_tval *tv_to;
19810
19813
19814 if (DUK_UNLIKELY(thr->valstack_top - thr->valstack_bottom <= 0)) {
19816 DUK_WO_NORETURN(return;);
19817 }
19818 tv_from = thr->valstack_top - 1;
19819 tv_to = thr->valstack_top++;
19820 DUK_ASSERT(tv_from != NULL);
19821 DUK_ASSERT(tv_to != NULL);
19822 DUK_TVAL_SET_TVAL(tv_to, tv_from);
19823 DUK_TVAL_INCREF(thr, tv_to); /* no side effects */
19824#endif
19825}
19826
19829 duk_dup(thr, 0);
19830}
19833 duk_dup(thr, 1);
19834}
19837 duk_dup(thr, 2);
19838}
19841 duk_dup(thr, -2);
19842}
19845 duk_dup(thr, -3);
19846}
19849 duk_dup(thr, -4);
19850}
19851
19852DUK_EXTERNAL void duk_insert(duk_hthread *thr, duk_idx_t to_idx) {
19853 duk_tval *p;
19854 duk_tval *q;
19855 duk_tval tv_tmp;
19856 duk_size_t nbytes;
19857
19859
19860 p = duk_require_tval(thr, to_idx);
19861 DUK_ASSERT(p != NULL);
19862 q = duk_require_tval(thr, -1);
19863 DUK_ASSERT(q != NULL);
19864
19865 DUK_ASSERT(q >= p);
19866
19867 /* nbytes
19868 * <--------->
19869 * [ ... | p | x | x | q ]
19870 * => [ ... | q | p | x | x ]
19871 */
19872
19873 nbytes = (duk_size_t) (((duk_uint8_t *) q) - ((duk_uint8_t *) p));
19874
19875 DUK_DDD(DUK_DDDPRINT("duk_insert: to_idx=%ld, p=%p, q=%p, nbytes=%lu",
19876 (long) to_idx,
19877 (void *) p,
19878 (void *) q,
19879 (unsigned long) nbytes));
19880
19881 /* No net refcount changes. No need to special case nbytes == 0
19882 * (p == q).
19883 */
19884 DUK_TVAL_SET_TVAL(&tv_tmp, q);
19885 duk_memmove((void *) (p + 1), (const void *) p, (size_t) nbytes);
19886 DUK_TVAL_SET_TVAL(p, &tv_tmp);
19887}
19888
19891 DUK_ASSERT(idx >= 0); /* Doesn't support negative indices. */
19892
19893 duk_push_undefined(thr);
19894 duk_insert(thr, idx);
19895}
19896
19898 duk_tval *tv, *tv_end;
19899
19901 DUK_ASSERT(idx >= 0); /* Doesn't support negative indices or count. */
19902 DUK_ASSERT(count >= 0);
19903
19904 tv = duk_reserve_gap(thr, idx, count);
19905 tv_end = tv + count;
19906 while (tv != tv_end) {
19908 tv++;
19909 }
19910}
19911
19912DUK_EXTERNAL void duk_pull(duk_hthread *thr, duk_idx_t from_idx) {
19913 duk_tval *p;
19914 duk_tval *q;
19915 duk_tval tv_tmp;
19916 duk_size_t nbytes;
19917
19919
19920 /* nbytes
19921 * <--------->
19922 * [ ... | x | x | p | y | y | q ]
19923 * => [ ... | x | x | y | y | q | p ]
19924 */
19925
19926 p = duk_require_tval(thr, from_idx);
19927 DUK_ASSERT(p != NULL);
19928 q = duk_require_tval(thr, -1);
19929 DUK_ASSERT(q != NULL);
19930
19931 DUK_ASSERT(q >= p);
19932
19933 nbytes = (duk_size_t) (((duk_uint8_t *) q) - ((duk_uint8_t *) p));
19934
19935 DUK_DDD(DUK_DDDPRINT("duk_pull: from_idx=%ld, p=%p, q=%p, nbytes=%lu",
19936 (long) from_idx,
19937 (void *) p,
19938 (void *) q,
19939 (unsigned long) nbytes));
19940
19941 /* No net refcount changes. No need to special case nbytes == 0
19942 * (p == q).
19943 */
19944 DUK_TVAL_SET_TVAL(&tv_tmp, p);
19945 duk_memmove((void *) p, (const void *) (p + 1), (size_t) nbytes);
19946 DUK_TVAL_SET_TVAL(q, &tv_tmp);
19947}
19948
19949DUK_EXTERNAL void duk_replace(duk_hthread *thr, duk_idx_t to_idx) {
19950 duk_tval *tv1;
19951 duk_tval *tv2;
19952 duk_tval tv_tmp;
19953
19955
19956 tv1 = duk_require_tval(thr, -1);
19957 DUK_ASSERT(tv1 != NULL);
19958 tv2 = duk_require_tval(thr, to_idx);
19959 DUK_ASSERT(tv2 != NULL);
19960
19961 /* For tv1 == tv2, both pointing to stack top, the end result
19962 * is same as duk_pop(thr).
19963 */
19964 DUK_TVAL_SET_TVAL(&tv_tmp, tv2);
19965 DUK_TVAL_SET_TVAL(tv2, tv1);
19967 thr->valstack_top--;
19968 DUK_TVAL_DECREF(thr, &tv_tmp); /* side effects */
19969}
19970
19971DUK_EXTERNAL void duk_copy(duk_hthread *thr, duk_idx_t from_idx, duk_idx_t to_idx) {
19972 duk_tval *tv1;
19973 duk_tval *tv2;
19976
19977 tv1 = duk_require_tval(thr, from_idx);
19978 DUK_ASSERT(tv1 != NULL);
19979 tv2 = duk_require_tval(thr, to_idx);
19980 DUK_ASSERT(tv2 != NULL);
19981
19982 /* For tv1 == tv2, this is a no-op (no explicit check needed). */
19983 DUK_TVAL_SET_TVAL_UPDREF(thr, tv2, tv1); /* side effects */
19984}
19985
19987 duk_tval *p;
19988 duk_tval *q;
19989#if defined(DUK_USE_REFERENCE_COUNTING)
19990 duk_tval tv_tmp;
19991#endif
19992 duk_size_t nbytes;
19993
19995
19996 p = duk_require_tval(thr, idx);
19997 DUK_ASSERT(p != NULL);
19998 q = duk_require_tval(thr, -1);
19999 DUK_ASSERT(q != NULL);
20000
20001 DUK_ASSERT(q >= p);
20002
20003 /* nbytes zero size case
20004 * <--------->
20005 * [ ... | p | x | x | q ] [ ... | p==q ]
20006 * => [ ... | x | x | q ] [ ... ]
20007 */
20008
20009#if defined(DUK_USE_REFERENCE_COUNTING)
20010 /* use a temp: decref only when valstack reachable values are correct */
20011 DUK_TVAL_SET_TVAL(&tv_tmp, p);
20012#endif
20014 nbytes = (duk_size_t) (((duk_uint8_t *) q) - ((duk_uint8_t *) p)); /* Note: 'q' is top-1 */
20015 duk_memmove((void *) p, (const void *) (p + 1), (size_t) nbytes);
20016
20018 thr->valstack_top--;
20020#if defined(DUK_USE_REFERENCE_COUNTING)
20021 DUK_TVAL_DECREF(thr, &tv_tmp); /* side effects */
20022#endif
20023}
20024
20027
20028 duk_remove(thr, idx); /* XXX: no optimization for now */
20029}
20030
20033
20034 duk_remove(thr, -2);
20035}
20036
20038#if defined(DUK_USE_PREFER_SIZE)
20039 /* XXX: maybe too slow even when preferring size? */
20041 DUK_ASSERT(count >= 0);
20042 DUK_ASSERT(idx >= 0);
20043
20044 while (count-- > 0) {
20045 duk_remove(thr, idx);
20046 }
20047#else /* DUK_USE_PREFER_SIZE */
20048 duk_tval *tv_src;
20049 duk_tval *tv_dst;
20050 duk_tval *tv_newtop;
20051 duk_tval *tv;
20052 duk_size_t bytes;
20053
20055 DUK_ASSERT(count >= 0);
20056 DUK_ASSERT(idx >= 0);
20057
20058 tv_dst = thr->valstack_bottom + idx;
20059 DUK_ASSERT(tv_dst <= thr->valstack_top);
20060 tv_src = tv_dst + count;
20061 DUK_ASSERT(tv_src <= thr->valstack_top);
20062 bytes = (duk_size_t) ((duk_uint8_t *) thr->valstack_top - (duk_uint8_t *) tv_src);
20063
20064 for (tv = tv_dst; tv < tv_src; tv++) {
20065 DUK_TVAL_DECREF_NORZ(thr, tv);
20066 }
20067
20068 duk_memmove((void *) tv_dst, (const void *) tv_src, bytes);
20069
20070 tv_newtop = thr->valstack_top - count;
20071 for (tv = tv_newtop; tv < thr->valstack_top; tv++) {
20073 }
20074 thr->valstack_top = tv_newtop;
20075
20076 /* When not preferring size, only NORZ macros are used; caller
20077 * is expected to DUK_REFZERO_CHECK().
20078 */
20079#endif /* DUK_USE_PREFER_SIZE */
20081
20084
20085 duk_remove_n(thr, idx, count); /* XXX: no optimization for now */
20086}
20087
20088/*
20089 * Stack slice primitives
20090 */
20091
20093 void *src;
20094 duk_size_t nbytes;
20095 duk_tval *p;
20096 duk_tval *q;
20097
20098 /* XXX: several pointer comparison issues here */
20099
20100 DUK_ASSERT_API_ENTRY(to_thr);
20101 DUK_CTX_ASSERT_VALID(to_thr);
20102 DUK_CTX_ASSERT_VALID(from_thr);
20103 DUK_ASSERT(to_thr->heap == from_thr->heap);
20104
20105 if (DUK_UNLIKELY(to_thr == from_thr)) {
20107 DUK_WO_NORETURN(return;);
20108 }
20110 /* Maximum value check ensures 'nbytes' won't wrap below.
20111 * Also handles negative count.
20112 */
20114 DUK_WO_NORETURN(return;);
20115 }
20116 DUK_ASSERT(count >= 0);
20117
20118 nbytes = sizeof(duk_tval) * (duk_size_t) count;
20119 if (DUK_UNLIKELY(nbytes == 0)) {
20120 return;
20121 }
20122 DUK_ASSERT(to_thr->valstack_top <= to_thr->valstack_end);
20123 if (DUK_UNLIKELY((duk_size_t) ((duk_uint8_t *) to_thr->valstack_end - (duk_uint8_t *) to_thr->valstack_top) < nbytes)) {
20125 DUK_WO_NORETURN(return;);
20126 }
20127 src = (void *) ((duk_uint8_t *) from_thr->valstack_top - nbytes);
20128 if (DUK_UNLIKELY(src < (void *) from_thr->valstack_bottom)) {
20130 DUK_WO_NORETURN(return;);
20131 }
20132
20133 /* Copy values (no overlap even if to_thr == from_thr; that's not
20134 * allowed now anyway).
20135 */
20136 DUK_ASSERT(nbytes > 0);
20137 duk_memcpy((void *) to_thr->valstack_top, (const void *) src, (size_t) nbytes);
20138
20139 p = to_thr->valstack_top;
20140 to_thr->valstack_top = (duk_tval *) (void *) (((duk_uint8_t *) p) + nbytes);
20141
20142 if (is_copy) {
20143 /* Incref copies, keep originals. */
20144 q = to_thr->valstack_top;
20145 while (p < q) {
20146 DUK_TVAL_INCREF(to_thr, p); /* no side effects */
20147 p++;
20148 }
20149 } else {
20150 /* No net refcount change. */
20151 p = from_thr->valstack_top;
20152 q = (duk_tval *) (void *) (((duk_uint8_t *) p) - nbytes);
20153 from_thr->valstack_top = q;
20154
20155 while (p > q) {
20156 p--;
20158 /* XXX: fast primitive to set a bunch of values to UNDEFINED */
20159 }
20160 }
20161}
20162
20163/* Internal helper: reserve a gap of 'count' elements at 'idx_base' and return a
20164 * pointer to the gap. Values in the gap are garbage and MUST be initialized by
20165 * the caller before any side effects may occur. The caller must ensure there's
20166 * enough stack reserve for 'count' values.
20167 */
20169 duk_tval *tv_src;
20170 duk_tval *tv_dst;
20171 duk_size_t gap_bytes;
20172 duk_size_t copy_bytes;
20173
20174 /* Caller is responsible for ensuring there's enough preallocated
20175 * value stack.
20176 */
20178 DUK_ASSERT(count >= 0);
20180
20181 tv_src = thr->valstack_bottom + idx_base;
20182 gap_bytes = (duk_size_t) count * sizeof(duk_tval);
20183 tv_dst = (duk_tval *) (void *) ((duk_uint8_t *) tv_src + gap_bytes);
20184 copy_bytes = (duk_size_t) ((duk_uint8_t *) thr->valstack_top - (duk_uint8_t *) tv_src);
20185 thr->valstack_top = (duk_tval *) (void *) ((duk_uint8_t *) thr->valstack_top + gap_bytes);
20186 duk_memmove((void *) tv_dst, (const void *) tv_src, copy_bytes);
20187
20188 /* Values in the gap are left as garbage: caller must fill them in
20189 * and INCREF them before any side effects.
20190 */
20191 return tv_src;
20192}
20193
20194/*
20195 * Get/opt/require
20196 */
20197
20200
20202
20203 tv = duk_get_tval_or_unused(thr, idx);
20204 DUK_ASSERT(tv != NULL);
20207 DUK_WO_NORETURN(return;);
20208 }
20209}
20210
20213
20215
20216 tv = duk_get_tval_or_unused(thr, idx);
20217 DUK_ASSERT(tv != NULL);
20218 if (DUK_UNLIKELY(!DUK_TVAL_IS_NULL(tv))) {
20220 DUK_WO_NORETURN(return;);
20221 }
20222}
20223
20225 duk_bool_t ret;
20226 duk_tval *tv;
20227
20229
20230 tv = duk_get_tval_or_unused(thr, idx);
20231 DUK_ASSERT(tv != NULL);
20232 if (DUK_TVAL_IS_BOOLEAN(tv)) {
20233 ret = DUK_TVAL_GET_BOOLEAN(tv);
20234 DUK_ASSERT(ret == 0 || ret == 1);
20235 } else {
20236 ret = def_value;
20237 /* Not guaranteed to be 0 or 1. */
20238 }
20239
20240 return ret;
20241}
20242
20245
20246 return duk__get_boolean_raw(thr, idx, 0); /* default: false */
20247}
20248
20251
20252 return duk__get_boolean_raw(thr, idx, def_value);
20253}
20254
20256 duk_tval *tv;
20257 duk_bool_t ret;
20258
20260
20262 DUK_ASSERT(tv != NULL);
20264 ret = DUK_TVAL_GET_BOOLEAN(tv);
20265 DUK_ASSERT(ret == 0 || ret == 1);
20266 return ret;
20267 } else {
20269 DUK_WO_NORETURN(return 0;);
20271}
20272
20275
20277 return def_value;
20278 }
20279 return duk_require_boolean(thr, idx);
20280}
20281
20283 duk_double_union ret;
20284 duk_tval *tv;
20285
20287
20288 tv = duk_get_tval_or_unused(thr, idx);
20289 DUK_ASSERT(tv != NULL);
20290#if defined(DUK_USE_FASTINT)
20291 if (DUK_TVAL_IS_FASTINT(tv)) {
20292 ret.d = (duk_double_t) DUK_TVAL_GET_FASTINT(tv); /* XXX: cast trick */
20293 } else
20294#endif
20295 if (DUK_TVAL_IS_DOUBLE(tv)) {
20296 /* When using packed duk_tval, number must be in NaN-normalized form
20297 * for it to be a duk_tval, so no need to normalize. NOP for unpacked
20298 * duk_tval.
20299 */
20300 ret.d = DUK_TVAL_GET_DOUBLE(tv);
20302 } else {
20303 ret.d = def_value;
20304 /* Default value (including NaN) may not be normalized. */
20305 }
20306
20307 return ret.d;
20309
20312 return duk__get_number_raw(thr, idx, DUK_DOUBLE_NAN); /* default: NaN */
20313}
20314
20317 return duk__get_number_raw(thr, idx, def_value);
20318}
20319
20321 duk_tval *tv;
20322 duk_double_union ret;
20323
20325
20326 tv = duk_get_tval_or_unused(thr, idx);
20327 DUK_ASSERT(tv != NULL);
20328 if (DUK_UNLIKELY(!DUK_TVAL_IS_NUMBER(tv))) {
20330 DUK_WO_NORETURN(return 0.0;);
20332
20333 ret.d = DUK_TVAL_GET_NUMBER(tv);
20334
20335 /* When using packed duk_tval, number must be in NaN-normalized form
20336 * for it to be a duk_tval, so no need to normalize. NOP for unpacked
20337 * duk_tval.
20338 */
20340 return ret.d;
20342
20345
20347 /* User provided default is not NaN normalized. */
20348 return def_value;
20349 }
20350 return duk_require_number(thr, idx);
20351}
20352
20355
20356 return (duk_int_t) duk__api_coerce_d2i(thr, idx, 0 /*def_value*/, 0 /*require*/);
20357}
20358
20361
20362 return (duk_uint_t) duk__api_coerce_d2ui(thr, idx, 0 /*def_value*/, 0 /*require*/);
20363}
20364
20367
20368 return (duk_int_t) duk__api_coerce_d2i(thr, idx, def_value, 0 /*require*/);
20369}
20370
20373
20374 return (duk_uint_t) duk__api_coerce_d2ui(thr, idx, def_value, 0 /*require*/);
20375}
20376
20379
20380 return (duk_int_t) duk__api_coerce_d2i(thr, idx, 0 /*def_value*/, 1 /*require*/);
20381}
20382
20385
20386 return (duk_uint_t) duk__api_coerce_d2ui(thr, idx, 0 /*def_value*/, 1 /*require*/);
20387}
20388
20391
20393 return def_value;
20394 }
20395 return duk_require_int(thr, idx);
20396}
20397
20400
20402 return def_value;
20403 }
20404 return duk_require_uint(thr, idx);
20405}
20406
20407DUK_EXTERNAL const char *duk_get_lstring(duk_hthread *thr, duk_idx_t idx, duk_size_t *out_len) {
20408 duk_hstring *h;
20409 const char *ret;
20410 duk_size_t len;
20411
20413
20414 h = duk_get_hstring(thr, idx);
20415 if (h != NULL) {
20416 len = DUK_HSTRING_GET_BYTELEN(h);
20417 ret = (const char *) DUK_HSTRING_GET_DATA(h);
20418 } else {
20419 len = 0;
20420 ret = NULL;
20421 }
20422
20423 if (out_len != NULL) {
20424 *out_len = len;
20425 }
20426 return ret;
20427}
20428
20429DUK_EXTERNAL const char *duk_require_lstring(duk_hthread *thr, duk_idx_t idx, duk_size_t *out_len) {
20431
20433
20434 h = duk_require_hstring(thr, idx);
20435 DUK_ASSERT(h != NULL);
20436 if (out_len) {
20437 *out_len = DUK_HSTRING_GET_BYTELEN(h);
20438 }
20439 return (const char *) DUK_HSTRING_GET_DATA(h);
20440}
20441
20444
20446
20447 h = duk_require_hstring_notsymbol(thr, idx);
20448 DUK_ASSERT(h != NULL);
20449 if (out_len) {
20450 *out_len = DUK_HSTRING_GET_BYTELEN(h);
20451 }
20452 return (const char *) DUK_HSTRING_GET_DATA(h);
20453}
20454
20455DUK_EXTERNAL const char *duk_get_string(duk_hthread *thr, duk_idx_t idx) {
20457
20459
20460 h = duk_get_hstring(thr, idx);
20461 if (h != NULL) {
20462 return (const char *) DUK_HSTRING_GET_DATA(h);
20463 } else {
20464 return NULL;
20465 }
20466}
20467
20469 duk_idx_t idx,
20470 duk_size_t *out_len,
20471 const char *def_ptr,
20472 duk_size_t def_len) {
20474
20476 if (out_len != NULL) {
20477 *out_len = def_len;
20478 }
20479 return def_ptr;
20480 }
20481 return duk_require_lstring(thr, idx, out_len);
20482}
20483
20484DUK_EXTERNAL const char *duk_opt_string(duk_hthread *thr, duk_idx_t idx, const char *def_ptr) {
20486
20488 return def_ptr;
20489 }
20490 return duk_require_string(thr, idx);
20491}
20492
20494 duk_idx_t idx,
20495 duk_size_t *out_len,
20496 const char *def_ptr,
20497 duk_size_t def_len) {
20498 duk_hstring *h;
20499 const char *ret;
20500 duk_size_t len;
20501
20503
20504 h = duk_get_hstring(thr, idx);
20505 if (h != NULL) {
20506 len = DUK_HSTRING_GET_BYTELEN(h);
20507 ret = (const char *) DUK_HSTRING_GET_DATA(h);
20508 } else {
20509 len = def_len;
20510 ret = def_ptr;
20511 }
20512
20513 if (out_len != NULL) {
20514 *out_len = len;
20515 }
20516 return ret;
20517}
20518
20519DUK_EXTERNAL const char *duk_get_string_default(duk_hthread *thr, duk_idx_t idx, const char *def_value) {
20521
20523
20524 h = duk_get_hstring(thr, idx);
20525 if (h != NULL) {
20526 return (const char *) DUK_HSTRING_GET_DATA(h);
20527 } else {
20528 return def_value;
20529 }
20530}
20531
20534
20536
20537 h = duk_get_hstring_notsymbol(thr, idx);
20538 if (h) {
20539 return (const char *) DUK_HSTRING_GET_DATA(h);
20540 } else {
20541 return NULL;
20542 }
20543}
20544
20547
20548 return duk_require_lstring(thr, idx, NULL);
20550
20552 duk_hstring *h;
20553
20555
20556 h = duk_require_hstring_notsymbol(thr, idx);
20557 DUK_ASSERT(h != NULL);
20558 return (const char *) DUK_HSTRING_GET_DATA(h);
20559}
20560
20563
20565
20566 tv = duk_get_tval_or_unused(thr, idx);
20567 DUK_ASSERT(tv != NULL);
20568 if (DUK_UNLIKELY(!DUK_TVAL_IS_OBJECT(tv))) {
20570 DUK_WO_NORETURN(return;);
20571 }
20572}
20573
20574DUK_LOCAL void *duk__get_pointer_raw(duk_hthread *thr, duk_idx_t idx, void *def_value) {
20575 duk_tval *tv;
20576 void *p;
20577
20579
20580 tv = duk_get_tval_or_unused(thr, idx);
20581 DUK_ASSERT(tv != NULL);
20582 if (!DUK_TVAL_IS_POINTER(tv)) {
20583 return def_value;
20584 }
20585
20586 p = DUK_TVAL_GET_POINTER(tv); /* may be NULL */
20587 return p;
20588}
20589
20592 return duk__get_pointer_raw(thr, idx, NULL /*def_value*/);
20593}
20594
20595DUK_EXTERNAL void *duk_opt_pointer(duk_hthread *thr, duk_idx_t idx, void *def_value) {
20599 return def_value;
20600 }
20601 return duk_require_pointer(thr, idx);
20602}
20603
20604DUK_EXTERNAL void *duk_get_pointer_default(duk_hthread *thr, duk_idx_t idx, void *def_value) {
20606 return duk__get_pointer_raw(thr, idx, def_value);
20607}
20608
20610 duk_tval *tv;
20611 void *p;
20612
20614
20615 /* Note: here we must be wary of the fact that a pointer may be
20616 * valid and be a NULL.
20617 */
20618 tv = duk_get_tval_or_unused(thr, idx);
20619 DUK_ASSERT(tv != NULL);
20622 DUK_WO_NORETURN(return NULL;);
20623 }
20624 p = DUK_TVAL_GET_POINTER(tv); /* may be NULL */
20625 return p;
20626}
20627
20628#if 0 /*unused*/
20629DUK_INTERNAL void *duk_get_voidptr(duk_hthread *thr, duk_idx_t idx) {
20630 duk_tval *tv;
20631 duk_heaphdr *h;
20632
20634
20636 DUK_ASSERT(tv != NULL);
20637 if (!DUK_TVAL_IS_HEAP_ALLOCATED(tv)) {
20638 return NULL;
20639 }
20640
20641 h = DUK_TVAL_GET_HEAPHDR(tv);
20642 DUK_ASSERT(h != NULL);
20643 return (void *) h;
20644}
20645#endif
20646
20648 duk_idx_t idx,
20649 duk_size_t *out_size,
20650 void *def_ptr,
20651 duk_size_t def_size,
20652 duk_bool_t throw_flag) {
20653 duk_hbuffer *h;
20654 void *ret;
20655 duk_size_t len;
20656 duk_tval *tv;
20657
20659
20660 if (out_size != NULL) {
20661 *out_size = 0;
20662 }
20663
20664 tv = duk_get_tval_or_unused(thr, idx);
20665 DUK_ASSERT(tv != NULL);
20666 if (DUK_LIKELY(DUK_TVAL_IS_BUFFER(tv))) {
20667 h = DUK_TVAL_GET_BUFFER(tv);
20668 DUK_ASSERT(h != NULL);
20669
20670 len = DUK_HBUFFER_GET_SIZE(h);
20671 ret = DUK_HBUFFER_GET_DATA_PTR(thr->heap, h);
20672 } else {
20673 if (throw_flag) {
20675 DUK_WO_NORETURN(return NULL;);
20676 }
20677 len = def_size;
20678 ret = def_ptr;
20679 }
20680
20681 if (out_size != NULL) {
20682 *out_size = len;
20683 }
20684 return ret;
20685}
20686
20687DUK_EXTERNAL void *duk_get_buffer(duk_hthread *thr, duk_idx_t idx, duk_size_t *out_size) {
20689
20690 return duk__get_buffer_helper(thr, idx, out_size, NULL /*def_ptr*/, 0 /*def_size*/, 0 /*throw_flag*/);
20691}
20692
20693DUK_EXTERNAL void *duk_opt_buffer(duk_hthread *thr, duk_idx_t idx, duk_size_t *out_size, void *def_ptr, duk_size_t def_size) {
20695
20697 if (out_size != NULL) {
20698 *out_size = def_size;
20699 }
20700 return def_ptr;
20701 }
20702 return duk_require_buffer(thr, idx, out_size);
20704
20706 duk_idx_t idx,
20707 duk_size_t *out_size,
20708 void *def_ptr,
20709 duk_size_t def_len) {
20711
20712 return duk__get_buffer_helper(thr, idx, out_size, def_ptr, def_len, 0 /*throw_flag*/);
20713}
20717
20718 return duk__get_buffer_helper(thr, idx, out_size, NULL /*def_ptr*/, 0 /*def_size*/, 1 /*throw_flag*/);
20719}
20720
20721/* Get the active buffer data area for a plain buffer or a buffer object.
20722 * Return NULL if the the value is not a buffer. Note that a buffer may
20723 * have a NULL data pointer when its size is zero, the optional 'out_isbuffer'
20724 * argument allows caller to detect this reliably.
20725 */
20727 duk_idx_t idx,
20728 duk_size_t *out_size,
20729 void *def_ptr,
20730 duk_size_t def_size,
20731 duk_bool_t throw_flag,
20732 duk_bool_t *out_isbuffer) {
20733 duk_tval *tv;
20734
20736
20737 if (out_isbuffer != NULL) {
20738 *out_isbuffer = 0;
20739 }
20740 if (out_size != NULL) {
20741 *out_size = def_size;
20742 }
20743
20744 tv = duk_get_tval_or_unused(thr, idx);
20745 DUK_ASSERT(tv != NULL);
20746
20747 if (DUK_TVAL_IS_BUFFER(tv)) {
20749 DUK_ASSERT(h != NULL);
20750 if (out_size != NULL) {
20751 *out_size = DUK_HBUFFER_GET_SIZE(h);
20752 }
20753 if (out_isbuffer != NULL) {
20754 *out_isbuffer = 1;
20755 }
20756 return (void *) DUK_HBUFFER_GET_DATA_PTR(thr->heap, h); /* may be NULL (but only if size is 0) */
20757 }
20758#if defined(DUK_USE_BUFFEROBJECT_SUPPORT)
20759 else if (DUK_TVAL_IS_OBJECT(tv)) {
20761 DUK_ASSERT(h != NULL);
20762 if (DUK_HOBJECT_IS_BUFOBJ(h)) {
20763 /* XXX: this is probably a useful shared helper: for a
20764 * duk_hbufobj, get a validated buffer pointer/length.
20765 */
20766 duk_hbufobj *h_bufobj = (duk_hbufobj *) h;
20767 DUK_HBUFOBJ_ASSERT_VALID(h_bufobj);
20768
20769 if (h_bufobj->buf != NULL && DUK_HBUFOBJ_VALID_SLICE(h_bufobj)) {
20770 duk_uint8_t *p;
20771
20772 p = (duk_uint8_t *) DUK_HBUFFER_GET_DATA_PTR(thr->heap, h_bufobj->buf);
20773 if (out_size != NULL) {
20774 *out_size = (duk_size_t) h_bufobj->length;
20775 }
20776 if (out_isbuffer != NULL) {
20777 *out_isbuffer = 1;
20778 }
20779 return (void *) (p + h_bufobj->offset);
20780 }
20781 /* if slice not fully valid, treat as error */
20782 }
20783 }
20784#endif /* DUK_USE_BUFFEROBJECT_SUPPORT */
20785
20786 if (throw_flag) {
20788 DUK_WO_NORETURN(return NULL;);
20789 }
20790 return def_ptr;
20791}
20792
20795 return duk_get_buffer_data_raw(thr, idx, out_size, NULL /*def_ptr*/, 0 /*def_size*/, 0 /*throw_flag*/, NULL);
20796}
20797
20799 duk_idx_t idx,
20800 duk_size_t *out_size,
20801 void *def_ptr,
20802 duk_size_t def_size) {
20804 return duk_get_buffer_data_raw(thr, idx, out_size, def_ptr, def_size, 0 /*throw_flag*/, NULL);
20805}
20806
20807DUK_EXTERNAL void *duk_opt_buffer_data(duk_hthread *thr, duk_idx_t idx, duk_size_t *out_size, void *def_ptr, duk_size_t def_size) {
20809
20811 if (out_size != NULL) {
20812 *out_size = def_size;
20813 }
20814 return def_ptr;
20815 }
20816 return duk_require_buffer_data(thr, idx, out_size);
20818
20821 return duk_get_buffer_data_raw(thr, idx, out_size, NULL /*def_ptr*/, 0 /*def_size*/, 1 /*throw_flag*/, NULL);
20822}
20823
20824/* Raw helper for getting a value from the stack, checking its tag.
20825 * The tag cannot be a number because numbers don't have an internal
20826 * tag in the packed representation.
20827 */
20828
20830 duk_tval *tv;
20831 duk_heaphdr *ret;
20832
20835 tv = duk_get_tval_or_unused(thr, idx);
20836 DUK_ASSERT(tv != NULL);
20837 if (DUK_TVAL_GET_TAG(tv) != tag) {
20838 return (duk_heaphdr *) NULL;
20840
20841 ret = DUK_TVAL_GET_HEAPHDR(tv);
20842 DUK_ASSERT(ret != NULL); /* tagged null pointers should never occur */
20843 return ret;
20844}
20845
20849}
20850
20852 duk_hstring *h;
20853
20855
20857 if (DUK_UNLIKELY(h && DUK_HSTRING_HAS_SYMBOL(h))) {
20858 return NULL;
20859 }
20860 return h;
20861}
20862
20865
20867
20869 if (DUK_UNLIKELY(h == NULL)) {
20871 DUK_WO_NORETURN(return NULL;);
20872 }
20873 return h;
20874}
20875
20878
20880
20882 if (DUK_UNLIKELY(h == NULL || DUK_HSTRING_HAS_SYMBOL(h))) {
20884 DUK_WO_NORETURN(return NULL;);
20885 }
20886 return h;
20887}
20888
20892}
20893
20896
20898
20900 if (DUK_UNLIKELY(h == NULL)) {
20902 DUK_WO_NORETURN(return NULL;);
20903 }
20904 return h;
20905}
20906
20910}
20911
20914
20916
20918 if (DUK_UNLIKELY(h == NULL)) {
20920 DUK_WO_NORETURN(return NULL;);
20921 }
20922 return h;
20923}
20924
20926 duk_hobject *h;
20927
20929
20931 if (DUK_UNLIKELY(h != NULL && !DUK_HOBJECT_IS_THREAD(h))) {
20932 h = NULL;
20933 }
20934 return (duk_hthread *) h;
20935}
20936
20939
20941
20943 if (DUK_UNLIKELY(!(h != NULL && DUK_HOBJECT_IS_THREAD(h)))) {
20945 DUK_WO_NORETURN(return NULL;);
20946 }
20947 return (duk_hthread *) h;
20948}
20949
20951 duk_hobject *h;
20952
20954
20956 if (DUK_UNLIKELY(h != NULL && !DUK_HOBJECT_IS_COMPFUNC(h))) {
20957 h = NULL;
20958 }
20959 return (duk_hcompfunc *) h;
20960}
20961
20964
20966
20968 if (DUK_UNLIKELY(!(h != NULL && DUK_HOBJECT_IS_COMPFUNC(h)))) {
20969 DUK_ERROR_REQUIRE_TYPE_INDEX(thr, idx, "compiledfunction", DUK_STR_NOT_COMPFUNC);
20970 DUK_WO_NORETURN(return NULL;);
20971 }
20972 return (duk_hcompfunc *) h;
20973}
20974
20976 duk_hobject *h;
20977
20979
20981 if (DUK_UNLIKELY(h != NULL && !DUK_HOBJECT_IS_NATFUNC(h))) {
20982 h = NULL;
20983 }
20984 return (duk_hnatfunc *) h;
20985}
20986
20989
20991
20993 if (DUK_UNLIKELY(!(h != NULL && DUK_HOBJECT_IS_NATFUNC(h)))) {
20994 DUK_ERROR_REQUIRE_TYPE_INDEX(thr, idx, "nativefunction", DUK_STR_NOT_NATFUNC);
20995 DUK_WO_NORETURN(return NULL;);
20996 }
20997 return (duk_hnatfunc *) h;
20998}
20999
21001 duk_tval *tv;
21002 duk_hobject *h;
21003 duk_hnatfunc *f;
21004
21006
21007 tv = duk_get_tval_or_unused(thr, idx);
21008 DUK_ASSERT(tv != NULL);
21009 if (DUK_UNLIKELY(!DUK_TVAL_IS_OBJECT(tv))) {
21010 return NULL;
21011 }
21013 DUK_ASSERT(h != NULL);
21014
21016 return NULL;
21017 }
21019 f = (duk_hnatfunc *) h;
21020
21021 return f->func;
21022}
21023
21026
21028 return def_value;
21029 }
21030 return duk_require_c_function(thr, idx);
21031}
21032
21035
21037
21038 ret = duk_get_c_function(thr, idx);
21039 if (ret != NULL) {
21040 return ret;
21041 }
21042
21043 return def_value;
21044}
21045
21048
21050
21051 ret = duk_get_c_function(thr, idx);
21052 if (DUK_UNLIKELY(!ret)) {
21053 DUK_ERROR_REQUIRE_TYPE_INDEX(thr, idx, "nativefunction", DUK_STR_NOT_NATFUNC);
21054 DUK_WO_NORETURN(return ret;);
21056 return ret;
21057}
21058
21061 if (DUK_UNLIKELY(!duk_is_function(thr, idx))) {
21063 DUK_WO_NORETURN(return;);
21064 }
21065}
21066
21069
21071
21073 if (DUK_UNLIKELY(h != NULL && !DUK_HOBJECT_HAS_CONSTRUCTABLE(h))) {
21075 DUK_WO_NORETURN(return;);
21076 }
21077 /* Lightfuncs (h == NULL) are constructable. */
21078}
21079
21082
21083 return duk_get_hthread(thr, idx);
21084}
21085
21088
21089 return duk_require_hthread(thr, idx);
21090}
21091
21094
21096 return def_value;
21097 }
21098 return duk_require_context(thr, idx);
21099}
21100
21103
21105
21106 ret = duk_get_context(thr, idx);
21107 if (ret != NULL) {
21108 return ret;
21109 }
21110
21111 return def_value;
21112}
21113
21115 duk_tval *tv;
21116 void *ret;
21117
21120 tv = duk_get_tval_or_unused(thr, idx);
21121 DUK_ASSERT(tv != NULL);
21123 return (void *) NULL;
21124 }
21125
21126 ret = (void *) DUK_TVAL_GET_HEAPHDR(tv);
21127 DUK_ASSERT(ret != NULL);
21128 return ret;
21129}
21130
21131DUK_EXTERNAL void *duk_opt_heapptr(duk_hthread *thr, duk_idx_t idx, void *def_value) {
21133
21135 return def_value;
21136 }
21137 return duk_require_heapptr(thr, idx);
21138}
21139
21140DUK_EXTERNAL void *duk_get_heapptr_default(duk_hthread *thr, duk_idx_t idx, void *def_value) {
21141 void *ret;
21142
21144
21145 ret = duk_get_heapptr(thr, idx);
21146 if (ret != NULL) {
21147 return ret;
21148 }
21149
21150 return def_value;
21151}
21152
21154 duk_tval *tv;
21155 void *ret;
21156
21158
21159 tv = duk_get_tval_or_unused(thr, idx);
21160 DUK_ASSERT(tv != NULL);
21163 DUK_WO_NORETURN(return NULL;);
21164 }
21165
21166 ret = (void *) DUK_TVAL_GET_HEAPHDR(tv);
21167 DUK_ASSERT(ret != NULL);
21168 return ret;
21169}
21170
21171/* Internal helper for getting/requiring a duk_hobject with possible promotion. */
21173 duk_uint_t val_mask;
21174 duk_hobject *res;
21175
21177
21178 res = duk_get_hobject(thr, idx); /* common case, not promoted */
21179 if (DUK_LIKELY(res != NULL)) {
21180 DUK_ASSERT(res != NULL);
21181 return res;
21182 }
21183
21184 val_mask = duk_get_type_mask(thr, idx);
21185 if (val_mask & type_mask) {
21186 if (type_mask & DUK_TYPE_MASK_PROMOTE) {
21187 res = duk_to_hobject(thr, idx);
21188 DUK_ASSERT(res != NULL);
21189 return res;
21190 } else {
21191 return NULL; /* accept without promoting */
21192 }
21193 }
21194
21195 if (type_mask & DUK_TYPE_MASK_THROW) {
21197 DUK_WO_NORETURN(return NULL;);
21198 }
21199 return NULL;
21200}
21201
21202/* Get a duk_hobject * at 'idx'; if the value is not an object but matches the
21203 * supplied 'type_mask', promote it to an object and return the duk_hobject *.
21204 * This is useful for call sites which want an object but also accept a plain
21205 * buffer and/or a lightfunc which gets automatically promoted to an object.
21206 * Return value is NULL if value is neither an object nor a plain type allowed
21207 * by the mask.
21208 */
21211 return duk__get_hobject_promote_mask_raw(thr, idx, type_mask | DUK_TYPE_MASK_PROMOTE);
21212}
21214/* Like duk_get_hobject_promote_mask() but throw a TypeError instead of
21215 * returning a NULL.
21216 */
21220}
21221
21222/* Require a duk_hobject * at 'idx'; if the value is not an object but matches the
21223 * supplied 'type_mask', return a NULL instead. Otherwise throw a TypeError.
21224 */
21227 return duk__get_hobject_promote_mask_raw(thr, idx, type_mask | DUK_TYPE_MASK_THROW);
21228}
21229
21231 duk_hobject *h;
21234 DUK_ASSERT_DISABLE(classnum >= 0); /* unsigned */
21235 DUK_ASSERT(classnum <= DUK_HOBJECT_CLASS_MAX);
21236
21238 if (DUK_UNLIKELY(h != NULL && DUK_HOBJECT_GET_CLASS_NUMBER(h) != classnum)) {
21239 h = NULL;
21240 }
21241 return h;
21242}
21243
21245 duk_hobject *h;
21246
21248 DUK_ASSERT_DISABLE(classnum >= 0); /* unsigned */
21249 DUK_ASSERT(classnum <= DUK_HOBJECT_CLASS_MAX);
21250
21252 if (DUK_UNLIKELY(!(h != NULL && DUK_HOBJECT_GET_CLASS_NUMBER(h) == classnum))) {
21253 duk_hstring *h_class;
21255 DUK_UNREF(h_class);
21256
21258 DUK_WO_NORETURN(return NULL;);
21259 }
21260 return h;
21261}
21262
21264 duk_tval *tv;
21265
21267
21268 tv = duk_get_tval_or_unused(thr, idx);
21269 DUK_ASSERT(tv != NULL);
21270
21271 switch (DUK_TVAL_GET_TAG(tv)) {
21272 case DUK_TAG_UNDEFINED:
21273 case DUK_TAG_NULL:
21274 case DUK_TAG_BOOLEAN:
21275 case DUK_TAG_POINTER:
21276 return 0;
21277#if defined(DUK_USE_PREFER_SIZE)
21278 /* String and buffer have a virtual non-configurable .length property
21279 * which is within size_t range so it can be looked up without specific
21280 * type checks. Lightfuncs inherit from %NativeFunctionPrototype%
21281 * which provides an inherited .length accessor; it could be overwritten
21282 * to produce unexpected types or values, but just number convert and
21283 * duk_size_t cast for now.
21284 */
21285 case DUK_TAG_STRING:
21286 case DUK_TAG_BUFFER:
21287 case DUK_TAG_LIGHTFUNC: {
21288 duk_size_t ret;
21290 ret = (duk_size_t) duk_to_number_m1(thr);
21291 duk_pop_unsafe(thr);
21292 return ret;
21293 }
21294#else /* DUK_USE_PREFER_SIZE */
21295 case DUK_TAG_STRING: {
21297 DUK_ASSERT(h != NULL);
21299 return 0;
21300 }
21302 }
21303 case DUK_TAG_BUFFER: {
21305 DUK_ASSERT(h != NULL);
21306 return (duk_size_t) DUK_HBUFFER_GET_SIZE(h);
21307 }
21308 case DUK_TAG_LIGHTFUNC: {
21309 /* We could look up the length from the lightfunc duk_tval,
21310 * but since Duktape 2.2 lightfunc .length comes from
21311 * %NativeFunctionPrototype% which can be overridden, so
21312 * look up the property explicitly.
21313 */
21314 duk_size_t ret;
21316 ret = (duk_size_t) duk_to_number_m1(thr);
21317 duk_pop_unsafe(thr);
21318 return ret;
21319 }
21320#endif /* DUK_USE_PREFER_SIZE */
21321 case DUK_TAG_OBJECT: {
21323 DUK_ASSERT(h != NULL);
21324 return (duk_size_t) duk_hobject_get_length(thr, h);
21325 }
21326#if defined(DUK_USE_FASTINT)
21327 case DUK_TAG_FASTINT:
21328#endif
21329 default:
21330 /* number or 'unused' */
21332 return 0;
21333 }
21334
21337
21338/*
21339 * duk_known_xxx() helpers
21340 *
21341 * Used internally when we're 100% sure that a certain index is valid and
21342 * contains an object of a certain type. For example, if we duk_push_object()
21343 * we can then safely duk_known_hobject(thr, -1). These helpers just assert
21344 * for the index and type, and if the assumptions are not valid, memory unsafe
21345 * behavior happens.
21346 */
21347
21349 duk_tval *tv;
21350 duk_heaphdr *h;
21351
21353 if (idx < 0) {
21354 tv = thr->valstack_top + idx;
21355 } else {
21356 tv = thr->valstack_bottom + idx;
21357 }
21358 DUK_ASSERT(tv >= thr->valstack_bottom);
21359 DUK_ASSERT(tv < thr->valstack_top);
21360 h = DUK_TVAL_GET_HEAPHDR(tv);
21361 DUK_ASSERT(h != NULL);
21362 return h;
21363}
21364
21367 DUK_ASSERT(duk_get_hstring(thr, idx) != NULL);
21368 return (duk_hstring *) duk__known_heaphdr(thr, idx);
21369}
21370
21373 DUK_ASSERT(duk_get_hobject(thr, idx) != NULL);
21374 return (duk_hobject *) duk__known_heaphdr(thr, idx);
21375}
21376
21379 DUK_ASSERT(duk_get_hbuffer(thr, idx) != NULL);
21380 return (duk_hbuffer *) duk__known_heaphdr(thr, idx);
21381}
21382
21385 DUK_ASSERT(duk_get_hcompfunc(thr, idx) != NULL);
21386 return (duk_hcompfunc *) duk__known_heaphdr(thr, idx);
21387}
21388
21391 DUK_ASSERT(duk_get_hnatfunc(thr, idx) != NULL);
21392 return (duk_hnatfunc *) duk__known_heaphdr(thr, idx);
21393}
21394
21397
21398 idx = duk_normalize_index(thr, idx);
21399 duk_push_uint(thr, (duk_uint_t) len);
21402
21403/*
21404 * Conversions and coercions
21405 *
21406 * The conversion/coercions are in-place operations on the value stack.
21407 * Some operations are implemented here directly, while others call a
21408 * helper in duk_js_ops.c after validating arguments.
21409 */
21410
21411/* E5 Section 8.12.8 */
21412
21414 if (duk_get_prop_stridx(thr, idx, func_stridx)) {
21415 /* [ ... func ] */
21416 if (duk_is_callable(thr, -1)) {
21417 duk_dup(thr, idx); /* -> [ ... func this ] */
21418 duk_call_method(thr, 0); /* -> [ ... retval ] */
21419 if (duk_is_primitive(thr, -1)) {
21420 duk_replace(thr, idx);
21421 return 1;
21422 }
21423 /* [ ... retval ]; popped below */
21424 }
21425 }
21426 duk_pop_unsafe(thr); /* [ ... func/retval ] -> [ ... ] */
21427 return 0;
21429
21431 duk_tval *tv;
21432
21434
21435 tv = duk_require_tval(thr, idx);
21436 DUK_ASSERT(tv != NULL);
21437 DUK_TVAL_SET_UNDEFINED_UPDREF(thr, tv); /* side effects */
21438}
21441 duk_tval *tv;
21442
21444
21445 tv = duk_require_tval(thr, idx);
21446 DUK_ASSERT(tv != NULL);
21447 DUK_TVAL_SET_NULL_UPDREF(thr, tv); /* side effects */
21448}
21449
21450/* E5 Section 9.1 */
21451DUK_LOCAL const char * const duk__toprim_hint_strings[3] = { "default", "string", "number" };
21452DUK_LOCAL void duk__to_primitive_helper(duk_hthread *thr, duk_idx_t idx, duk_int_t hint, duk_bool_t check_symbol) {
21453 /* Inline initializer for coercers[] is not allowed by old compilers like BCC. */
21454 duk_small_uint_t coercers[2];
21455
21457 DUK_ASSERT(hint == DUK_HINT_NONE || hint == DUK_HINT_NUMBER || hint == DUK_HINT_STRING);
21458
21459 idx = duk_require_normalize_index(thr, idx);
21460
21461 /* If already primitive, return as is. */
21463 DUK_ASSERT(!duk_is_buffer(thr, idx)); /* duk_to_string() relies on this behavior */
21464 return;
21465 }
21466
21467 /* @@toPrimitive lookup. Also do for plain buffers and lightfuncs
21468 * which mimic objects.
21469 */
21470 if (check_symbol && duk_get_method_stridx(thr, idx, DUK_STRIDX_WELLKNOWN_SYMBOL_TO_PRIMITIVE)) {
21471 DUK_ASSERT(hint >= 0 && (duk_size_t) hint < sizeof(duk__toprim_hint_strings) / sizeof(const char *));
21472 duk_dup(thr, idx);
21474 duk_call_method(thr, 1); /* [ ... method value hint ] -> [ ... res] */
21476 goto fail;
21477 }
21478 duk_replace(thr, idx);
21479 return;
21480 }
21481
21482 /* Objects are coerced based on E5 specification.
21483 * Lightfuncs are coerced because they behave like
21484 * objects even if they're internally a primitive
21485 * type. Same applies to plain buffers, which behave
21486 * like ArrayBuffer objects since Duktape 2.x.
21487 */
21488
21489 /* Hint magic for Date is unnecessary in ES2015 because of
21490 * Date.prototype[@@toPrimitive]. However, it is needed if
21491 * symbol support is not enabled.
21492 */
21493#if defined(DUK_USE_SYMBOL_BUILTIN)
21494 if (hint == DUK_HINT_NONE) {
21495 hint = DUK_HINT_NUMBER;
21496 }
21497#else /* DUK_USE_SYMBOL_BUILTIN */
21498 if (hint == DUK_HINT_NONE) {
21499 duk_small_uint_t class_number;
21500
21501 class_number = duk_get_class_number(thr, idx);
21502 if (class_number == DUK_HOBJECT_CLASS_DATE) {
21503 hint = DUK_HINT_STRING;
21504 } else {
21505 hint = DUK_HINT_NUMBER;
21506 }
21507 }
21508#endif /* DUK_USE_SYMBOL_BUILTIN */
21509
21510 coercers[0] = DUK_STRIDX_VALUE_OF;
21511 coercers[1] = DUK_STRIDX_TO_STRING;
21512 if (hint == DUK_HINT_STRING) {
21513 coercers[0] = DUK_STRIDX_TO_STRING;
21514 coercers[1] = DUK_STRIDX_VALUE_OF;
21515 }
21516
21517 if (duk__defaultvalue_coerce_attempt(thr, idx, coercers[0])) {
21518 DUK_ASSERT(!duk_is_buffer(thr, idx)); /* duk_to_string() relies on this behavior */
21519 return;
21521
21522 if (duk__defaultvalue_coerce_attempt(thr, idx, coercers[1])) {
21523 DUK_ASSERT(!duk_is_buffer(thr, idx)); /* duk_to_string() relies on this behavior */
21524 return;
21526
21527fail:
21529 DUK_WO_NORETURN(return;);
21530}
21533 duk__to_primitive_helper(thr, idx, hint, 1 /*check_symbol*/);
21534}
21535
21536#if defined(DUK_USE_SYMBOL_BUILTIN)
21538 duk__to_primitive_helper(thr, idx, hint, 0 /*check_symbol*/);
21539}
21540#endif
21541
21542/* E5 Section 9.2 */
21544 duk_tval *tv;
21545 duk_bool_t val;
21546
21548
21549 idx = duk_require_normalize_index(thr, idx);
21550 tv = DUK_GET_TVAL_POSIDX(thr, idx);
21551 DUK_ASSERT(tv != NULL);
21552
21553 val = duk_js_toboolean(tv);
21554 DUK_ASSERT(val == 0 || val == 1);
21555
21556 /* Note: no need to re-lookup tv, conversion is side effect free. */
21557 DUK_ASSERT(tv != NULL);
21558 DUK_TVAL_SET_BOOLEAN_UPDREF(thr, tv, val); /* side effects */
21559 return val;
21560}
21561
21563 duk_tval *tv;
21564 duk_bool_t val;
21565
21567
21568 tv = duk_require_tval(thr, -1);
21569 DUK_ASSERT(tv != NULL);
21570
21571 val = duk_js_toboolean(tv);
21572 DUK_ASSERT(val == 0 || val == 1);
21573
21574 duk_pop_unsafe(thr);
21575 return val;
21576}
21577
21579 duk_tval *tv;
21580 duk_double_t d;
21581
21583
21584 /* XXX: No need to normalize; the whole operation could be inlined here to
21585 * avoid 'tv' re-lookup.
21587 idx = duk_require_normalize_index(thr, idx);
21588 tv = DUK_GET_TVAL_POSIDX(thr, idx);
21589 DUK_ASSERT(tv != NULL);
21590 d = duk_js_tonumber(thr, tv); /* XXX: fastint coercion? now result will always be a non-fastint */
21591
21592 /* ToNumber() may have side effects so must relookup 'tv'. */
21593 tv = DUK_GET_TVAL_POSIDX(thr, idx);
21594 DUK_TVAL_SET_NUMBER_UPDREF(thr, tv, d); /* side effects */
21595 return d;
21596}
21597
21600 return duk_to_number(thr, -1);
21601}
21604 return duk_to_number(thr, -2);
21605}
21606
21608#if defined(DUK_USE_PREFER_SIZE)
21609 duk_double_t res;
21610
21612
21613 duk_push_tval(thr, tv);
21614 res = duk_to_number_m1(thr);
21615 duk_pop_unsafe(thr);
21616 return res;
21617#else
21618 duk_double_t res;
21619 duk_tval *tv_dst;
21620
21623
21624 tv_dst = thr->valstack_top++;
21625 DUK_TVAL_SET_TVAL(tv_dst, tv);
21626 DUK_TVAL_INCREF(thr, tv_dst); /* decref not necessary */
21627 res = duk_to_number_m1(thr); /* invalidates tv_dst */
21628
21629 tv_dst = --thr->valstack_top;
21631 DUK_ASSERT(!DUK_TVAL_NEEDS_REFCOUNT_UPDATE(tv_dst)); /* plain number */
21632 DUK_TVAL_SET_UNDEFINED(tv_dst); /* valstack init policy */
21633
21634 return res;
21635#endif
21636}
21637
21638/* XXX: combine all the integer conversions: they share everything
21639 * but the helper function for coercion.
21640 */
21641
21643
21645 duk_tval *tv;
21646 duk_double_t d;
21647
21649
21650 tv = duk_require_tval(thr, idx);
21651 DUK_ASSERT(tv != NULL);
21652
21653#if defined(DUK_USE_FASTINT)
21654 /* If argument is a fastint, guarantee that it remains one.
21655 * There's no downgrade check for other cases.
21656 */
21657 if (DUK_TVAL_IS_FASTINT(tv)) {
21658 /* XXX: Unnecessary conversion back and forth. */
21661#endif
21662 d = coerce_func(thr, tv);
21663
21664 /* XXX: fastint? */
21665
21666 /* Relookup in case coerce_func() has side effects, e.g. ends up coercing an object */
21667 tv = duk_require_tval(thr, idx);
21668 DUK_TVAL_SET_NUMBER_UPDREF(thr, tv, d); /* side effects */
21669 return d;
21670}
21671
21673 /* Value coercion (in stack): ToInteger(), E5 Section 9.4,
21674 * API return value coercion: custom.
21675 */
21677 (void) duk__to_int_uint_helper(thr, idx, duk_js_tointeger);
21678 return (duk_int_t) duk__api_coerce_d2i(thr, idx, 0 /*def_value*/, 0 /*require*/);
21679}
21680
21682 /* Value coercion (in stack): ToInteger(), E5 Section 9.4,
21683 * API return value coercion: custom.
21684 */
21686 (void) duk__to_int_uint_helper(thr, idx, duk_js_tointeger);
21687 return (duk_uint_t) duk__api_coerce_d2ui(thr, idx, 0 /*def_value*/, 0 /*require*/);
21688}
21689
21690DUK_EXTERNAL duk_int32_t duk_to_int32(duk_hthread *thr, duk_idx_t idx) {
21691 duk_tval *tv;
21692 duk_int32_t ret;
21693
21695
21696 tv = duk_require_tval(thr, idx);
21697 DUK_ASSERT(tv != NULL);
21698 ret = duk_js_toint32(thr, tv);
21699
21700 /* Relookup in case coerce_func() has side effects, e.g. ends up coercing an object */
21701 tv = duk_require_tval(thr, idx);
21702 DUK_TVAL_SET_I32_UPDREF(thr, tv, ret); /* side effects */
21703 return ret;
21704}
21705
21706DUK_EXTERNAL duk_uint32_t duk_to_uint32(duk_hthread *thr, duk_idx_t idx) {
21707 duk_tval *tv;
21708 duk_uint32_t ret;
21709
21711
21712 tv = duk_require_tval(thr, idx);
21713 DUK_ASSERT(tv != NULL);
21714 ret = duk_js_touint32(thr, tv);
21715
21716 /* Relookup in case coerce_func() has side effects, e.g. ends up coercing an object */
21717 tv = duk_require_tval(thr, idx);
21718 DUK_TVAL_SET_U32_UPDREF(thr, tv, ret); /* side effects */
21719 return ret;
21720}
21721
21722DUK_EXTERNAL duk_uint16_t duk_to_uint16(duk_hthread *thr, duk_idx_t idx) {
21723 duk_tval *tv;
21724 duk_uint16_t ret;
21725
21727
21728 tv = duk_require_tval(thr, idx);
21729 DUK_ASSERT(tv != NULL);
21730 ret = duk_js_touint16(thr, tv);
21731
21732 /* Relookup in case coerce_func() has side effects, e.g. ends up coercing an object */
21733 tv = duk_require_tval(thr, idx);
21734 DUK_TVAL_SET_U32_UPDREF(thr, tv, ret); /* side effects */
21735 return ret;
21736}
21737
21738#if defined(DUK_USE_BUFFEROBJECT_SUPPORT)
21739/* Special coercion for Uint8ClampedArray. */
21741 duk_double_t d;
21742 duk_double_t t;
21743 duk_uint8_t ret;
21744
21746
21747 /* XXX: Simplify this algorithm, should be possible to come up with
21748 * a shorter and faster algorithm by inspecting IEEE representation
21749 * directly.
21750 */
21751
21752 d = duk_to_number(thr, idx);
21753 if (d <= 0.0) {
21754 return 0;
21755 } else if (d >= 255) {
21756 return 255;
21757 } else if (DUK_ISNAN(d)) {
21758 /* Avoid NaN-to-integer coercion as it is compiler specific. */
21759 return 0;
21760 }
21761
21762 t = d - DUK_FLOOR(d);
21763 if (duk_double_equals(t, 0.5)) {
21764 /* Exact halfway, round to even. */
21765 ret = (duk_uint8_t) d;
21766 ret = (ret + 1) & 0xfe; /* Example: d=3.5, t=0.5 -> ret = (3 + 1) & 0xfe = 4 & 0xfe = 4
21767 * Example: d=4.5, t=0.5 -> ret = (4 + 1) & 0xfe = 5 & 0xfe = 4
21768 */
21769 } else {
21770 /* Not halfway, round to nearest. */
21771 ret = (duk_uint8_t) (d + 0.5);
21772 }
21773 return ret;
21774}
21775#endif /* DUK_USE_BUFFEROBJECT_SUPPORT */
21776
21777DUK_EXTERNAL const char *duk_to_lstring(duk_hthread *thr, duk_idx_t idx, duk_size_t *out_len) {
21779
21780 (void) duk_to_string(thr, idx);
21782 return duk_require_lstring(thr, idx, out_len);
21783}
21784
21787 DUK_UNREF(udata);
21788
21789 (void) duk_to_string(thr, -1);
21790 return 1;
21791}
21792
21793DUK_EXTERNAL const char *duk_safe_to_lstring(duk_hthread *thr, duk_idx_t idx, duk_size_t *out_len) {
21795
21796 idx = duk_require_normalize_index(thr, idx);
21797
21798 /* We intentionally ignore the duk_safe_call() return value and only
21799 * check the output type. This way we don't also need to check that
21800 * the returned value is indeed a string in the success case.
21801 */
21802
21803 duk_dup(thr, idx);
21804 (void) duk_safe_call(thr, duk__safe_to_string_raw, NULL /*udata*/, 1 /*nargs*/, 1 /*nrets*/);
21805 if (!duk_is_string(thr, -1)) {
21806 /* Error: try coercing error to string once. */
21807 (void) duk_safe_call(thr, duk__safe_to_string_raw, NULL /*udata*/, 1 /*nargs*/, 1 /*nrets*/);
21808 if (!duk_is_string(thr, -1)) {
21809 /* Double error */
21810 duk_pop_unsafe(thr);
21812 } else {
21813 ;
21815 } else {
21816 /* String; may be a symbol, accepted. */
21817 ;
21818 }
21819 DUK_ASSERT(duk_is_string(thr, -1));
21820
21821 duk_replace(thr, idx);
21822 DUK_ASSERT(duk_get_string(thr, idx) != NULL);
21823 return duk_get_lstring(thr, idx, out_len);
21824}
21825
21826DUK_EXTERNAL const char *duk_to_stacktrace(duk_hthread *thr, duk_idx_t idx) {
21828 idx = duk_require_normalize_index(thr, idx);
21829
21830 /* The expected argument to the call is an Error object. The stack
21831 * trace is extracted without an inheritance-based instanceof check
21832 * so that one can also extract the stack trace of a foreign error
21833 * created in another Realm. Accept only a string .stack property.
21834 */
21835 if (duk_is_object(thr, idx)) {
21836 (void) duk_get_prop_string(thr, idx, "stack");
21837 if (duk_is_string(thr, -1)) {
21838 duk_replace(thr, idx);
21839 } else {
21840 duk_pop(thr);
21841 }
21842 }
21843
21844 return duk_to_string(thr, idx);
21845}
21846
21849 DUK_UNREF(udata);
21850
21851 (void) duk_to_stacktrace(thr, -1);
21852
21853 return 1;
21854}
21855
21857 duk_int_t rc;
21858
21860 idx = duk_require_normalize_index(thr, idx);
21861
21862 duk_dup(thr, idx);
21863 rc = duk_safe_call(thr, duk__safe_to_stacktrace_raw, NULL /*udata*/, 1 /*nargs*/, 1 /*nrets*/);
21864 if (rc != 0) {
21865 /* Coercion failed. Try to coerce the coercion itself error
21866 * to a stack trace once. If that also fails, return a fixed,
21867 * preallocated 'Error' string to avoid potential infinite loop.
21869 rc = duk_safe_call(thr, duk__safe_to_stacktrace_raw, NULL /*udata*/, 1 /*nargs*/, 1 /*nrets*/);
21870 if (rc != 0) {
21871 duk_pop_unsafe(thr);
21873 }
21874 }
21875 duk_replace(thr, idx);
21876
21877 return duk_get_string(thr, idx);
21878}
21879
21881 duk_hstring *h;
21882
21884
21885 duk_to_primitive(thr, idx, DUK_HINT_STRING); /* needed for e.g. Symbol objects */
21886 h = duk_get_hstring(thr, idx);
21887 if (h == NULL) {
21888 /* The "is string?" check may seem unnecessary, but as things
21889 * are duk_to_hstring() invokes ToString() which fails for
21890 * symbols. But since symbols are already strings for Duktape
21891 * C API, we check for that before doing the coercion.
21892 */
21893 h = duk_to_hstring(thr, idx);
21894 }
21895 DUK_ASSERT(h != NULL);
21896 return h;
21897}
21898
21899#if defined(DUK_USE_DEBUGGER_SUPPORT) /* only needed by debugger for now */
21900DUK_INTERNAL duk_hstring *duk_safe_to_hstring(duk_hthread *thr, duk_idx_t idx) {
21902
21903 (void) duk_safe_to_string(thr, idx);
21904 DUK_ASSERT(duk_is_string(thr, idx));
21905 DUK_ASSERT(duk_get_hstring(thr, idx) != NULL);
21906 return duk_known_hstring(thr, idx);
21907}
21908#endif
21909
21910/* Push Object.prototype.toString() output for 'tv'. */
21911DUK_INTERNAL void duk_push_class_string_tval(duk_hthread *thr, duk_tval *tv, duk_bool_t avoid_side_effects) {
21912 duk_hobject *h_obj;
21913 duk_small_uint_t classnum;
21914 duk_small_uint_t stridx;
21915 duk_tval tv_tmp;
21916
21918 DUK_ASSERT(tv != NULL);
21919
21920 /* Stabilize 'tv', duk_push_literal() may trigger side effects. */
21921 DUK_TVAL_SET_TVAL(&tv_tmp, tv);
21922 tv = &tv_tmp;
21923
21924 /* Conceptually for any non-undefined/null value we should do a
21925 * ToObject() coercion and look up @@toStringTag (from the object
21926 * prototype) to see if a custom result should be used, with the
21927 * exception of Arrays which are handled specially first.
21928 *
21929 * We'd like to avoid the actual conversion, but even for primitive
21930 * types the prototype may have @@toStringTag. What's worse, the
21931 * @@toStringTag property may be a getter that must get the object
21932 * coerced value (not the prototype) as its 'this' binding.
21933 *
21934 * For now, do an actual object coercion. This could be avoided by
21935 * doing a side effect free lookup to see if a getter would be invoked.
21936 * If not, the value can be read directly and the object coercion could
21937 * be avoided. This may not be worth it in practice, because
21938 * Object.prototype.toString() is usually not performance critical.
21939 */
21940
21941 duk_push_literal(thr, "[object "); /* -> [ ... "[object" ] */
21942
21943 switch (DUK_TVAL_GET_TAG(tv)) {
21944 case DUK_TAG_UNUSED: /* Treat like 'undefined', shouldn't happen. */
21945 case DUK_TAG_UNDEFINED: {
21947 goto finish;
21948 }
21949 case DUK_TAG_NULL: {
21951 goto finish;
21952 }
21953 }
21954
21955 duk_push_tval(thr, tv);
21956 tv = NULL; /* Invalidated by ToObject(). */
21957 h_obj = duk_to_hobject(thr, -1);
21958 DUK_ASSERT(h_obj != NULL);
21959 if (duk_js_isarray_hobject(h_obj)) {
21960 stridx = DUK_STRIDX_UC_ARRAY;
21961 } else {
21962 /* [ ... "[object" obj ] */
21963
21964#if defined(DUK_USE_SYMBOL_BUILTIN)
21965 /* XXX: better handling with avoid_side_effects == 1; lookup tval
21966 * without Proxy or getter side effects, and use it in sanitized
21967 * form if it's a string.
21968 */
21969 if (!avoid_side_effects) {
21971 if (duk_is_string_notsymbol(thr, -1)) {
21972 duk_remove_m2(thr);
21973 goto finish;
21974 }
21975 duk_pop_unsafe(thr);
21976 }
21977#else
21978 DUK_UNREF(avoid_side_effects);
21979#endif
21980
21981 classnum = DUK_HOBJECT_GET_CLASS_NUMBER(h_obj);
21982 stridx = DUK_HOBJECT_CLASS_NUMBER_TO_STRIDX(classnum);
21984 duk_pop_unsafe(thr);
21985 duk_push_hstring_stridx(thr, stridx);
21986
21987finish:
21988 /* [ ... "[object" tag ] */
21989 duk_push_literal(thr, "]");
21990 duk_concat(thr, 3); /* [ ... "[object" tag "]" ] -> [ ... res ] */
21991}
21992
21993/* XXX: other variants like uint, u32 etc */
21995duk_to_int_clamped_raw(duk_hthread *thr, duk_idx_t idx, duk_int_t minval, duk_int_t maxval, duk_bool_t *out_clamped) {
21996 duk_tval *tv;
21997 duk_tval tv_tmp;
21998 duk_double_t d, dmin, dmax;
21999 duk_int_t res;
22000 duk_bool_t clamped = 0;
22001
22003
22004 tv = duk_require_tval(thr, idx);
22005 DUK_ASSERT(tv != NULL);
22006 d = duk_js_tointeger(thr, tv); /* E5 Section 9.4, ToInteger() */
22007
22008 dmin = (duk_double_t) minval;
22009 dmax = (duk_double_t) maxval;
22010
22011 if (d < dmin) {
22012 clamped = 1;
22013 res = minval;
22014 d = dmin;
22015 } else if (d > dmax) {
22016 clamped = 1;
22017 res = maxval;
22018 d = dmax;
22019 } else {
22020 res = (duk_int_t) d;
22021 }
22022 DUK_UNREF(d); /* SCANBUILD: with suitable dmin/dmax limits 'd' is unused */
22023 /* 'd' and 'res' agree here */
22024
22025 /* Relookup in case duk_js_tointeger() ends up e.g. coercing an object. */
22026 tv = duk_get_tval(thr, idx);
22027 DUK_ASSERT(tv != NULL); /* not popped by side effect */
22028 DUK_TVAL_SET_TVAL(&tv_tmp, tv);
22029#if defined(DUK_USE_FASTINT)
22030#if (DUK_INT_MAX <= 0x7fffffffL)
22031 DUK_TVAL_SET_I32(tv, res);
22032#else
22033 /* Clamping needed if duk_int_t is 64 bits. */
22034 if (res >= DUK_FASTINT_MIN && res <= DUK_FASTINT_MAX) {
22035 DUK_TVAL_SET_FASTINT(tv, res);
22036 } else {
22037 DUK_TVAL_SET_NUMBER(tv, d);
22038 }
22039#endif
22040#else
22041 DUK_TVAL_SET_NUMBER(tv, d); /* no need to incref */
22042#endif
22043 DUK_TVAL_DECREF(thr, &tv_tmp); /* side effects */
22044
22045 if (out_clamped) {
22046 *out_clamped = clamped;
22047 } else {
22048 /* coerced value is updated to value stack even when RangeError thrown */
22049 if (clamped) {
22051 DUK_WO_NORETURN(return 0;);
22052 }
22053 }
22055 return res;
22056}
22057
22060
22062
22063 return duk_to_int_clamped_raw(thr, idx, minval, maxval, &dummy);
22064}
22065
22068 return duk_to_int_clamped_raw(thr, idx, minval, maxval, NULL); /* out_clamped==NULL -> RangeError if outside range */
22069}
22070
22071DUK_EXTERNAL const char *duk_to_string(duk_hthread *thr, duk_idx_t idx) {
22072 duk_tval *tv;
22073
22075
22076 idx = duk_require_normalize_index(thr, idx);
22077 tv = DUK_GET_TVAL_POSIDX(thr, idx);
22078 DUK_ASSERT(tv != NULL);
22079
22080 switch (DUK_TVAL_GET_TAG(tv)) {
22081 case DUK_TAG_UNDEFINED: {
22083 break;
22084 }
22085 case DUK_TAG_NULL: {
22087 break;
22088 }
22089 case DUK_TAG_BOOLEAN: {
22090 if (DUK_TVAL_GET_BOOLEAN(tv)) {
22092 } else {
22094 }
22095 break;
22096 }
22097 case DUK_TAG_STRING: {
22098 /* Nop for actual strings, TypeError for Symbols.
22099 * Because various internals rely on ToString() coercion of
22100 * internal strings, -allow- (NOP) string coercion for hidden
22101 * symbols.
22102 */
22103#if 1
22104 duk_hstring *h;
22105 h = DUK_TVAL_GET_STRING(tv);
22106 DUK_ASSERT(h != NULL);
22109 DUK_WO_NORETURN(goto skip_replace;);
22110 } else {
22111 goto skip_replace;
22112 }
22113#else
22114 goto skip_replace;
22115#endif
22116 break;
22117 }
22118 case DUK_TAG_BUFFER: /* Go through Uint8Array.prototype.toString() for coercion. */
22119 case DUK_TAG_OBJECT: {
22120 /* Plain buffers: go through ArrayBuffer.prototype.toString()
22121 * for coercion.
22122 *
22123 * Symbol objects: duk_to_primitive() results in a plain symbol
22124 * value, and duk_to_string() then causes a TypeError.
22125 */
22127 DUK_ASSERT(!duk_is_buffer(thr, idx)); /* ToPrimitive() must guarantee */
22128 DUK_ASSERT(!duk_is_object(thr, idx));
22129 return duk_to_string(thr, idx); /* Note: recursive call */
22130 }
22131 case DUK_TAG_POINTER: {
22132 void *ptr = DUK_TVAL_GET_POINTER(tv);
22133 if (ptr != NULL) {
22134 duk_push_sprintf(thr, DUK_STR_FMT_PTR, (void *) ptr);
22135 } else {
22136 /* Represent a null pointer as 'null' to be consistent with
22137 * the JX format variant. Native '%p' format for a NULL
22138 * pointer may be e.g. '(nil)'.
22139 */
22141 }
22142 break;
22143 }
22144 case DUK_TAG_LIGHTFUNC: {
22145 /* Should match Function.prototype.toString() */
22147 break;
22148 }
22149#if defined(DUK_USE_FASTINT)
22150 case DUK_TAG_FASTINT:
22151#endif
22152 default: {
22153 /* number */
22156 duk_push_tval(thr, tv);
22157 duk_numconv_stringify(thr, 10 /*radix*/, 0 /*precision:shortest*/, 0 /*force_exponential*/);
22158 break;
22159 }
22160 }
22161
22162 duk_replace(thr, idx);
22163
22164skip_replace:
22165 DUK_ASSERT(duk_is_string(thr, idx));
22166 return duk_require_string(thr, idx);
22167}
22170 duk_hstring *ret;
22171
22174 duk_to_string(thr, idx);
22175 ret = duk_get_hstring(thr, idx);
22176 DUK_ASSERT(ret != NULL);
22177 return ret;
22178}
22179
22182 return duk_to_hstring(thr, -1);
22183}
22184
22186 duk_hstring *ret;
22187
22189
22190 ret = duk_get_hstring(thr, idx);
22191 if (DUK_UNLIKELY(ret && DUK_HSTRING_HAS_SYMBOL(ret))) {
22192 return ret;
22193 }
22194 return duk_to_hstring(thr, idx);
22195}
22196
22197/* Convert a plain buffer or any buffer object into a string, using the buffer
22198 * bytes 1:1 in the internal string representation. For views the active byte
22199 * slice (not element slice interpreted as an initializer) is used. This is
22200 * necessary in Duktape 2.x because ToString(plainBuffer) no longer creates a
22201 * string with the same bytes as in the buffer but rather (usually)
22202 * '[object ArrayBuffer]'.
22203 */
22205 void *ptr_src;
22206 duk_size_t len;
22207 const char *res;
22208
22210
22211 idx = duk_require_normalize_index(thr, idx);
22212
22213 ptr_src = duk_require_buffer_data(thr, idx, &len);
22214 DUK_ASSERT(ptr_src != NULL || len == 0);
22215
22216 res = duk_push_lstring(thr, (const char *) ptr_src, len);
22217 duk_replace(thr, idx);
22218 return res;
22219}
22220
22222 duk_hbuffer *h_buf;
22223 const duk_uint8_t *src_data;
22224 duk_size_t src_size;
22225 duk_uint8_t *dst_data;
22226
22228
22229 idx = duk_require_normalize_index(thr, idx);
22230
22231 h_buf = duk_get_hbuffer(thr, idx);
22232 if (h_buf != NULL) {
22233 /* Buffer is kept as is, with the fixed/dynamic nature of the
22234 * buffer only changed if requested. An external buffer
22235 * is converted into a non-external dynamic buffer in a
22236 * duk_to_dynamic_buffer() call.
22237 */
22238 duk_uint_t tmp;
22239 duk_uint8_t *tmp_ptr;
22240
22241 tmp_ptr = (duk_uint8_t *) DUK_HBUFFER_GET_DATA_PTR(thr->heap, h_buf);
22242 src_data = (const duk_uint8_t *) tmp_ptr;
22243 src_size = DUK_HBUFFER_GET_SIZE(h_buf);
22244
22246 if ((tmp == mode && !DUK_HBUFFER_HAS_EXTERNAL(h_buf)) || mode == DUK_BUF_MODE_DONTCARE) {
22247 /* Note: src_data may be NULL if input is a zero-size
22248 * dynamic buffer.
22249 */
22250 dst_data = tmp_ptr;
22251 goto skip_copy;
22252 }
22253 } else {
22254 /* Non-buffer value is first ToString() coerced, then converted
22255 * to a buffer (fixed buffer is used unless a dynamic buffer is
22256 * explicitly requested). Symbols are rejected with a TypeError.
22257 * XXX: C API could maybe allow symbol-to-buffer coercion?
22258 */
22259 src_data = (const duk_uint8_t *) duk_to_lstring(thr, idx, &src_size);
22260 }
22261
22262 dst_data = (duk_uint8_t *) duk_push_buffer(thr, src_size, (mode == DUK_BUF_MODE_DYNAMIC) /*dynamic*/);
22263 /* dst_data may be NULL if size is zero. */
22264 duk_memcpy_unsafe((void *) dst_data, (const void *) src_data, (size_t) src_size);
22265
22266 duk_replace(thr, idx);
22267skip_copy:
22268
22269 if (out_size) {
22270 *out_size = src_size;
22271 }
22272 return dst_data;
22273}
22274
22276 duk_tval *tv;
22277 void *res;
22278
22280
22281 idx = duk_require_normalize_index(thr, idx);
22282 tv = DUK_GET_TVAL_POSIDX(thr, idx);
22283 DUK_ASSERT(tv != NULL);
22284
22285 switch (DUK_TVAL_GET_TAG(tv)) {
22286 case DUK_TAG_UNDEFINED:
22287 case DUK_TAG_NULL:
22288 case DUK_TAG_BOOLEAN:
22289 res = NULL;
22290 break;
22291 case DUK_TAG_POINTER:
22292 res = DUK_TVAL_GET_POINTER(tv);
22293 break;
22294 case DUK_TAG_STRING:
22295 case DUK_TAG_OBJECT:
22296 case DUK_TAG_BUFFER:
22297 /* Heap allocated: return heap pointer which is NOT useful
22298 * for the caller, except for debugging.
22299 */
22300 res = (void *) DUK_TVAL_GET_HEAPHDR(tv);
22301 break;
22302 case DUK_TAG_LIGHTFUNC:
22303 /* Function pointers do not always cast correctly to void *
22304 * (depends on memory and segmentation model for instance),
22305 * so they coerce to NULL.
22306 */
22307 res = NULL;
22308 break;
22309#if defined(DUK_USE_FASTINT)
22310 case DUK_TAG_FASTINT:
22311#endif
22312 default:
22313 /* number */
22316 res = NULL;
22317 break;
22318 }
22319
22320 duk_push_pointer(thr, res);
22321 duk_replace(thr, idx);
22322 return res;
22323}
22324
22326 duk_idx_t nargs;
22327 duk_uint_t flags = 0; /* shared flags for a subset of types */
22328 duk_small_uint_t lf_len;
22329 duk_hnatfunc *nf;
22330
22331 nargs = (duk_idx_t) DUK_LFUNC_FLAGS_GET_NARGS(lf_flags);
22332 if (nargs == DUK_LFUNC_NARGS_VARARGS) {
22333 nargs = (duk_idx_t) DUK_VARARGS;
22334 }
22335
22339 (void) duk__push_c_function_raw(thr, func, nargs, flags, DUK_BIDX_NATIVE_FUNCTION_PROTOTYPE);
22340
22341 lf_len = DUK_LFUNC_FLAGS_GET_LENGTH(lf_flags);
22342 if ((duk_idx_t) lf_len != nargs) {
22343 /* Explicit length is only needed if it differs from 'nargs'. */
22344 duk_push_int(thr, (duk_int_t) lf_len);
22346 }
22347
22348#if defined(DUK_USE_FUNC_NAME_PROPERTY)
22349 duk_push_lightfunc_name_raw(thr, func, lf_flags);
22351#endif
22352
22353 nf = duk_known_hnatfunc(thr, -1);
22354 nf->magic = (duk_int16_t) DUK_LFUNC_FLAGS_GET_MAGIC(lf_flags);
22355}
22356
22358 duk_tval *tv;
22359 duk_uint_t flags = 0; /* shared flags for a subset of types */
22360 duk_small_int_t proto = 0;
22361
22363
22364 idx = duk_require_normalize_index(thr, idx);
22365 tv = DUK_GET_TVAL_POSIDX(thr, idx);
22366 DUK_ASSERT(tv != NULL);
22367
22368 switch (DUK_TVAL_GET_TAG(tv)) {
22369#if !defined(DUK_USE_BUFFEROBJECT_SUPPORT)
22370 case DUK_TAG_BUFFER: /* With no bufferobject support, don't object coerce. */
22371#endif
22372 case DUK_TAG_UNDEFINED:
22373 case DUK_TAG_NULL: {
22375 DUK_WO_NORETURN(return;);
22376 break;
22377 }
22378 case DUK_TAG_BOOLEAN: {
22379 flags =
22382 goto create_object;
22383 }
22384 case DUK_TAG_STRING: {
22385 duk_hstring *h;
22386 h = DUK_TVAL_GET_STRING(tv);
22387 DUK_ASSERT(h != NULL);
22392 } else {
22396 }
22397 goto create_object;
22398 }
22399 case DUK_TAG_OBJECT: {
22400 /* nop */
22401 break;
22402 }
22403#if defined(DUK_USE_BUFFEROBJECT_SUPPORT)
22404 case DUK_TAG_BUFFER: {
22405 /* A plain buffer object coerces to a full ArrayBuffer which
22406 * is not fully transparent behavior (ToObject() should be a
22407 * nop for an object). This behavior matches lightfuncs which
22408 * also coerce to an equivalent Function object. There are
22409 * also downsides to defining ToObject(plainBuffer) as a no-op;
22410 * for example duk_to_hobject() could result in a NULL pointer.
22411 */
22412 duk_hbuffer *h_buf;
22413
22414 h_buf = DUK_TVAL_GET_BUFFER(tv);
22415 DUK_ASSERT(h_buf != NULL);
22417 goto replace_value;
22418 }
22419#endif /* DUK_USE_BUFFEROBJECT_SUPPORT */
22420 case DUK_TAG_POINTER: {
22421 flags =
22424 goto create_object;
22425 }
22426 case DUK_TAG_LIGHTFUNC: {
22427 /* Lightfunc coerces to a Function instance with concrete
22428 * properties. Since 'length' is virtual for Duktape/C
22429 * functions, don't need to define that. The result is made
22430 * extensible to mimic what happens to strings in object
22431 * coercion:
22432 *
22433 * > Object.isExtensible(Object('foo'))
22434 * true
22435 */
22436 duk_small_uint_t lf_flags;
22437 duk_c_function func;
22438
22439 DUK_TVAL_GET_LIGHTFUNC(tv, func, lf_flags);
22440 duk__push_func_from_lightfunc(thr, func, lf_flags);
22441 goto replace_value;
22442 }
22443#if defined(DUK_USE_FASTINT)
22444 case DUK_TAG_FASTINT:
22445#endif
22446 default: {
22449 flags =
22452 goto create_object;
22453 }
22454 }
22455 DUK_ASSERT(duk_is_object(thr, idx));
22456 return;
22457
22458create_object:
22459 (void) duk_push_object_helper(thr, flags, proto);
22460
22461 /* Note: Boolean prototype's internal value property is not writable,
22462 * but duk_xdef_prop_stridx() disregards the write protection. Boolean
22463 * instances are immutable.
22465 * String and buffer special behaviors are already enabled which is not
22466 * ideal, but a write to the internal value is not affected by them.
22467 */
22468 duk_dup(thr, idx);
22470
22471replace_value:
22472 duk_replace(thr, idx);
22473 DUK_ASSERT(duk_is_object(thr, idx));
22474}
22475
22477 duk_hobject *ret;
22480
22481 duk_to_object(thr, idx);
22482 ret = duk_known_hobject(thr, idx);
22483 return ret;
22484}
22485
22487 * Type checking
22488 */
22489
22491 duk_tval *tv;
22492
22493 tv = duk_get_tval_or_unused(thr, idx);
22494 DUK_ASSERT(tv != NULL);
22495 return (DUK_TVAL_GET_TAG(tv) == tag);
22496}
22497
22499 duk_hobject *obj;
22500
22502
22503 obj = duk_get_hobject(thr, idx);
22504 if (obj) {
22505 return (DUK_HEAPHDR_CHECK_FLAG_BITS((duk_heaphdr *) obj, flag_mask) ? 1 : 0);
22506 }
22507 return 0;
22508}
22509
22511 DUK_ASSERT(tv != NULL);
22512
22513#if defined(DUK_USE_PACKED_TVAL)
22514 switch (DUK_TVAL_GET_TAG(tv)) {
22515 case DUK_TAG_UNUSED:
22516 return DUK_TYPE_NONE;
22517 case DUK_TAG_UNDEFINED:
22518 return DUK_TYPE_UNDEFINED;
22519 case DUK_TAG_NULL:
22520 return DUK_TYPE_NULL;
22521 case DUK_TAG_BOOLEAN:
22522 return DUK_TYPE_BOOLEAN;
22523 case DUK_TAG_STRING:
22524 return DUK_TYPE_STRING;
22525 case DUK_TAG_OBJECT:
22526 return DUK_TYPE_OBJECT;
22527 case DUK_TAG_BUFFER:
22528 return DUK_TYPE_BUFFER;
22529 case DUK_TAG_POINTER:
22530 return DUK_TYPE_POINTER;
22531 case DUK_TAG_LIGHTFUNC:
22532 return DUK_TYPE_LIGHTFUNC;
22533#if defined(DUK_USE_FASTINT)
22534 case DUK_TAG_FASTINT:
22535#endif
22536 default:
22537 /* Note: number has no explicit tag (in 8-byte representation) */
22540 return DUK_TYPE_NUMBER;
22541 }
22542#else /* DUK_USE_PACKED_TVAL */
22546#endif /* DUK_USE_PACKED_TVAL */
22547}
22548
22550 duk_tval *tv;
22551
22553
22554 tv = duk_get_tval_or_unused(thr, idx);
22555 DUK_ASSERT(tv != NULL);
22556
22557 return duk_get_type_tval(tv);
22558}
22559
22560#if defined(DUK_USE_VERBOSE_ERRORS) && defined(DUK_USE_PARANOID_ERRORS)
22561DUK_LOCAL const char * const duk__type_names[] = { "none", "undefined", "null", "boolean", "number",
22562 "string", "object", "buffer", "pointer", "lightfunc" };
22563
22564DUK_INTERNAL const char *duk_get_type_name(duk_hthread *thr, duk_idx_t idx) {
22565 duk_int_t type_tag;
22566
22568
22569 type_tag = duk_get_type(thr, idx);
22570 DUK_ASSERT(type_tag >= DUK_TYPE_MIN && type_tag <= DUK_TYPE_MAX);
22571 DUK_ASSERT(DUK_TYPE_MIN == 0 && sizeof(duk__type_names) / sizeof(const char *) == DUK_TYPE_MAX + 1);
22572
22573 return duk__type_names[type_tag];
22574}
22575#endif /* DUK_USE_VERBOSE_ERRORS && DUK_USE_PARANOID_ERRORS */
22576
22578 duk_tval *tv;
22579 duk_hobject *obj;
22580
22582
22583 tv = duk_get_tval_or_unused(thr, idx);
22584 DUK_ASSERT(tv != NULL);
22585
22586 switch (DUK_TVAL_GET_TAG(tv)) {
22587 case DUK_TAG_OBJECT:
22588 obj = DUK_TVAL_GET_OBJECT(tv);
22589 DUK_ASSERT(obj != NULL);
22590 return DUK_HOBJECT_GET_CLASS_NUMBER(obj);
22592 /* Buffers behave like Uint8Array objects. */
22594 case DUK_TAG_LIGHTFUNC:
22595 /* Lightfuncs behave like Function objects. */
22597 default:
22598 /* Primitive or UNUSED, no class number. */
22600 }
22601}
22602
22605
22606 return (duk_get_type(thr, idx) == type) ? 1 : 0;
22607}
22608
22610 DUK_ASSERT(tv != NULL);
22611
22612#if defined(DUK_USE_PACKED_TVAL)
22613 switch (DUK_TVAL_GET_TAG(tv)) {
22614 case DUK_TAG_UNUSED:
22615 return DUK_TYPE_MASK_NONE;
22616 case DUK_TAG_UNDEFINED:
22618 case DUK_TAG_NULL:
22619 return DUK_TYPE_MASK_NULL;
22620 case DUK_TAG_BOOLEAN:
22621 return DUK_TYPE_MASK_BOOLEAN;
22622 case DUK_TAG_STRING:
22623 return DUK_TYPE_MASK_STRING;
22624 case DUK_TAG_OBJECT:
22625 return DUK_TYPE_MASK_OBJECT;
22626 case DUK_TAG_BUFFER:
22627 return DUK_TYPE_MASK_BUFFER;
22628 case DUK_TAG_POINTER:
22629 return DUK_TYPE_MASK_POINTER;
22630 case DUK_TAG_LIGHTFUNC:
22632#if defined(DUK_USE_FASTINT)
22633 case DUK_TAG_FASTINT:
22634#endif
22635 default:
22636 /* Note: number has no explicit tag (in 8-byte representation) */
22639 return DUK_TYPE_MASK_NUMBER;
22640 }
22641#else /* DUK_USE_PACKED_TVAL */
22645#endif /* DUK_USE_PACKED_TVAL */
22646}
22649 duk_tval *tv;
22650
22652
22653 tv = duk_get_tval_or_unused(thr, idx);
22654 DUK_ASSERT(tv != NULL);
22655
22656 return duk_get_type_mask_tval(tv);
22657}
22658
22661
22662 if (DUK_LIKELY((duk_get_type_mask(thr, idx) & mask) != 0U)) {
22663 return 1;
22664 }
22667 DUK_WO_NORETURN(return 0;);
22668 }
22669 return 0;
22671
22674 return duk__tag_check(thr, idx, DUK_TAG_UNDEFINED);
22676
22679 return duk__tag_check(thr, idx, DUK_TAG_NULL);
22680}
22681
22684 return duk__tag_check(thr, idx, DUK_TAG_BOOLEAN);
22685}
22686
22688 duk_tval *tv;
22689
22691
22693 * Number is special because it doesn't have a specific
22694 * tag in the 8-byte representation.
22695 */
22696
22697 /* XXX: shorter version for unpacked representation? */
22698
22699 tv = duk_get_tval_or_unused(thr, idx);
22700 DUK_ASSERT(tv != NULL);
22701 return DUK_TVAL_IS_NUMBER(tv);
22702}
22703
22705 /* XXX: This will now return false for non-numbers, even though they would
22706 * coerce to NaN (as a general rule). In particular, duk_get_number()
22707 * returns a NaN for non-numbers, so should this function also return
22708 * true for non-numbers?
22709 */
22710
22711 duk_tval *tv;
22712
22714
22715 tv = duk_get_tval_or_unused(thr, idx);
22716 DUK_ASSERT(tv != NULL);
22717
22718 /* XXX: for packed duk_tval an explicit "is number" check is unnecessary */
22719 if (!DUK_TVAL_IS_NUMBER(tv)) {
22720 return 0;
22721 }
22724
22727 return duk__tag_check(thr, idx, DUK_TAG_STRING);
22729
22732 return duk_get_hstring_notsymbol(thr, idx) != NULL;
22733}
22737 return duk__tag_check(thr, idx, DUK_TAG_OBJECT);
22738}
22739
22742 return duk__tag_check(thr, idx, DUK_TAG_BUFFER);
22743}
22744
22745#if defined(DUK_USE_BUFFEROBJECT_SUPPORT)
22747 duk_tval *tv;
22748
22750
22751 tv = duk_get_tval_or_unused(thr, idx);
22752 DUK_ASSERT(tv != NULL);
22753 if (DUK_TVAL_IS_BUFFER(tv)) {
22754 return 1;
22755 } else if (DUK_TVAL_IS_OBJECT(tv)) {
22757 DUK_ASSERT(h != NULL);
22758 if (DUK_HOBJECT_IS_BUFOBJ(h)) {
22759 return 1;
22760 }
22762 return 0;
22763}
22764#else /* DUK_USE_BUFFEROBJECT_SUPPORT */
22767
22768 return duk_is_buffer(thr, idx);
22769}
22770
22771#endif /* DUK_USE_BUFFEROBJECT_SUPPORT */
22772
22775 return duk__tag_check(thr, idx, DUK_TAG_POINTER);
22776}
22777
22780 return duk__tag_check(thr, idx, DUK_TAG_LIGHTFUNC);
22781}
22782
22784 duk_hstring *h;
22785
22787 h = duk_get_hstring(thr, idx);
22788 /* Use DUK_LIKELY() here because caller may be more likely to type
22789 * check an expected symbol than not.
22790 */
22791 if (DUK_LIKELY(h != NULL && DUK_HSTRING_HAS_SYMBOL(h))) {
22792 return 1;
22793 }
22794 return 0;
22795}
22796
22797/* IsArray(), returns true for Array instance or Proxy of Array instance. */
22799 duk_tval *tv;
22800
22802
22803 tv = duk_get_tval(thr, idx);
22804 if (tv) {
22805 return duk_js_isarray(tv);
22806 }
22807 return 0;
22808}
22809
22811 duk_tval *tv;
22812
22814
22815 tv = duk_get_tval_or_unused(thr, idx);
22817 duk_hobject *h;
22818 h = DUK_TVAL_GET_OBJECT(tv);
22819 DUK_ASSERT(h != NULL);
22820 return DUK_HOBJECT_HAS_CALLABLE(h) ? 1 : 0;
22821 }
22822 if (DUK_TVAL_IS_LIGHTFUNC(tv)) {
22823 return 1;
22824 }
22825 return 0;
22826}
22827
22830
22831 DUK_UNREF(thr);
22832
22834 duk_hobject *h;
22835 h = DUK_TVAL_GET_OBJECT(tv);
22836 DUK_ASSERT(h != NULL);
22837 return DUK_HOBJECT_HAS_CALLABLE(h) ? 1 : 0;
22838 }
22839 if (DUK_TVAL_IS_LIGHTFUNC(tv)) {
22840 return 1;
22841 }
22842 return 0;
22843}
22844
22846 duk_tval *tv;
22847
22849
22850 tv = duk_get_tval_or_unused(thr, idx);
22852 duk_hobject *h;
22853 h = DUK_TVAL_GET_OBJECT(tv);
22854 DUK_ASSERT(h != NULL);
22855 return DUK_HOBJECT_HAS_CONSTRUCTABLE(h) ? 1 : 0;
22857 if (DUK_TVAL_IS_LIGHTFUNC(tv)) {
22858 return 1;
22859 }
22860 return 0;
22862
22867
22871}
22872
22876}
22877
22879 duk_hobject *obj;
22880
22882
22883 obj = duk_get_hobject(thr, idx);
22884 if (obj) {
22886 }
22887 return 0;
22888}
22889
22891 duk_tval *tv;
22892
22894
22895 tv = duk_get_tval_or_unused(thr, idx);
22896 DUK_ASSERT(tv != NULL);
22897 if (DUK_TVAL_IS_BUFFER(tv)) {
22899 DUK_ASSERT(h != NULL);
22900 return (DUK_HBUFFER_HAS_DYNAMIC(h) ? 0 : 1);
22901 }
22902 return 0;
22903}
22904
22906 duk_tval *tv;
22907
22909
22910 tv = duk_get_tval_or_unused(thr, idx);
22911 DUK_ASSERT(tv != NULL);
22912 if (DUK_TVAL_IS_BUFFER(tv)) {
22914 DUK_ASSERT(h != NULL);
22915 return (DUK_HBUFFER_HAS_DYNAMIC(h) && !DUK_HBUFFER_HAS_EXTERNAL(h) ? 1 : 0);
22916 }
22917 return 0;
22918}
22919
22921 duk_tval *tv;
22922
22924
22925 tv = duk_get_tval_or_unused(thr, idx);
22926 DUK_ASSERT(tv != NULL);
22927 if (DUK_TVAL_IS_BUFFER(tv)) {
22929 DUK_ASSERT(h != NULL);
22930 return (DUK_HBUFFER_HAS_DYNAMIC(h) && DUK_HBUFFER_HAS_EXTERNAL(h) ? 1 : 0);
22931 }
22932 return 0;
22933}
22934
22936 duk_hobject *h;
22937 duk_uint_t sanity;
22938
22940
22941 h = duk_get_hobject(thr, idx);
22942
22944 do {
22945 if (!h) {
22946 return DUK_ERR_NONE;
22947 }
22948
22949 /* XXX: something more convenient? */
22950
22951 if (h == thr->builtins[DUK_BIDX_EVAL_ERROR_PROTOTYPE]) {
22952 return DUK_ERR_EVAL_ERROR;
22953 }
22955 return DUK_ERR_RANGE_ERROR;
22956 }
22959 }
22961 return DUK_ERR_SYNTAX_ERROR;
22962 }
22963 if (h == thr->builtins[DUK_BIDX_TYPE_ERROR_PROTOTYPE]) {
22964 return DUK_ERR_TYPE_ERROR;
22965 }
22966 if (h == thr->builtins[DUK_BIDX_URI_ERROR_PROTOTYPE]) {
22967 return DUK_ERR_URI_ERROR;
22968 }
22969 if (h == thr->builtins[DUK_BIDX_ERROR_PROTOTYPE]) {
22970 return DUK_ERR_ERROR;
22972
22973 h = DUK_HOBJECT_GET_PROTOTYPE(thr->heap, h);
22974 } while (--sanity > 0);
22975
22976 return DUK_ERR_NONE;
22977}
22978
22979/*
22980 * Pushers
22981 */
22982
22984 duk_tval *tv_slot;
22985
22987 DUK_ASSERT(tv != NULL);
22988
22990 tv_slot = thr->valstack_top++;
22991 DUK_TVAL_SET_TVAL(tv_slot, tv);
22992 DUK_TVAL_INCREF(thr, tv); /* no side effects */
22993}
22994
22997
22999
23000 /* Because value stack init policy is 'undefined above top',
23001 * we don't need to write, just assert.
23002 */
23003 thr->valstack_top++;
23005}
23006
23008 duk_tval *tv_slot;
23009
23012 tv_slot = thr->valstack_top++;
23013 DUK_TVAL_SET_NULL(tv_slot);
23014}
23017 duk_tval *tv_slot;
23019
23022 b = (val ? 1 : 0); /* ensure value is 1 or 0 (not other non-zero) */
23023 tv_slot = thr->valstack_top++;
23025}
23026
23028 duk_tval *tv_slot;
23029
23032 tv_slot = thr->valstack_top++;
23035
23037 duk_tval *tv_slot;
23038
23041 tv_slot = thr->valstack_top++;
23043}
23044
23045/* normalize NaN which may not match our canonical internal NaN */
23047 duk_tval *tv_slot;
23049
23052 du.d = val;
23054 tv_slot = thr->valstack_top++;
23055 DUK_TVAL_SET_NUMBER(tv_slot, du.d);
23056}
23057
23059#if defined(DUK_USE_FASTINT)
23060 duk_tval *tv_slot;
23061
23064 tv_slot = thr->valstack_top++;
23065#if DUK_INT_MAX <= 0x7fffffffL
23066 DUK_TVAL_SET_I32(tv_slot, (duk_int32_t) val);
23067#else
23068 if (val >= DUK_FASTINT_MIN && val <= DUK_FASTINT_MAX) {
23069 DUK_TVAL_SET_FASTINT(tv_slot, (duk_int64_t) val);
23070 } else {
23071 duk_double_t = (duk_double_t) val;
23072 DUK_TVAL_SET_NUMBER(tv_slot, d);
23073 }
23074#endif
23075#else /* DUK_USE_FASTINT */
23076 duk_tval *tv_slot;
23077 duk_double_t d;
23078
23081 d = (duk_double_t) val;
23082 tv_slot = thr->valstack_top++;
23083 DUK_TVAL_SET_NUMBER(tv_slot, d);
23084#endif /* DUK_USE_FASTINT */
23085}
23086
23088#if defined(DUK_USE_FASTINT)
23089 duk_tval *tv_slot;
23090
23093 tv_slot = thr->valstack_top++;
23094#if DUK_UINT_MAX <= 0xffffffffUL
23095 DUK_TVAL_SET_U32(tv_slot, (duk_uint32_t) val);
23096#else
23097 if (val <= DUK_FASTINT_MAX) { /* val is unsigned so >= 0 */
23098 /* XXX: take advantage of val being unsigned, no need to mask */
23099 DUK_TVAL_SET_FASTINT(tv_slot, (duk_int64_t) val);
23100 } else {
23101 duk_double_t = (duk_double_t) val;
23102 DUK_TVAL_SET_NUMBER(tv_slot, d);
23103 }
23104#endif
23105#else /* DUK_USE_FASTINT */
23106 duk_tval *tv_slot;
23107 duk_double_t d;
23108
23111 d = (duk_double_t) val;
23112 tv_slot = thr->valstack_top++;
23113 DUK_TVAL_SET_NUMBER(tv_slot, d);
23114#endif /* DUK_USE_FASTINT */
23115}
23116
23118 duk_tval *tv_slot;
23120
23125 tv_slot = thr->valstack_top++;
23126 DUK_TVAL_SET_NUMBER(tv_slot, du.d);
23127}
23128
23129DUK_EXTERNAL const char *duk_push_lstring(duk_hthread *thr, const char *str, duk_size_t len) {
23130 duk_hstring *h;
23131 duk_tval *tv_slot;
23132
23134
23135 /* Check stack before interning (avoid hanging temp). */
23137
23138 /* NULL with zero length represents an empty string; NULL with higher
23139 * length is also now treated like an empty string although it is
23140 * a bit dubious. This is unlike duk_push_string() which pushes a
23141 * 'null' if the input string is a NULL.
23142 */
23143 if (DUK_UNLIKELY(str == NULL)) {
23144 len = 0U;
23145 }
23146
23147 /* Check for maximum string length. */
23150 DUK_WO_NORETURN(return NULL;);
23152
23153 h = duk_heap_strtable_intern_checked(thr, (const duk_uint8_t *) str, (duk_uint32_t) len);
23154 DUK_ASSERT(h != NULL);
23155
23156 tv_slot = thr->valstack_top++;
23157 DUK_TVAL_SET_STRING(tv_slot, h);
23158 DUK_HSTRING_INCREF(thr, h); /* no side effects */
23159
23160 return (const char *) DUK_HSTRING_GET_DATA(h);
23161}
23162
23163DUK_EXTERNAL const char *duk_push_string(duk_hthread *thr, const char *str) {
23165
23166 if (str) {
23167 return duk_push_lstring(thr, str, DUK_STRLEN(str));
23168 } else {
23169 duk_push_null(thr);
23170 return NULL;
23171 }
23172}
23173
23174#if !defined(DUK_USE_PREFER_SIZE)
23175#if defined(DUK_USE_LITCACHE_SIZE)
23176DUK_EXTERNAL const char *duk_push_literal_raw(duk_hthread *thr, const char *str, duk_size_t len) {
23177 duk_hstring *h;
23178 duk_tval *tv_slot;
23179
23181 DUK_ASSERT(str != NULL);
23182 DUK_ASSERT(str[len] == (char) 0);
23183
23184 /* Check for maximum string length. */
23187 DUK_WO_NORETURN(return NULL;);
23188 }
23189
23190 h = duk_heap_strtable_intern_literal_checked(thr, (const duk_uint8_t *) str, (duk_uint32_t) len);
23191 DUK_ASSERT(h != NULL);
23192
23193 tv_slot = thr->valstack_top++;
23194 DUK_TVAL_SET_STRING(tv_slot, h);
23195 DUK_HSTRING_INCREF(thr, h); /* no side effects */
23196
23197 return (const char *) DUK_HSTRING_GET_DATA(h);
23199#else /* DUK_USE_LITCACHE_SIZE */
23200DUK_EXTERNAL const char *duk_push_literal_raw(duk_hthread *thr, const char *str, duk_size_t len) {
23202 DUK_ASSERT(str != NULL);
23203 DUK_ASSERT(str[len] == (char) 0);
23204
23205 return duk_push_lstring(thr, str, len);
23206}
23207#endif /* DUK_USE_LITCACHE_SIZE */
23208#endif /* !DUK_USE_PREFER_SIZE */
23209
23210DUK_EXTERNAL void duk_push_pointer(duk_hthread *thr, void *val) {
23211 duk_tval *tv_slot;
23212
23215 tv_slot = thr->valstack_top++;
23216 DUK_TVAL_SET_POINTER(tv_slot, val);
23217}
23218
23220 duk_hstring *h_tmp;
23221
23223
23224 /* XXX: this could be a direct DUK_SPRINTF to a buffer followed by duk_push_string() */
23225 duk_push_uint(thr, (duk_uint_t) i);
23226 h_tmp = duk_to_hstring_m1(thr);
23227 DUK_ASSERT(h_tmp != NULL);
23228 return h_tmp;
23229}
23230
23231DUK_LOCAL void duk__push_this_helper(duk_hthread *thr, duk_small_uint_t check_object_coercible) {
23232 duk_tval *tv_slot;
23233
23235
23236 DUK_ASSERT(DUK_TVAL_IS_UNDEFINED(thr->valstack_top)); /* because of valstack init policy */
23237 tv_slot = thr->valstack_top++;
23238
23239 if (DUK_UNLIKELY(thr->callstack_curr == NULL)) {
23240 if (check_object_coercible) {
23241 goto type_error;
23242 }
23243 /* 'undefined' already on stack top */
23244 } else {
23245 duk_tval *tv;
23246
23247 /* 'this' binding is just before current activation's bottom */
23248 DUK_ASSERT(thr->valstack_bottom > thr->valstack);
23249 tv = thr->valstack_bottom - 1;
23250 if (check_object_coercible && (DUK_TVAL_IS_UNDEFINED(tv) || DUK_TVAL_IS_NULL(tv))) {
23251 /* XXX: better macro for DUK_TVAL_IS_UNDEFINED_OR_NULL(tv) */
23252 goto type_error;
23254
23255 DUK_TVAL_SET_TVAL(tv_slot, tv);
23256 DUK_TVAL_INCREF(thr, tv);
23257 }
23258 return;
23260type_error:
23262 DUK_WO_NORETURN(return;);
23263}
23264
23267
23268 duk__push_this_helper(thr, 0 /*check_object_coercible*/);
23269}
23270
23273
23274 duk__push_this_helper(thr, 1 /*check_object_coercible*/);
23275}
23278 duk_hobject *h;
23279
23281
23282 duk__push_this_helper(thr, 1 /*check_object_coercible*/);
23283 h = duk_to_hobject(thr, -1);
23284 DUK_ASSERT(h != NULL);
23285 return h;
23286}
23287
23290
23291 duk__push_this_helper(thr, 1 /*check_object_coercible*/);
23292 return duk_to_hstring_m1(thr); /* This will reject all Symbol values; accepts Symbol objects. */
23293}
23297
23298 DUK_ASSERT(thr->callstack_top > 0); /* caller required to know */
23299 DUK_ASSERT(thr->callstack_curr != NULL); /* caller required to know */
23300 DUK_ASSERT(thr->valstack_bottom > thr->valstack); /* consequence of above */
23301 DUK_ASSERT(thr->valstack_bottom - 1 >= thr->valstack); /* 'this' binding exists */
23302
23303 return thr->valstack_bottom - 1;
23304}
23305
23307 duk_activation *act;
23308
23310
23311 /* https://www.ecma-international.org/ecma-262/6.0/#sec-meta-properties-runtime-semantics-evaluation
23312 * https://www.ecma-international.org/ecma-262/6.0/#sec-getnewtarget
23313 *
23314 * No newTarget support now, so as a first approximation
23315 * use the resolved (non-bound) target function.
23316 *
23317 * Check CONSTRUCT flag from current function, or if running
23318 * direct eval, from a non-direct-eval parent (with possibly
23319 * more than one nested direct eval). An alternative to this
23320 * would be to store [[NewTarget]] as a hidden symbol of the
23321 * lexical scope, and then just look up that variable.
23322 *
23323 * Calls from the application will either be for an empty
23324 * call stack, or a Duktape/C function as the top activation.
23325 */
23326
23327 act = thr->callstack_curr;
23328 for (;;) {
23329 if (act == NULL) {
23330 break;
23331 }
23332
23333 if (act->flags & DUK_ACT_FLAG_CONSTRUCT) {
23335 return;
23336 } else if (act->flags & DUK_ACT_FLAG_DIRECT_EVAL) {
23337 act = act->parent;
23338 } else {
23339 break;
23340 }
23341 }
23342
23343 duk_push_undefined(thr);
23344}
23345
23348
23350
23351 act = thr->callstack_curr;
23352 if (act != NULL) {
23353 duk_push_tval(thr, &act->tv_func);
23354 } else {
23355 duk_push_undefined(thr);
23356 }
23358
23361
23362 if (thr->heap->curr_thread) {
23364 } else {
23365 duk_push_undefined(thr);
23366 }
23367}
23368
23371
23373}
23374
23375/* XXX: size optimize */
23378 DUK_DDD(DUK_DDDPRINT("creating heap/global/thread stash on first use"));
23379 duk_pop_unsafe(thr);
23381 duk_dup_top(thr);
23383 -3,
23385 DUK_PROPDESC_FLAGS_C); /* [ ... parent stash stash ] -> [ ... parent stash ] */
23386 }
23388}
23389
23391 duk_heap *heap;
23393 heap = thr->heap;
23394 DUK_ASSERT(heap->heap_object != NULL);
23395 duk_push_hobject(thr, heap->heap_object);
23396 duk__push_stash(thr);
23397}
23398
23402 duk__push_stash(thr);
23403}
23407 if (DUK_UNLIKELY(target_thr == NULL)) {
23409 DUK_WO_NORETURN(return;);
23410 }
23411 duk_push_hobject(thr, (duk_hobject *) target_thr);
23412 duk__push_stash(thr);
23413}
23414
23415/* XXX: duk_ssize_t would be useful here */
23416DUK_LOCAL duk_int_t duk__try_push_vsprintf(duk_hthread *thr, void *buf, duk_size_t sz, const char *fmt, va_list ap) {
23417 duk_int_t len;
23418
23420 DUK_UNREF(thr);
23422 /* NUL terminator handling doesn't matter here */
23423 len = DUK_VSNPRINTF((char *) buf, sz, fmt, ap);
23424 if (len < (duk_int_t) sz) {
23425 /* Return value of 'sz' or more indicates output was (potentially)
23426 * truncated.
23427 */
23428 return (duk_int_t) len;
23429 }
23430 return -1;
23431}
23432
23433DUK_EXTERNAL const char *duk_push_vsprintf(duk_hthread *thr, const char *fmt, va_list ap) {
23434 duk_uint8_t stack_buf[DUK_PUSH_SPRINTF_INITIAL_SIZE];
23436 duk_bool_t pushed_buf = 0;
23437 void *buf;
23438 duk_int_t len; /* XXX: duk_ssize_t */
23439 const char *res;
23440
23442
23443 /* special handling of fmt==NULL */
23444 if (!fmt) {
23445 duk_hstring *h_str;
23447 h_str = duk_known_hstring(thr, -1);
23448 return (const char *) DUK_HSTRING_GET_DATA(h_str);
23449 }
23450
23451 /* initial estimate based on format string */
23452 sz = DUK_STRLEN(fmt) + 16; /* format plus something to avoid just missing */
23455 }
23456 DUK_ASSERT(sz > 0);
23457
23458 /* Try to make do with a stack buffer to avoid allocating a temporary buffer.
23459 * This works 99% of the time which is quite nice.
23460 */
23461 for (;;) {
23462 va_list ap_copy; /* copied so that 'ap' can be reused */
23463
23464 if (sz <= sizeof(stack_buf)) {
23465 buf = stack_buf;
23466 } else if (!pushed_buf) {
23467 pushed_buf = 1;
23468 buf = duk_push_dynamic_buffer(thr, sz);
23469 } else {
23470 buf = duk_resize_buffer(thr, -1, sz);
23471 }
23472 DUK_ASSERT(buf != NULL);
23473
23474 DUK_VA_COPY(ap_copy, ap);
23475 len = duk__try_push_vsprintf(thr, buf, sz, fmt, ap_copy);
23476 va_end(ap_copy);
23477 if (len >= 0) {
23478 break;
23479 }
23480
23481 /* failed, resize and try again */
23482 sz = sz * 2;
23485 DUK_WO_NORETURN(return NULL;);
23486 }
23488
23489 /* Cannot use duk_buffer_to_string() on the buffer because it is
23490 * usually larger than 'len'; 'buf' is also usually a stack buffer.
23491 */
23492 res = duk_push_lstring(thr, (const char *) buf, (duk_size_t) len); /* [ buf? res ] */
23493 if (pushed_buf) {
23494 duk_remove_m2(thr);
23495 }
23496 return res;
23497}
23498
23499DUK_EXTERNAL const char *duk_push_sprintf(duk_hthread *thr, const char *fmt, ...) {
23500 va_list ap;
23501 const char *ret;
23502
23504
23505 /* allow fmt==NULL */
23506 va_start(ap, fmt);
23507 ret = duk_push_vsprintf(thr, fmt, ap);
23508 va_end(ap);
23509
23510 return ret;
23511}
23512
23514 duk_uint_t hobject_flags_and_class,
23515 duk_small_int_t prototype_bidx) {
23516 duk_tval *tv_slot;
23517 duk_hobject *h;
23518
23520 DUK_ASSERT(prototype_bidx == -1 || (prototype_bidx >= 0 && prototype_bidx < DUK_NUM_BUILTINS));
23521
23523
23524 h = duk_hobject_alloc(thr, hobject_flags_and_class);
23525 DUK_ASSERT(h != NULL);
23526
23527 DUK_DDD(DUK_DDDPRINT("created object with flags: 0x%08lx", (unsigned long) h->hdr.h_flags));
23528
23529 tv_slot = thr->valstack_top;
23530 DUK_TVAL_SET_OBJECT(tv_slot, h);
23531 DUK_HOBJECT_INCREF(thr, h); /* no side effects */
23532 thr->valstack_top++;
23533
23534 /* object is now reachable */
23535
23536 if (prototype_bidx >= 0) {
23537 DUK_HOBJECT_SET_PROTOTYPE_INIT_INCREF(thr, h, thr->builtins[prototype_bidx]);
23538 } else {
23539 DUK_ASSERT(prototype_bidx == -1);
23540 DUK_ASSERT(DUK_HOBJECT_GET_PROTOTYPE(thr->heap, h) == NULL);
23541 }
23542
23543 return h;
23544}
23547 duk_hobject *h;
23548
23550
23551 h = duk_push_object_helper(thr, hobject_flags_and_class, -1);
23552 DUK_ASSERT(h != NULL);
23554 return h;
23556
23559
23560 (void) duk_push_object_helper(thr,
23564 return duk_get_top_index_unsafe(thr);
23565}
23566
23568 duk_uint_t flags;
23569 duk_harray *obj;
23570 duk_idx_t ret;
23571 duk_tval *tv_slot;
23572
23574
23577
23578 obj = duk_harray_alloc(thr, flags);
23579 DUK_ASSERT(obj != NULL);
23580
23582
23583 tv_slot = thr->valstack_top;
23584 DUK_TVAL_SET_OBJECT(tv_slot, (duk_hobject *) obj);
23585 DUK_HOBJECT_INCREF(thr, obj); /* XXX: could preallocate with refcount = 1 */
23586 ret = (duk_idx_t) (thr->valstack_top - thr->valstack_bottom);
23587 thr->valstack_top++;
23588
23589 DUK_ASSERT(obj->length == 0); /* Array .length starts at zero. */
23590 return ret;
23591}
23592
23594 duk_uint_t flags;
23595 duk_harray *obj;
23596 duk_idx_t ret;
23597 duk_tval *tv_slot;
23598
23600
23603
23604 obj = duk_harray_alloc(thr, flags);
23605 DUK_ASSERT(obj != NULL);
23606
23607 tv_slot = thr->valstack_top;
23608 DUK_TVAL_SET_OBJECT(tv_slot, (duk_hobject *) obj);
23609 DUK_HOBJECT_INCREF(thr, obj); /* XXX: could preallocate with refcount = 1 */
23610 ret = (duk_idx_t) (thr->valstack_top - thr->valstack_bottom);
23611 thr->valstack_top++;
23612
23613 DUK_ASSERT(obj->length == 0); /* Array .length starts at zero. */
23614 return ret;
23615}
23616
23618 /* XXX: API call could do this directly, cast to void in API macro. */
23619 duk_harray *a;
23620
23622
23623 (void) duk_push_array(thr);
23626 DUK_ASSERT(a != NULL);
23627 return a;
23628}
23629
23630/* Push a duk_harray with preallocated size (.length also set to match size).
23631 * Caller may then populate array part of the duk_harray directly.
23632 */
23634 duk_harray *a;
23635
23637
23638 a = duk_push_harray(thr);
23639
23640 duk_hobject_realloc_props(thr, (duk_hobject *) a, 0, size, 0, 0);
23641 a->length = size;
23642 return a;
23644
23646 duk_harray *a;
23647
23649
23650 a = duk_push_harray_with_size(thr, size);
23651 DUK_ASSERT(a != NULL);
23652 return DUK_HOBJECT_A_GET_BASE(thr->heap, (duk_hobject *) a);
23653}
23654
23656 duk_hthread *obj;
23657 duk_idx_t ret;
23658 duk_tval *tv_slot;
23659
23661
23663
23665 DUK_ASSERT(obj != NULL);
23667#if defined(DUK_USE_ROM_STRINGS)
23668 /* Nothing to initialize, strs[] is in ROM. */
23669#else
23670#if defined(DUK_USE_HEAPPTR16)
23671 obj->strs16 = thr->strs16;
23672#else
23673 obj->strs = thr->strs;
23674#endif
23675#endif
23676 DUK_DDD(DUK_DDDPRINT("created thread object with flags: 0x%08lx", (unsigned long) obj->obj.hdr.h_flags));
23677
23678 /* make the new thread reachable */
23679 tv_slot = thr->valstack_top;
23680 DUK_TVAL_SET_OBJECT(tv_slot, (duk_hobject *) obj);
23681 DUK_HTHREAD_INCREF(thr, obj);
23682 ret = (duk_idx_t) (thr->valstack_top - thr->valstack_bottom);
23683 thr->valstack_top++;
23684
23685 /* important to do this *after* pushing, to make the thread reachable for gc */
23686 if (DUK_UNLIKELY(!duk_hthread_init_stacks(thr->heap, obj))) {
23688 DUK_WO_NORETURN(return 0;);
23689 }
23690
23691 /* initialize built-ins - either by copying or creating new ones */
23692 if (flags & DUK_THREAD_NEW_GLOBAL_ENV) {
23694 } else {
23696 }
23698 /* default prototype */
23700
23701 /* Initial stack size satisfies the stack slack constraints so there
23702 * is no need to require stack here.
23703 */
23705
23706 return ret;
23707}
23708
23710 duk_hcompfunc *obj;
23711 duk_tval *tv_slot;
23712
23714
23716
23717 /* Template functions are not strictly constructable (they don't
23718 * have a "prototype" property for instance), so leave the
23719 * DUK_HOBJECT_FLAG_CONSRUCTABLE flag cleared here.
23720 */
23721
23722 obj = duk_hcompfunc_alloc(thr,
23725 if (DUK_UNLIKELY(obj == NULL)) {
23727 DUK_WO_NORETURN(return NULL;);
23728 }
23729
23730 DUK_DDD(DUK_DDDPRINT("created compiled function object with flags: 0x%08lx", (unsigned long) obj->obj.hdr.h_flags));
23731
23732 tv_slot = thr->valstack_top;
23733 DUK_TVAL_SET_OBJECT(tv_slot, (duk_hobject *) obj);
23734 DUK_HOBJECT_INCREF(thr, obj);
23735 thr->valstack_top++;
23736
23737 /* default prototype */
23738 DUK_ASSERT(DUK_HOBJECT_GET_PROTOTYPE(thr->heap, (duk_hobject *) obj) == NULL);
23740
23741 return obj;
23742}
23743
23745 duk_hboundfunc *obj;
23746 duk_tval *tv_slot;
23747
23749
23751 obj = duk_hboundfunc_alloc(thr->heap,
23754 if (!obj) {
23756 DUK_WO_NORETURN(return NULL;);
23757 }
23758
23759 tv_slot = thr->valstack_top++;
23761 DUK_HOBJECT_INCREF(thr, obj);
23762
23763 /* Prototype is left as NULL because the caller always sets it (and
23764 * it depends on the target function).
23765 */
23766 DUK_ASSERT(DUK_HOBJECT_GET_PROTOTYPE(thr->heap, (duk_hobject *) obj) == NULL);
23767
23768 return obj;
23769}
23770
23773 duk_hnatfunc *obj;
23774 duk_idx_t ret;
23775 duk_tval *tv_slot;
23776 duk_int16_t func_nargs;
23777
23779
23781
23782 if (DUK_UNLIKELY(func == NULL)) {
23783 goto api_error;
23784 }
23785 if (nargs >= 0 && nargs < DUK_HNATFUNC_NARGS_MAX) {
23786 func_nargs = (duk_int16_t) nargs;
23787 } else if (nargs == DUK_VARARGS) {
23788 func_nargs = DUK_HNATFUNC_NARGS_VARARGS;
23789 } else {
23790 goto api_error;
23791 }
23792
23793 obj = duk_hnatfunc_alloc(thr, flags);
23794 DUK_ASSERT(obj != NULL);
23795
23796 obj->func = func;
23797 obj->nargs = func_nargs;
23798
23799 DUK_DDD(DUK_DDDPRINT("created native function object with flags: 0x%08lx, nargs=%ld",
23800 (unsigned long) obj->obj.hdr.h_flags,
23801 (long) obj->nargs));
23802
23803 tv_slot = thr->valstack_top;
23804 DUK_TVAL_SET_OBJECT(tv_slot, (duk_hobject *) obj);
23805 DUK_HOBJECT_INCREF(thr, obj);
23807 thr->valstack_top++;
23808
23809 DUK_ASSERT_BIDX_VALID(proto_bidx);
23810 DUK_HOBJECT_SET_PROTOTYPE_INIT_INCREF(thr, (duk_hobject *) obj, thr->builtins[proto_bidx]);
23811 return ret;
23812
23813api_error:
23815 DUK_WO_NORETURN(return 0;);
23816}
23817
23819 duk_uint_t flags;
23820
23822
23826
23827 /* Default prototype is a Duktape specific %NativeFunctionPrototype%
23828 * which provides .length and .name getters.
23829 */
23830 return duk__push_c_function_raw(thr, func, nargs, flags, DUK_BIDX_NATIVE_FUNCTION_PROTOTYPE);
23831}
23832
23835
23837
23841
23842 /* Must use Function.prototype for standard built-in functions. */
23843 (void) duk__push_c_function_raw(thr, func, nargs, flags, DUK_BIDX_FUNCTION_PROTOTYPE);
23844}
23845
23847 duk_uint_t flags;
23850
23854
23855 /* Must use Function.prototype for standard built-in functions. */
23856 (void) duk__push_c_function_raw(thr, func, nargs, flags, DUK_BIDX_FUNCTION_PROTOTYPE);
23857}
23858
23861 duk_small_uint_t lf_flags;
23862 duk_tval *tv_slot;
23863
23865
23867
23868 if (nargs >= DUK_LFUNC_NARGS_MIN && nargs <= DUK_LFUNC_NARGS_MAX) {
23869 /* as is */
23870 } else if (nargs == DUK_VARARGS) {
23872 } else {
23873 goto api_error;
23874 }
23875 if (DUK_UNLIKELY(!(length >= DUK_LFUNC_LENGTH_MIN && length <= DUK_LFUNC_LENGTH_MAX))) {
23876 goto api_error;
23877 }
23878 if (DUK_UNLIKELY(!(magic >= DUK_LFUNC_MAGIC_MIN && magic <= DUK_LFUNC_MAGIC_MAX))) {
23879 goto api_error;
23880 }
23881
23882 lf_flags = DUK_LFUNC_FLAGS_PACK((duk_small_int_t) magic, (duk_small_uint_t) length, (duk_small_uint_t) nargs);
23883 tv_slot = thr->valstack_top++;
23885 DUK_TVAL_SET_LIGHTFUNC(tv_slot, func, lf_flags);
23886 DUK_ASSERT(tv_slot >= thr->valstack_bottom);
23887 return (duk_idx_t) (tv_slot - thr->valstack_bottom);
23888
23889api_error:
23891 DUK_WO_NORETURN(return 0;);
23892}
23893
23894#if defined(DUK_USE_BUFFEROBJECT_SUPPORT)
23896 duk_uint_t hobject_flags_and_class,
23897 duk_small_int_t prototype_bidx) {
23898 duk_hbufobj *obj;
23899 duk_tval *tv_slot;
23900
23902 DUK_ASSERT(prototype_bidx >= 0);
23903
23905
23906 obj = duk_hbufobj_alloc(thr, hobject_flags_and_class);
23907 DUK_ASSERT(obj != NULL);
23908
23909 DUK_HOBJECT_SET_PROTOTYPE_INIT_INCREF(thr, (duk_hobject *) obj, thr->builtins[prototype_bidx]);
23911
23912 tv_slot = thr->valstack_top;
23914 DUK_HOBJECT_INCREF(thr, obj);
23915 thr->valstack_top++;
23917 return obj;
23918}
23919#endif /* DUK_USE_BUFFEROBJECT_SUPPORT */
23920
23921/* XXX: There's quite a bit of overlap with buffer creation handling in
23922 * duk_bi_buffer.c. Look for overlap and refactor.
23923 */
23924#if defined(DUK_USE_BUFFEROBJECT_SUPPORT)
23925#define DUK__PACK_ARGS(classnum, protobidx, elemtype, elemshift, istypedarray) \
23926 (((classnum) << 24) | ((protobidx) << 16) | ((elemtype) << 8) | ((elemshift) << 4) | (istypedarray))
23927
23928static const duk_uint32_t duk__bufobj_flags_lookup[] = {
23929 /* Node.js Buffers are Uint8Array instances which inherit from Buffer.prototype. */
23933 0,
23934 0), /* DUK_BUFOBJ_ARRAYBUFFER */
23938 0,
23939 1), /* DUK_BUFOBJ_NODEJS_BUFFER */
23943 0,
23944 0), /* DUK_BUFOBJ_DATAVIEW */
23948 0,
23949 1), /* DUK_BUFOBJ_INT8ARRAY */
23953 0,
23954 1), /* DUK_BUFOBJ_UINT8ARRAY */
23958 0,
23959 1), /* DUK_BUFOBJ_UINT8CLAMPEDARRAY */
23963 1,
23964 1), /* DUK_BUFOBJ_INT16ARRAY */
23968 1,
23969 1), /* DUK_BUFOBJ_UINT16ARRAY */
23973 2,
23974 1), /* DUK_BUFOBJ_INT32ARRAY */
23978 2,
23979 1), /* DUK_BUFOBJ_UINT32ARRAY */
23983 2,
23984 1), /* DUK_BUFOBJ_FLOAT32ARRAY */
23988 3,
23989 1) /* DUK_BUFOBJ_FLOAT64ARRAY */
23990};
23991#endif /* DUK_USE_BUFFEROBJECT_SUPPORT */
23992
23993#if defined(DUK_USE_BUFFEROBJECT_SUPPORT)
23995 duk_idx_t idx_buffer,
23996 duk_size_t byte_offset,
23997 duk_size_t byte_length,
23998 duk_uint_t flags) {
23999 duk_hbufobj *h_bufobj;
24000 duk_hbuffer *h_val;
24001 duk_hobject *h_arraybuf;
24002 duk_uint32_t tmp;
24003 duk_uint_t classnum;
24004 duk_uint_t protobidx;
24005 duk_uint_t lookupidx;
24006 duk_uint_t uint_offset, uint_length, uint_added;
24007
24009
24010 /* The underlying types for offset/length in duk_hbufobj is
24011 * duk_uint_t; make sure argument values fit.
24012 */
24013 uint_offset = (duk_uint_t) byte_offset;
24014 uint_length = (duk_uint_t) byte_length;
24015 if (sizeof(duk_size_t) != sizeof(duk_uint_t)) {
24016 if (DUK_UNLIKELY((duk_size_t) uint_offset != byte_offset || (duk_size_t) uint_length != byte_length)) {
24017 goto range_error;
24018 }
24019 }
24020
24021 DUK_ASSERT_DISABLE(flags >= 0); /* flags is unsigned */
24022 lookupidx = flags;
24023 if (DUK_UNLIKELY(lookupidx >= sizeof(duk__bufobj_flags_lookup) / sizeof(duk_uint32_t))) {
24024 goto arg_error;
24025 }
24026 tmp = duk__bufobj_flags_lookup[lookupidx];
24027 classnum = tmp >> 24;
24028 protobidx = (tmp >> 16) & 0xff;
24029
24030 h_arraybuf = duk_get_hobject(thr, idx_buffer);
24031 if (h_arraybuf != NULL && /* argument is an object */
24032 flags != DUK_BUFOBJ_ARRAYBUFFER && /* creating a view */
24033 DUK_HOBJECT_GET_CLASS_NUMBER(h_arraybuf) == DUK_HOBJECT_CLASS_ARRAYBUFFER /* argument is ArrayBuffer */) {
24034 duk_uint_t tmp_offset;
24035
24036 DUK_HBUFOBJ_ASSERT_VALID((duk_hbufobj *) h_arraybuf);
24037 h_val = ((duk_hbufobj *) h_arraybuf)->buf;
24038 if (DUK_UNLIKELY(h_val == NULL)) {
24039 goto arg_error;
24040 }
24041
24042 tmp_offset = uint_offset + ((duk_hbufobj *) h_arraybuf)->offset;
24043 if (DUK_UNLIKELY(tmp_offset < uint_offset)) {
24044 goto range_error;
24045 }
24046 uint_offset = tmp_offset;
24047
24048 /* Note intentional difference to new TypedArray(): we allow
24049 * caller to create an uncovered typed array (which is memory
24050 * safe); new TypedArray() rejects it.
24051 */
24052 } else {
24053 /* Handle unexpected object arguments here too, for nice error
24054 * messages.
24055 */
24056 h_arraybuf = NULL;
24057 h_val = duk_require_hbuffer(thr, idx_buffer);
24058 }
24059
24060 /* Wrap check for offset+length. */
24061 uint_added = uint_offset + uint_length;
24062 if (DUK_UNLIKELY(uint_added < uint_offset)) {
24063 goto range_error;
24064 }
24065 DUK_ASSERT(uint_added >= uint_offset && uint_added >= uint_length);
24066
24067 DUK_ASSERT(h_val != NULL);
24068
24069 h_bufobj = duk_push_bufobj_raw(thr,
24071 (duk_small_int_t) protobidx);
24072 DUK_ASSERT(h_bufobj != NULL);
24073
24074 h_bufobj->buf = h_val;
24075 DUK_HBUFFER_INCREF(thr, h_val);
24076 h_bufobj->buf_prop = h_arraybuf;
24077 DUK_HOBJECT_INCREF_ALLOWNULL(thr, h_arraybuf);
24078 h_bufobj->offset = uint_offset;
24079 h_bufobj->length = uint_length;
24080 h_bufobj->shift = (tmp >> 4) & 0x0f;
24081 h_bufobj->elem_type = (tmp >> 8) & 0xff;
24082 h_bufobj->is_typedarray = tmp & 0x0f;
24083 DUK_HBUFOBJ_ASSERT_VALID(h_bufobj);
24084
24085 /* TypedArray views need an automatic ArrayBuffer which must be
24086 * provided as .buffer property of the view. The ArrayBuffer is
24087 * referenced via duk_hbufobj->buf_prop and an inherited .buffer
24088 * accessor returns it. The ArrayBuffer is created lazily on first
24089 * access if necessary so we don't need to do anything more here.
24090 */
24091 return;
24092
24093range_error:
24095 DUK_WO_NORETURN(return;);
24096
24097arg_error:
24099 DUK_WO_NORETURN(return;);
24100}
24101#else /* DUK_USE_BUFFEROBJECT_SUPPORT */
24103 duk_idx_t idx_buffer,
24104 duk_size_t byte_offset,
24105 duk_size_t byte_length,
24106 duk_uint_t flags) {
24108 DUK_UNREF(idx_buffer);
24109 DUK_UNREF(byte_offset);
24110 DUK_UNREF(byte_length);
24111 DUK_UNREF(flags);
24113 DUK_WO_NORETURN(return;);
24114}
24115#endif /* DUK_USE_BUFFEROBJECT_SUPPORT */
24116
24118 duk_errcode_t err_code,
24119 const char *filename,
24121 const char *fmt,
24122 va_list ap) {
24123 duk_hobject *proto;
24124#if defined(DUK_USE_AUGMENT_ERROR_CREATE)
24125 duk_small_uint_t augment_flags;
24126#endif
24127
24129 DUK_ASSERT(thr != NULL);
24130 DUK_UNREF(filename);
24131 DUK_UNREF(line);
24132
24133 /* Error code also packs a tracedata related flag. */
24134#if defined(DUK_USE_AUGMENT_ERROR_CREATE)
24135 augment_flags = 0;
24136 if (err_code & DUK_ERRCODE_FLAG_NOBLAME_FILELINE) {
24137 augment_flags = DUK_AUGMENT_FLAG_NOBLAME_FILELINE;
24138 }
24139#endif
24140 err_code = err_code & (~DUK_ERRCODE_FLAG_NOBLAME_FILELINE);
24141
24142 /* error gets its 'name' from the prototype */
24143 proto = duk_error_prototype_from_code(thr, err_code);
24147 proto);
24148
24149 /* ... and its 'message' from an instance property */
24150 if (fmt) {
24151 duk_push_vsprintf(thr, fmt, ap);
24153 } else {
24154 /* If no explicit message given, put error code into message field
24155 * (as a number). This is not fully in keeping with the ECMAScript
24156 * error model because messages are supposed to be strings (Error
24157 * constructors use ToString() on their argument). However, it's
24158 * probably more useful than having a separate 'code' property.
24159 */
24160 duk_push_int(thr, err_code);
24162 }
24163
24164 /* XXX: .code = err_code disabled, not sure if useful */
24165
24166 /* Creation time error augmentation */
24167#if defined(DUK_USE_AUGMENT_ERROR_CREATE)
24168 /* filename may be NULL in which case file/line is not recorded */
24169 duk_err_augment_error_create(thr, thr, filename, line, augment_flags); /* may throw an error */
24170#endif
24171
24172 return duk_get_top_index_unsafe(thr);
24173}
24174
24176duk_push_error_object_raw(duk_hthread *thr, duk_errcode_t err_code, const char *filename, duk_int_t line, const char *fmt, ...) {
24177 va_list ap;
24178 duk_idx_t ret;
24179
24181
24182 va_start(ap, fmt);
24183 ret = duk_push_error_object_va_raw(thr, err_code, filename, line, fmt, ap);
24184 va_end(ap);
24185 return ret;
24186}
24187
24188#if !defined(DUK_USE_VARIADIC_MACROS)
24189DUK_EXTERNAL duk_idx_t duk_push_error_object_stash(duk_hthread *thr, duk_errcode_t err_code, const char *fmt, ...) {
24190 const char *filename = duk_api_global_filename;
24192 va_list ap;
24193 duk_idx_t ret;
24196
24199 va_start(ap, fmt);
24200 ret = duk_push_error_object_va_raw(thr, err_code, filename, line, fmt, ap);
24201 va_end(ap);
24202 return ret;
24203}
24204#endif /* DUK_USE_VARIADIC_MACROS */
24205
24207 duk_tval *tv_slot;
24208 duk_hbuffer *h;
24209 void *buf_data;
24210
24212
24214
24215 /* Check for maximum buffer length. */
24218 DUK_WO_NORETURN(return NULL;);
24219 }
24220
24221 h = duk_hbuffer_alloc(thr->heap, size, flags, &buf_data);
24222 if (DUK_UNLIKELY(h == NULL)) {
24224 DUK_WO_NORETURN(return NULL;);
24225 }
24226
24227 tv_slot = thr->valstack_top;
24229 DUK_HBUFFER_INCREF(thr, h);
24230 thr->valstack_top++;
24231
24232 return (void *) buf_data;
24233}
24234
24237 return duk_push_buffer_raw(thr, len, DUK_BUF_FLAG_NOZERO);
24238}
24239
24241 void *ptr;
24242
24244
24245 ptr = duk_push_buffer_raw(thr, len, 0);
24246 DUK_ASSERT(ptr != NULL);
24247#if !defined(DUK_USE_ZERO_BUFFER_DATA)
24248 /* ES2015 requires zeroing even when DUK_USE_ZERO_BUFFER_DATA
24249 * is not set.
24250 */
24251 duk_memzero((void *) ptr, (size_t) len);
24252#endif
24253 return ptr;
24254}
24255
24256#if defined(DUK_USE_ES6_PROXY)
24258 duk_hobject *h_target;
24259 duk_hobject *h_handler;
24260 duk_hproxy *h_proxy;
24261 duk_tval *tv_slot;
24262 duk_uint_t flags;
24263
24265 DUK_UNREF(proxy_flags);
24266
24267 /* DUK__CHECK_SPACE() unnecessary because the Proxy is written to
24268 * value stack in-place.
24269 */
24270#if 0
24272#endif
24273
24274 /* Reject a proxy object as the target because it would need
24275 * special handling in property lookups. (ES2015 has no such
24276 * restriction.)
24277 */
24279 DUK_ASSERT(h_target != NULL);
24280 if (DUK_HOBJECT_IS_PROXY(h_target)) {
24281 goto fail_args;
24282 }
24283
24284 /* Reject a proxy object as the handler because it would cause
24285 * potentially unbounded recursion. (ES2015 has no such
24286 * restriction.)
24287 *
24288 * There's little practical reason to use a lightfunc or a plain
24289 * buffer as the handler table: one could only provide traps via
24290 * their prototype objects (Function.prototype and ArrayBuffer.prototype).
24291 * Even so, as lightfuncs and plain buffers mimic their object
24292 * counterparts, they're promoted and accepted here.
24293 */
24295 DUK_ASSERT(h_handler != NULL);
24296 if (DUK_HOBJECT_IS_PROXY(h_handler)) {
24297 goto fail_args;
24298 }
24299
24300 /* XXX: Proxy object currently has no prototype, so ToPrimitive()
24301 * coercion fails which is a bit confusing.
24302 */
24303
24304 /* CALLABLE and CONSTRUCTABLE flags are copied from the (initial)
24305 * target, see ES2015 Sections 9.5.15 and 9.5.13.
24306 */
24309 if (flags & DUK_HOBJECT_FLAG_CALLABLE) {
24311 } else {
24313 }
24314
24315 h_proxy = duk_hproxy_alloc(thr, flags);
24316 DUK_ASSERT(h_proxy != NULL);
24317 DUK_ASSERT(DUK_HOBJECT_GET_PROTOTYPE(thr->heap, (duk_hobject *) h_proxy) == NULL);
24318
24319 /* Initialize Proxy target and handler references; avoid INCREF
24320 * by stealing the value stack refcounts via direct value stack
24321 * manipulation. INCREF is needed for the Proxy itself however.
24322 */
24323 DUK_ASSERT(h_target != NULL);
24324 h_proxy->target = h_target;
24325 DUK_ASSERT(h_handler != NULL);
24326 h_proxy->handler = h_handler;
24327 DUK_HPROXY_ASSERT_VALID(h_proxy);
24328
24329 DUK_ASSERT(duk_get_hobject(thr, -2) == h_target);
24330 DUK_ASSERT(duk_get_hobject(thr, -1) == h_handler);
24331 tv_slot = thr->valstack_top - 2;
24332 DUK_ASSERT(tv_slot >= thr->valstack_bottom);
24333 DUK_TVAL_SET_OBJECT(tv_slot, (duk_hobject *) h_proxy);
24334 DUK_HOBJECT_INCREF(thr, (duk_hobject *) h_proxy);
24335 tv_slot++;
24336 DUK_TVAL_SET_UNDEFINED(tv_slot); /* [ ... target handler ] -> [ ... proxy undefined ] */
24337 thr->valstack_top = tv_slot; /* -> [ ... proxy ] */
24338
24339 DUK_DD(DUK_DDPRINT("created Proxy: %!iT", duk_get_tval(thr, -1)));
24340
24341 return (duk_idx_t) (thr->valstack_top - thr->valstack_bottom - 1);
24342
24343fail_args:
24345 DUK_WO_NORETURN(return 0;);
24346}
24347#else /* DUK_USE_ES6_PROXY */
24350 DUK_UNREF(proxy_flags);
24352 DUK_WO_NORETURN(return 0;);
24353}
24354#endif /* DUK_USE_ES6_PROXY */
24355
24356#if defined(DUK_USE_ASSERTIONS)
24357DUK_LOCAL void duk__validate_push_heapptr(duk_hthread *thr, void *ptr) {
24358 duk_heaphdr *h;
24359 duk_heaphdr *curr;
24360 duk_bool_t found = 0;
24361
24362 h = (duk_heaphdr *) ptr;
24363 if (h == NULL) {
24364 /* Allowed. */
24365 return;
24366 }
24367 DUK_ASSERT(h != NULL);
24369
24370 /* One particular problem case is where an object has been
24371 * queued for finalization but the finalizer hasn't yet been
24372 * executed.
24373 *
24374 * Corner case: we're running in a finalizer for object X, and
24375 * user code calls duk_push_heapptr() for X itself. In this
24376 * case X will be in finalize_list, and we can detect the case
24377 * by seeing that X's FINALIZED flag is set (which is done before
24378 * the finalizer starts executing).
24379 */
24380#if defined(DUK_USE_FINALIZER_SUPPORT)
24381 for (curr = thr->heap->finalize_list; curr != NULL; curr = DUK_HEAPHDR_GET_NEXT(thr->heap, curr)) {
24382 /* FINALIZABLE is set for all objects on finalize_list
24383 * except for an object being finalized right now. So
24384 * can't assert here.
24385 */
24386#if 0
24388#endif
24389
24390 if (curr == h) {
24392 /* Object is currently being finalized. */
24393 DUK_ASSERT(found == 0); /* Would indicate corrupted lists. */
24394 found = 1;
24395 } else {
24396 /* Not being finalized but on finalize_list,
24397 * allowed since Duktape 2.1.
24398 */
24399 DUK_ASSERT(found == 0); /* Would indicate corrupted lists. */
24400 found = 1;
24401 }
24402 }
24403 }
24404#endif /* DUK_USE_FINALIZER_SUPPORT */
24405
24406#if defined(DUK_USE_REFERENCE_COUNTING)
24407 /* Because refzero_list is now processed to completion inline with
24408 * no side effects, it's always empty here.
24409 */
24410 DUK_ASSERT(thr->heap->refzero_list == NULL);
24411#endif
24412
24413 /* If not present in finalize_list (or refzero_list), it
24414 * must be either in heap_allocated or the string table.
24415 */
24416 if (DUK_HEAPHDR_IS_STRING(h)) {
24417 duk_uint32_t i;
24418 duk_hstring *str;
24419 duk_heap *heap = thr->heap;
24420
24421 DUK_ASSERT(found == 0);
24422 for (i = 0; i < heap->st_size; i++) {
24423#if defined(DUK_USE_STRTAB_PTRCOMP)
24424 str = DUK_USE_HEAPPTR_DEC16((heap)->heap_udata, heap->strtable16[i]);
24425#else
24426 str = heap->strtable[i];
24427#endif
24428 while (str != NULL) {
24429 if (str == (duk_hstring *) h) {
24430 DUK_ASSERT(found == 0); /* Would indicate corrupted lists. */
24431 found = 1;
24432 break;
24433 }
24434 str = str->hdr.h_next;
24435 }
24436 }
24437 DUK_ASSERT(found != 0);
24438 } else {
24439 for (curr = thr->heap->heap_allocated; curr != NULL; curr = DUK_HEAPHDR_GET_NEXT(thr->heap, curr)) {
24440 if (curr == h) {
24441 DUK_ASSERT(found == 0); /* Would indicate corrupted lists. */
24442 found = 1;
24443 }
24444 }
24445 DUK_ASSERT(found != 0);
24446 }
24447}
24448#endif /* DUK_USE_ASSERTIONS */
24449
24451 duk_idx_t ret;
24452 duk_tval *tv;
24453
24455
24456 /* Reviving an object using a heap pointer is a dangerous API
24457 * operation: if the application doesn't guarantee that the
24458 * pointer target is always reachable, difficult-to-diagnose
24459 * problems may ensue. Try to validate the 'ptr' argument to
24460 * the extent possible.
24461 */
24462
24463#if defined(DUK_USE_ASSERTIONS)
24464 duk__validate_push_heapptr(thr, ptr);
24465#endif
24466
24468
24469 ret = (duk_idx_t) (thr->valstack_top - thr->valstack_bottom);
24470 tv = thr->valstack_top++;
24471
24472 if (ptr == NULL) {
24474 return ret;
24475 }
24476
24478
24479 /* If the argument is on finalize_list it has technically been
24480 * unreachable before duk_push_heapptr() but it's still safe to
24481 * push it. Starting from Duktape 2.1 allow application code to
24482 * do so. There are two main cases:
24483 *
24484 * (1) The object is on the finalize_list and we're called by
24485 * the finalizer for the object being finalized. In this
24486 * case do nothing: finalize_list handling will deal with
24487 * the object queueing. This is detected by the object not
24488 * having a FINALIZABLE flag despite being on the finalize_list;
24489 * the flag is cleared for the object being finalized only.
24490 *
24491 * (2) The object is on the finalize_list but is not currently
24492 * being processed. In this case the object can be queued
24493 * back to heap_allocated with a few flags cleared, in effect
24494 * cancelling the finalizer.
24495 */
24497 duk_heaphdr *curr;
24498
24499 DUK_D(DUK_DPRINT("duk_push_heapptr() with a pointer on finalize_list, autorescue"));
24500
24501 curr = (duk_heaphdr *) ptr;
24503
24504 /* Because FINALIZED is set prior to finalizer call, it will
24505 * be set for the object being currently finalized, but not
24506 * for other objects on finalize_list.
24507 */
24509
24510 /* Dequeue object from finalize_list and queue it back to
24511 * heap_allocated.
24512 */
24513#if defined(DUK_USE_REFERENCE_COUNTING)
24514 DUK_ASSERT(DUK_HEAPHDR_GET_REFCOUNT(curr) >= 1); /* Preincremented on finalize_list insert. */
24516#endif
24519
24520 /* Continue with the rest. */
24521 }
24522
24523 switch (DUK_HEAPHDR_GET_TYPE((duk_heaphdr *) ptr)) {
24524 case DUK_HTYPE_STRING:
24525 DUK_TVAL_SET_STRING(tv, (duk_hstring *) ptr);
24526 break;
24527 case DUK_HTYPE_OBJECT:
24528 DUK_TVAL_SET_OBJECT(tv, (duk_hobject *) ptr);
24529 break;
24530 default:
24532 DUK_TVAL_SET_BUFFER(tv, (duk_hbuffer *) ptr);
24533 break;
24534 }
24535
24536 DUK_HEAPHDR_INCREF(thr, (duk_heaphdr *) ptr);
24537
24538 return ret;
24539}
24541/* Push object with no prototype, i.e. a "bare" object. */
24544
24545 (void) duk_push_object_helper(thr,
24548 -1); /* no prototype */
24549 return duk_get_top_index_unsafe(thr);
24551
24553 duk_tval tv;
24554
24556 DUK_ASSERT(h != NULL);
24557
24558 DUK_TVAL_SET_STRING(&tv, h);
24559 duk_push_tval(thr, &tv);
24560}
24565 duk_push_hstring(thr, DUK_HTHREAD_GET_STRING(thr, stridx));
24566}
24567
24572
24574 duk_tval tv;
24575
24577 DUK_ASSERT(h != NULL);
24578
24579 DUK_TVAL_SET_OBJECT(&tv, h);
24580 duk_push_tval(thr, &tv);
24582
24584 duk_tval tv;
24585
24587 DUK_ASSERT(h != NULL);
24588
24589 DUK_TVAL_SET_BUFFER(&tv, h);
24590 duk_push_tval(thr, &tv);
24591}
24592
24595 DUK_ASSERT(builtin_idx >= 0 && builtin_idx < DUK_NUM_BUILTINS);
24596 DUK_ASSERT(thr->builtins[builtin_idx] != NULL);
24597
24598 duk_push_hobject(thr, thr->builtins[builtin_idx]);
24599}
24600
24601/*
24602 * Poppers
24603 */
24604
24606 duk_tval *tv;
24607#if defined(DUK_USE_REFERENCE_COUNTING)
24608 duk_tval *tv_end;
24609#endif
24610
24612 DUK_ASSERT(count >= 0);
24614
24615#if defined(DUK_USE_REFERENCE_COUNTING)
24616 tv = thr->valstack_top;
24617 tv_end = tv - count;
24618 while (tv != tv_end) {
24619 tv--;
24620 DUK_ASSERT(tv >= thr->valstack_bottom);
24622 }
24623 thr->valstack_top = tv;
24625#else
24626 tv = thr->valstack_top;
24627 while (count > 0) {
24628 count--;
24629 tv--;
24630 DUK_ASSERT(tv >= thr->valstack_bottom);
24632 }
24633 thr->valstack_top = tv;
24634#endif
24635
24637}
24638
24642
24645 DUK_WO_NORETURN(return;);
24647 DUK_ASSERT(count >= 0);
24648
24650}
24651
24652#if defined(DUK_USE_PREFER_SIZE)
24655 duk_pop_n(thr, count);
24656}
24657#else /* DUK_USE_PREFER_SIZE */
24661}
24662#endif /* DUK_USE_PREFER_SIZE */
24663
24664/* Pop N elements without DECREF (in effect "stealing" any actual refcounts). */
24665#if defined(DUK_USE_REFERENCE_COUNTING)
24667 duk_tval *tv;
24668
24670 DUK_ASSERT(count >= 0);
24673
24674 tv = thr->valstack_top;
24675 while (count > 0) {
24676 count--;
24677 tv--;
24678 DUK_ASSERT(tv >= thr->valstack_bottom);
24680 }
24681 thr->valstack_top = tv;
24682
24684}
24685#else /* DUK_USE_REFERENCE_COUNTING */
24688 duk_pop_n_unsafe(thr, count);
24689}
24690#endif /* DUK_USE_REFERENCE_COUNTING */
24691
24692/* Popping one element is called so often that when footprint is not an issue,
24693 * compile a specialized function for it.
24694 */
24695#if defined(DUK_USE_PREFER_SIZE)
24696DUK_EXTERNAL void duk_pop(duk_hthread *thr) {
24698 duk_pop_n(thr, 1);
24699}
24702 duk_pop_n_unsafe(thr, 1);
24703}
24707}
24708#else /* DUK_USE_PREFER_SIZE */
24710 duk_tval *tv;
24711
24716
24717 tv = --thr->valstack_top;
24718 DUK_ASSERT(tv >= thr->valstack_bottom);
24719#if defined(DUK_USE_REFERENCE_COUNTING)
24720 DUK_TVAL_SET_UNDEFINED_UPDREF(thr, tv); /* side effects */
24721#else
24723#endif
24724
24727DUK_EXTERNAL void duk_pop(duk_hthread *thr) {
24729
24731 if (DUK_UNLIKELY(thr->valstack_top == thr->valstack_bottom)) {
24733 DUK_WO_NORETURN(return;);
24734 }
24735
24737}
24741}
24743 duk_tval *tv;
24744
24749
24750 tv = --thr->valstack_top;
24751 DUK_ASSERT(tv >= thr->valstack_bottom);
24753
24755}
24756#endif /* !DUK_USE_PREFER_SIZE */
24757
24758#if defined(DUK_USE_PREFER_SIZE)
24762}
24763#else /* DUK_USE_PREFER_SIZE */
24769
24771 thr->valstack_top--;
24772
24774}
24775#endif /* !DUK_USE_PREFER_SIZE */
24776
24777#if defined(DUK_USE_PREFER_SIZE)
24780 duk_pop_n(thr, 2);
24781}
24784 duk_pop_n_unsafe(thr, 2);
24785}
24789}
24790#else
24792 duk_tval *tv;
24793
24798
24799 tv = --thr->valstack_top;
24800 DUK_ASSERT(tv >= thr->valstack_bottom);
24801#if defined(DUK_USE_REFERENCE_COUNTING)
24802 DUK_TVAL_SET_UNDEFINED_UPDREF(thr, tv); /* side effects */
24803#else
24805#endif
24806 tv = --thr->valstack_top;
24807 DUK_ASSERT(tv >= thr->valstack_bottom);
24808#if defined(DUK_USE_REFERENCE_COUNTING)
24809 DUK_TVAL_SET_UNDEFINED_UPDREF(thr, tv); /* side effects */
24810#else
24812#endif
24813
24818
24820 if (DUK_UNLIKELY(thr->valstack_top - 2 < thr->valstack_bottom)) {
24822 DUK_WO_NORETURN(return;);
24823 }
24824
24826}
24830}
24836
24839 thr->valstack_top -= 2;
24840
24842}
24843#endif /* !DUK_USE_PREFER_SIZE */
24844
24847 duk_pop_n(thr, 3);
24848}
24849
24852 duk_pop_n_unsafe(thr, 3);
24853}
24858}
24859
24860/*
24861 * Pack and unpack (pack value stack entries into an array and vice versa)
24862 */
24863
24864/* XXX: pack index range? array index offset? */
24865/* XXX: need ability to pack into a bare array? */
24867 duk_tval *tv_src;
24868 duk_tval *tv_dst;
24869 duk_tval *tv_curr;
24870 duk_tval *tv_limit;
24871 duk_idx_t top;
24872
24874
24876 top = (duk_idx_t) (thr->valstack_top - thr->valstack_bottom);
24877 DUK_ASSERT(top >= 0);
24878 if (DUK_UNLIKELY((duk_uidx_t) count > (duk_uidx_t) top)) {
24879 /* Also handles negative count. */
24881 DUK_WO_NORETURN(return;);
24882 }
24883 DUK_ASSERT(count >= 0);
24884
24885 /* Wrapping is controlled by the check above: value stack top can be
24886 * at most DUK_USE_VALSTACK_LIMIT which is low enough so that
24887 * multiplying with sizeof(duk_tval) won't wrap.
24888 */
24890 DUK_ASSERT((duk_size_t) count <= DUK_SIZE_MAX / sizeof(duk_tval)); /* no wrapping */
24891
24892 tv_dst = duk_push_harray_with_size_outptr(thr, (duk_uint32_t) count); /* XXX: uninitialized would be OK */
24893 DUK_ASSERT(count == 0 || tv_dst != NULL);
24894 DUK_ASSERT(!duk_is_bare_object(thr, -1));
24895
24896 /* Copy value stack values directly to the array part without
24897 * any refcount updates: net refcount changes are zero.
24898 */
24899 tv_src = thr->valstack_top - count - 1;
24900 duk_memcpy_unsafe((void *) tv_dst, (const void *) tv_src, (size_t) count * sizeof(duk_tval));
24901
24902 /* Overwrite result array to final value stack location and wipe
24903 * the rest; no refcount operations needed.
24904 */
24905
24906 tv_dst = tv_src; /* when count == 0, same as tv_src (OK) */
24907 tv_src = thr->valstack_top - 1;
24908 DUK_TVAL_SET_TVAL(tv_dst, tv_src);
24910 /* XXX: internal helper to wipe a value stack segment? */
24911 tv_curr = tv_dst + 1;
24912 tv_limit = thr->valstack_top;
24913 while (tv_curr != tv_limit) {
24914 /* Wipe policy: keep as 'undefined'. */
24915 DUK_TVAL_SET_UNDEFINED(tv_curr);
24916 tv_curr++;
24917 }
24918 thr->valstack_top = tv_dst + 1;
24919}
24920
24922 duk_tval *tv;
24923
24925
24926 tv = duk_require_tval(thr, idx);
24927 if (DUK_LIKELY(DUK_TVAL_IS_OBJECT(tv))) {
24928 duk_hobject *h;
24929 duk_uint32_t len;
24930 duk_uint32_t i;
24931
24932 h = DUK_TVAL_GET_OBJECT(tv);
24933 DUK_ASSERT(h != NULL);
24934 DUK_UNREF(h);
24935
24936#if defined(DUK_USE_ARRAY_FASTPATH) /* close enough */
24937 if (DUK_LIKELY(DUK_HOBJECT_IS_ARRAY(h) && ((duk_harray *) h)->length <= DUK_HOBJECT_GET_ASIZE(h))) {
24938 duk_harray *h_arr;
24939 duk_tval *tv_src;
24940 duk_tval *tv_dst;
24941
24942 h_arr = (duk_harray *) h;
24943 len = h_arr->length;
24944 if (DUK_UNLIKELY(len >= 0x80000000UL)) {
24945 goto fail_over_2g;
24946 }
24947 duk_require_stack(thr, (duk_idx_t) len);
24948
24949 /* The potential allocation in duk_require_stack() may
24950 * run a finalizer which modifies the argArray so that
24951 * e.g. becomes sparse. So, we need to recheck that the
24952 * array didn't change size and that there's still a
24953 * valid backing array part.
24954 *
24955 * XXX: alternatively, could prevent finalizers for the
24956 * duration.
24957 */
24958 if (DUK_UNLIKELY(len != h_arr->length || h_arr->length > DUK_HOBJECT_GET_ASIZE((duk_hobject *) h_arr))) {
24959 goto skip_fast;
24960 }
24961
24962 /* Main fast path: arguments array is almost always
24963 * an actual array (though it might also be an arguments
24964 * object).
24965 */
24966
24967 DUK_DDD(DUK_DDDPRINT("fast path for %ld elements", (long) h_arr->length));
24968 tv_src = DUK_HOBJECT_A_GET_BASE(thr->heap, h);
24969 tv_dst = thr->valstack_top;
24970 while (len-- > 0) {
24971 DUK_ASSERT(tv_dst < thr->valstack_end);
24972 if (DUK_UNLIKELY(DUK_TVAL_IS_UNUSED(tv_src))) {
24973 /* Gaps are very unlikely. Skip over them,
24974 * without an ancestor lookup (technically
24975 * not compliant).
24976 */
24977 DUK_ASSERT(DUK_TVAL_IS_UNDEFINED(tv_dst)); /* valstack policy */
24978 } else {
24979 DUK_TVAL_SET_TVAL(tv_dst, tv_src);
24980 DUK_TVAL_INCREF(thr, tv_dst);
24981 }
24982 tv_src++;
24983 tv_dst++;
24984 }
24985 DUK_ASSERT(tv_dst <= thr->valstack_end);
24986 thr->valstack_top = tv_dst;
24987 return (duk_idx_t) h_arr->length;
24988 }
24989 skip_fast:
24990#endif /* DUK_USE_ARRAY_FASTPATH */
24991
24992 /* Slow path: actual lookups. The initial 'length' lookup
24993 * decides the output length, regardless of side effects that
24994 * may resize or change the argArray while we read the
24995 * indices.
24996 */
24997 idx = duk_normalize_index(thr, idx);
24999 len = duk_to_uint32(thr, -1); /* ToUint32() coercion required */
25000 if (DUK_UNLIKELY(len >= 0x80000000UL)) {
25001 goto fail_over_2g;
25002 }
25003 duk_pop_unsafe(thr);
25004 DUK_DDD(DUK_DDDPRINT("slow path for %ld elements", (long) len));
25005
25006 duk_require_stack(thr, (duk_idx_t) len);
25007 for (i = 0; i < len; i++) {
25008 duk_get_prop_index(thr, idx, (duk_uarridx_t) i);
25009 }
25010 return (duk_idx_t) len;
25011 } else if (DUK_TVAL_IS_UNDEFINED(tv) || DUK_TVAL_IS_NULL(tv)) {
25012 return 0;
25013 }
25014
25016 DUK_WO_NORETURN(return 0;);
25017
25018fail_over_2g:
25020 DUK_WO_NORETURN(return 0;);
25021}
25023/*
25024 * Error throwing
25025 */
25026
25027#if defined(DUK_USE_GCC_PRAGMAS)
25028#pragma GCC diagnostic push
25029#pragma GCC diagnostic ignored "-Wsuggest-attribute=noreturn"
25030#elif defined(DUK_USE_CLANG_PRAGMAS)
25031#pragma clang diagnostic push
25032#endif
25033
25035 duk_tval *tv_val;
25036
25038 DUK_ASSERT(thr->valstack_bottom >= thr->valstack);
25040 DUK_ASSERT(thr->valstack_end >= thr->valstack_top);
25041
25042 if (DUK_UNLIKELY(thr->valstack_top == thr->valstack_bottom)) {
25044 DUK_WO_NORETURN(return;);
25045 }
25046
25047 /* Errors are augmented when they are created, not when they are
25048 * thrown or re-thrown. The current error handler, however, runs
25049 * just before an error is thrown.
25050 */
25051
25052 /* Sync so that augmentation sees up-to-date activations, NULL
25053 * thr->ptr_curr_pc so that it's not used if side effects occur
25054 * in augmentation or longjmp handling.
25055 */
25057
25058#if defined(DUK_USE_AUGMENT_ERROR_THROW)
25059 DUK_DDD(DUK_DDDPRINT("THROW ERROR (API): %!dT (before throw augment)", (duk_tval *) duk_get_tval(thr, -1)));
25061#endif
25062 DUK_DDD(DUK_DDDPRINT("THROW ERROR (API): %!dT (after throw augment)", (duk_tval *) duk_get_tval(thr, -1)));
25063
25064 tv_val = DUK_GET_TVAL_NEGIDX(thr, -1);
25066#if defined(DUK_USE_DEBUGGER_SUPPORT)
25067 duk_err_check_debugger_integration(thr);
25068#endif
25069
25070 /* thr->heap->lj.jmpbuf_ptr is checked by duk_err_longjmp() so we don't
25071 * need to check that here. If the value is NULL, a fatal error occurs
25072 * because we can't return.
25073 */
25074
25075 duk_err_longjmp(thr);
25077}
25078
25079DUK_EXTERNAL void duk_fatal_raw(duk_hthread *thr, const char *err_msg) {
25081 DUK_ASSERT(thr != NULL);
25082 DUK_ASSERT(thr->heap != NULL);
25083 DUK_ASSERT(thr->heap->fatal_func != NULL);
25084
25085 DUK_D(DUK_DPRINT("fatal error occurred: %s", err_msg ? err_msg : "NULL"));
25086
25087 /* fatal_func should be noreturn, but noreturn declarations on function
25088 * pointers has a very spotty support apparently so it's not currently
25089 * done.
25090 */
25091 thr->heap->fatal_func(thr->heap->heap_udata, err_msg);
25092
25093 /* If the fatal handler returns, all bets are off. It'd be nice to
25094 * print something here but since we don't want to depend on stdio,
25095 * there's no way to do so portably.
25096 */
25097 DUK_D(DUK_DPRINT("fatal error handler returned, all bets are off!"));
25098 for (;;) {
25099 /* loop forever, don't return (function marked noreturn) */
25100 }
25101}
25102
25105 const char *filename,
25107 const char *fmt,
25108 va_list ap) {
25110
25111 duk_push_error_object_va_raw(thr, err_code, filename, line, fmt, ap);
25112 (void) duk_throw(thr);
25113 DUK_WO_NORETURN(return;);
25114}
25115
25117 duk_errcode_t err_code,
25118 const char *filename,
25120 const char *fmt,
25121 ...) {
25122 va_list ap;
25123
25125
25126 va_start(ap, fmt);
25127 duk_push_error_object_va_raw(thr, err_code, filename, line, fmt, ap);
25128 va_end(ap);
25129 (void) duk_throw(thr);
25130 DUK_WO_NORETURN(return;);
25132
25133#if defined(DUK_USE_GCC_PRAGMAS)
25134#pragma GCC diagnostic pop
25135#elif defined(DUK_USE_CLANG_PRAGMAS)
25136#pragma clang diagnostic pop
25137#endif
25138
25139#if !defined(DUK_USE_VARIADIC_MACROS)
25141 DUK_LOCAL_DECL void duk__throw_error_from_stash(duk_hthread *thr, duk_errcode_t err_code, const char *fmt, va_list ap));
25142
25143DUK_LOCAL void duk__throw_error_from_stash(duk_hthread *thr, duk_errcode_t err_code, const char *fmt, va_list ap) {
25144 const char *filename;
25146
25148
25149 filename = duk_api_global_filename;
25153
25154 duk_push_error_object_va_raw(thr, err_code, filename, line, fmt, ap);
25155 (void) duk_throw(thr);
25157}
25158
25159#define DUK__ERROR_STASH_SHARED(code) \
25160 do { \
25161 va_list ap; \
25162 va_start(ap, fmt); \
25163 duk__throw_error_from_stash(thr, (code), fmt, ap); \
25164 va_end(ap); \
25165 DUK_WO_NORETURN(return 0;); \
25166 } while (0)
25167
25168DUK_EXTERNAL duk_ret_t duk_error_stash(duk_hthread *thr, duk_errcode_t err_code, const char *fmt, ...) {
25170 DUK__ERROR_STASH_SHARED(err_code);
25171}
25175}
25179}
25183}
25187}
25188DUK_EXTERNAL duk_ret_t duk_syntax_error_stash(duk_hthread *thr, const char *fmt, ...) {
25191}
25192DUK_EXTERNAL duk_ret_t duk_type_error_stash(duk_hthread *thr, const char *fmt, ...) {
25195}
25196DUK_EXTERNAL duk_ret_t duk_uri_error_stash(duk_hthread *thr, const char *fmt, ...) {
25199}
25200#endif /* DUK_USE_VARIADIC_MACROS */
25201
25202/*
25203 * Comparison
25204 */
25205
25207 duk_tval *tv1, *tv2;
25208
25210
25211 tv1 = duk_get_tval(thr, idx1);
25212 tv2 = duk_get_tval(thr, idx2);
25213 if ((tv1 == NULL) || (tv2 == NULL)) {
25214 return 0;
25215 }
25216
25217 /* Coercion may be needed, the helper handles that by pushing the
25218 * tagged values to the stack.
25219 */
25220 return duk_js_equals(thr, tv1, tv2);
25221}
25222
25224 duk_tval *tv1, *tv2;
25225
25227
25228 tv1 = duk_get_tval(thr, idx1);
25229 tv2 = duk_get_tval(thr, idx2);
25230 if ((tv1 == NULL) || (tv2 == NULL)) {
25231 return 0;
25232 }
25233
25234 /* No coercions or other side effects, so safe */
25235 return duk_js_strict_equals(tv1, tv2);
25236}
25237
25239 duk_tval *tv1, *tv2;
25240
25242
25243 tv1 = duk_get_tval(thr, idx1);
25244 tv2 = duk_get_tval(thr, idx2);
25245 if ((tv1 == NULL) || (tv2 == NULL)) {
25246 return 0;
25247 }
25248
25249 /* No coercions or other side effects, so safe */
25250 return duk_js_samevalue(tv1, tv2);
25251}
25252
25253/*
25254 * instanceof
25255 */
25256
25258 duk_tval *tv1, *tv2;
25259
25261
25262 /* Index validation is strict, which differs from duk_equals().
25263 * The strict behavior mimics how instanceof itself works, e.g.
25264 * it is a TypeError if rval is not a -callable- object. It would
25265 * be somewhat inconsistent if rval would be allowed to be
25266 * non-existent without a TypeError.
25267 */
25268 tv1 = duk_require_tval(thr, idx1);
25269 DUK_ASSERT(tv1 != NULL);
25270 tv2 = duk_require_tval(thr, idx2);
25271 DUK_ASSERT(tv2 != NULL);
25272
25273 return duk_js_instanceof(thr, tv1, tv2);
25274}
25275
25276/*
25277 * Lightfunc
25278 */
25279
25281 /* Lightfunc name, includes Duktape/C native function pointer, which
25282 * can often be used to locate the function from a symbol table.
25283 * The name also includes the 16-bit duk_tval flags field because it
25284 * includes the magic value. Because a single native function often
25285 * provides different functionality depending on the magic value, it
25286 * seems reasonably to include it in the name.
25287 *
25288 * On the other hand, a complicated name increases string table
25289 * pressure in low memory environments (but only when function name
25290 * is accessed).
25291 */
25292
25294
25295 duk_push_literal(thr, "light_");
25296 duk_push_string_funcptr(thr, (duk_uint8_t *) &func, sizeof(func));
25297 duk_push_sprintf(thr, "_%04x", (unsigned int) lf_flags);
25298 duk_concat(thr, 3);
25299}
25302 duk_c_function func;
25303 duk_small_uint_t lf_flags;
25304
25307
25308 DUK_TVAL_GET_LIGHTFUNC(tv, func, lf_flags);
25309 duk_push_lightfunc_name_raw(thr, func, lf_flags);
25310}
25311
25313 duk_c_function func;
25314 duk_small_uint_t lf_flags;
25315
25318
25319 DUK_TVAL_GET_LIGHTFUNC(tv, func, lf_flags); /* read before 'tv' potentially invalidated */
25320 duk_push_literal(thr, "function ");
25321 duk_push_lightfunc_name_raw(thr, func, lf_flags);
25322 duk_push_literal(thr, "() { [lightfunc code] }");
25323 duk_concat(thr, 3);
25324}
25325
25326/*
25327 * Function pointers
25328 *
25329 * Printing function pointers is non-portable, so we do that by hex printing
25330 * bytes from memory.
25331 */
25332
25333DUK_INTERNAL void duk_push_string_funcptr(duk_hthread *thr, duk_uint8_t *ptr, duk_size_t sz) {
25334 duk_uint8_t buf[32 * 2];
25335 duk_uint8_t *p, *q;
25338
25340 DUK_ASSERT(sz <= 32); /* sanity limit for function pointer size */
25341
25342 p = buf;
25343#if defined(DUK_USE_INTEGER_LE)
25344 q = ptr + sz;
25345#else
25346 q = ptr;
25347#endif
25348 for (i = 0; i < sz; i++) {
25349#if defined(DUK_USE_INTEGER_LE)
25350 t = *(--q);
25351#else
25352 t = *(q++);
25353#endif
25354 *p++ = duk_lc_digits[t >> 4];
25355 *p++ = duk_lc_digits[t & 0x0f];
25356 }
25358 duk_push_lstring(thr, (const char *) buf, sz * 2);
25360
25361/*
25362 * Push readable string summarizing duk_tval. The operation is side effect
25363 * free and will only throw from internal errors (e.g. out of memory).
25364 * This is used by e.g. property access code to summarize a key/base safely,
25365 * and is not intended to be fast (but small and safe).
25367
25368/* String limits for summary strings. */
25369#define DUK__READABLE_SUMMARY_MAXCHARS 96 /* maximum supported by helper */
25370#define DUK__READABLE_STRING_MAXCHARS 32 /* for strings/symbols */
25371#define DUK__READABLE_ERRMSG_MAXCHARS 96 /* for error messages */
25372
25373/* String sanitizer which escapes ASCII control characters and a few other
25374 * ASCII characters, passes Unicode as is, and replaces invalid UTF-8 with
25375 * question marks. No errors are thrown for any input string, except in out
25376 * of memory situations.
25377 */
25379 const duk_uint8_t *p, *p_start, *p_end;
25380 duk_uint8_t buf[DUK_UNICODE_MAX_XUTF8_LENGTH * DUK__READABLE_SUMMARY_MAXCHARS + 2 /*quotes*/ + 3 /*periods*/];
25381 duk_uint8_t *q;
25383 duk_small_uint_t nchars;
25384
25386 DUK_ASSERT(h_input != NULL);
25388
25389 p_start = (const duk_uint8_t *) DUK_HSTRING_GET_DATA(h_input);
25390 p_end = p_start + DUK_HSTRING_GET_BYTELEN(h_input);
25391 p = p_start;
25392 q = buf;
25393
25394 nchars = 0;
25395 *q++ = (duk_uint8_t) DUK_ASC_SINGLEQUOTE;
25396 for (;;) {
25397 if (p >= p_end) {
25398 break;
25399 }
25400 if (nchars == maxchars) {
25401 *q++ = (duk_uint8_t) DUK_ASC_PERIOD;
25402 *q++ = (duk_uint8_t) DUK_ASC_PERIOD;
25403 *q++ = (duk_uint8_t) DUK_ASC_PERIOD;
25404 break;
25405 }
25406 if (duk_unicode_decode_xutf8(thr, &p, p_start, p_end, &cp)) {
25407 if (cp < 0x20 || cp == 0x7f || cp == DUK_ASC_SINGLEQUOTE || cp == DUK_ASC_BACKSLASH) {
25408 DUK_ASSERT(DUK_UNICODE_MAX_XUTF8_LENGTH >= 4); /* estimate is valid */
25409 DUK_ASSERT((cp >> 4) <= 0x0f);
25410 *q++ = (duk_uint8_t) DUK_ASC_BACKSLASH;
25411 *q++ = (duk_uint8_t) DUK_ASC_LC_X;
25412 *q++ = (duk_uint8_t) duk_lc_digits[cp >> 4];
25413 *q++ = (duk_uint8_t) duk_lc_digits[cp & 0x0f];
25414 } else {
25415 q += duk_unicode_encode_xutf8(cp, q);
25417 } else {
25418 p++; /* advance manually */
25419 *q++ = (duk_uint8_t) DUK_ASC_QUESTION;
25420 }
25421 nchars++;
25422 }
25423 *q++ = (duk_uint8_t) DUK_ASC_SINGLEQUOTE;
25424
25425 duk_push_lstring(thr, (const char *) buf, (duk_size_t) (q - buf));
25426}
25427
25428DUK_LOCAL const char *duk__push_string_tval_readable(duk_hthread *thr, duk_tval *tv, duk_bool_t error_aware) {
25430 /* 'tv' may be NULL */
25431
25432 if (tv == NULL) {
25433 duk_push_literal(thr, "none");
25434 } else {
25435 switch (DUK_TVAL_GET_TAG(tv)) {
25436 case DUK_TAG_STRING: {
25438 if (DUK_HSTRING_HAS_SYMBOL(h)) {
25439 /* XXX: string summary produces question marks
25440 * so this is not very ideal.
25441 */
25442 duk_push_literal(thr, "[Symbol ");
25444 duk_push_literal(thr, " ");
25446 duk_push_literal(thr, "]");
25447 duk_concat(thr, 5);
25448 break;
25449 }
25451 break;
25452 }
25453 case DUK_TAG_OBJECT: {
25455 DUK_ASSERT(h != NULL);
25456
25457 if (error_aware && duk_hobject_prototype_chain_contains(thr,
25458 h,
25460 1 /*ignore_loop*/)) {
25461 /* Get error message in a side effect free way if
25462 * possible; if not, summarize as a generic object.
25463 * Error message currently gets quoted.
25464 */
25465 /* XXX: better internal getprop call; get without side effects
25466 * but traverse inheritance chain.
25467 */
25468 duk_tval *tv_msg;
25470 if (tv_msg != NULL && DUK_TVAL_IS_STRING(tv_msg)) {
25471 /* It's critical to avoid recursion so
25472 * only summarize a string .message.
25473 */
25475 DUK_TVAL_GET_STRING(tv_msg),
25477 break;
25478 }
25479 }
25480 duk_push_class_string_tval(thr, tv, 1 /*avoid_side_effects*/);
25481 break;
25482 }
25483 case DUK_TAG_BUFFER: {
25484 /* While plain buffers mimic Uint8Arrays, they summarize differently.
25485 * This is useful so that the summarized string accurately reflects the
25486 * internal type which may matter for figuring out bugs etc.
25487 */
25488 /* XXX: Hex encoded, length limited buffer summary here? */
25490 DUK_ASSERT(h != NULL);
25491 duk_push_sprintf(thr, "[buffer:%ld]", (long) DUK_HBUFFER_GET_SIZE(h));
25492 break;
25493 }
25494 case DUK_TAG_POINTER: {
25495 /* Surround with parentheses like in JX, ensures NULL pointer
25496 * is distinguishable from null value ("(null)" vs "null").
25497 */
25498 duk_push_tval(thr, tv);
25499 duk_push_sprintf(thr, "(%s)", duk_to_string(thr, -1));
25501 break;
25502 }
25503 default: {
25504 duk_push_tval(thr, tv);
25505 break;
25506 }
25507 }
25508 }
25509
25510 return duk_to_string(thr, -1);
25511}
25514 return duk__push_string_tval_readable(thr, tv, 0 /*error_aware*/);
25516
25519 return duk_push_string_tval_readable(thr, duk_get_tval(thr, idx));
25520}
25521
25524 return duk__push_string_tval_readable(thr, tv, 1 /*error_aware*/);
25525}
25526
25528 const duk_uint8_t *p;
25529 const duk_uint8_t *p_end;
25530 const duk_uint8_t *q;
25531
25533
25534 /* .toString() */
25535 duk_push_literal(thr, "Symbol(");
25536 p = (const duk_uint8_t *) DUK_HSTRING_GET_DATA(h);
25537 p_end = p + DUK_HSTRING_GET_BYTELEN(h);
25538 DUK_ASSERT(p[0] == 0xff || (p[0] & 0xc0) == 0x80);
25539 p++;
25540 for (q = p; q < p_end; q++) {
25541 if (*q == 0xffU) {
25542 /* Terminate either at end-of-string (but NUL MUST
25543 * be accepted without terminating description) or
25544 * 0xFF, which is used to mark start of unique trailer
25545 * (and cannot occur in CESU-8 / extended UTF-8).
25546 */
25547 break;
25548 }
25549 }
25550 duk_push_lstring(thr, (const char *) p, (duk_size_t) (q - p));
25551 duk_push_literal(thr, ")");
25552 duk_concat(thr, 3);
25553}
25554
25555/*
25556 * Functions
25557 */
25558
25559#if 0 /* not used yet */
25560DUK_INTERNAL void duk_push_hnatfunc_name(duk_hthread *thr, duk_hnatfunc *h) {
25561 duk_c_function func;
25562
25564 DUK_ASSERT(h != NULL);
25566
25567 duk_push_sprintf(thr, "native_");
25568 func = h->func;
25569 duk_push_string_funcptr(thr, (duk_uint8_t *) &func, sizeof(func));
25570 duk_push_sprintf(thr, "_%04x_%04x",
25571 (unsigned int) (duk_uint16_t) h->nargs,
25572 (unsigned int) (duk_uint16_t) h->magic);
25573 duk_concat(thr, 3);
25574}
25575#endif
25576
25577/*
25578 * duk_tval slice copy
25579 */
25580
25582 duk_tval *tv;
25583
25585 DUK_UNREF(thr);
25586 DUK_ASSERT(count * sizeof(duk_tval) >= count); /* no wrap */
25587
25588 duk_memcpy_unsafe((void *) tv_dst, (const void *) tv_src, count * sizeof(duk_tval));
25589
25590 tv = tv_dst;
25591 while (count-- > 0) {
25592 DUK_TVAL_INCREF(thr, tv);
25593 tv++;
25594 }
25595}
25596
25597/* automatic undefs */
25598#undef DUK__ASSERT_SPACE
25599#undef DUK__CHECK_SPACE
25600#undef DUK__ERROR_STASH_SHARED
25601#undef DUK__PACK_ARGS
25602#undef DUK__READABLE_ERRMSG_MAXCHARS
25603#undef DUK__READABLE_STRING_MAXCHARS
25604#undef DUK__READABLE_SUMMARY_MAXCHARS
25605/*
25606 * String manipulation
25607 */
25608
25609/* #include duk_internal.h -> already included */
25610
25613 duk_uint_t i;
25614 duk_size_t idx;
25615 duk_size_t len;
25616 duk_hstring *h;
25617 duk_uint8_t *buf;
25618
25620
25621 if (DUK_UNLIKELY(count_in <= 0)) {
25622 if (count_in < 0) {
25624 DUK_WO_NORETURN(return;);
25625 }
25626 DUK_ASSERT(count_in == 0);
25628 return;
25629 }
25630 count = (duk_uint_t) count_in;
25631
25632 if (is_join) {
25633 duk_size_t t1, t2, limit;
25634 h = duk_to_hstring(thr, -((duk_idx_t) count) - 1);
25635 DUK_ASSERT(h != NULL);
25636
25637 /* A bit tricky overflow test, see doc/code-issues.rst. */
25639 t2 = (duk_size_t) (count - 1);
25641 if (DUK_UNLIKELY(t2 != 0 && t1 > limit / t2)) {
25642 /* Combined size of separators already overflows. */
25643 goto error_overflow;
25644 }
25645 len = (duk_size_t) (t1 * t2);
25646 } else {
25647 len = (duk_size_t) 0;
25648 }
25649
25650 for (i = count; i >= 1; i--) {
25651 duk_size_t new_len;
25652 h = duk_to_hstring(thr, -((duk_idx_t) i));
25653 new_len = len + (duk_size_t) DUK_HSTRING_GET_BYTELEN(h);
25654
25655 /* Impose a string maximum length, need to handle overflow
25656 * correctly.
25657 */
25658 if (new_len < len || /* wrapped */
25659 new_len > (duk_size_t) DUK_HSTRING_MAX_BYTELEN) {
25660 goto error_overflow;
25661 }
25662 len = new_len;
25663 }
25664
25665 DUK_DDD(DUK_DDDPRINT("join/concat %lu strings, total length %lu bytes", (unsigned long) count, (unsigned long) len));
25666
25667 /* Use stack allocated buffer to ensure reachability in errors
25668 * (e.g. intern error).
25669 */
25670 buf = (duk_uint8_t *) duk_push_fixed_buffer_nozero(thr, len);
25671 DUK_ASSERT(buf != NULL);
25672
25673 /* [ ... (sep) str1 str2 ... strN buf ] */
25674
25675 idx = 0;
25676 for (i = count; i >= 1; i--) {
25677 if (is_join && i != count) {
25678 h = duk_require_hstring(thr, -((duk_idx_t) count) - 2); /* extra -1 for buffer */
25680 idx += DUK_HSTRING_GET_BYTELEN(h);
25681 }
25682 h = duk_require_hstring(thr, -((duk_idx_t) i) - 1); /* extra -1 for buffer */
25684 idx += DUK_HSTRING_GET_BYTELEN(h);
25685 }
25686
25687 DUK_ASSERT(idx == len);
25688
25689 /* [ ... (sep) str1 str2 ... strN buf ] */
25690
25691 /* Get rid of the strings early to minimize memory use before intern. */
25692
25693 if (is_join) {
25694 duk_replace(thr, -((duk_idx_t) count) - 2); /* overwrite sep */
25695 duk_pop_n(thr, (duk_idx_t) count);
25696 } else {
25697 duk_replace(thr, -((duk_idx_t) count) - 1); /* overwrite str1 */
25698 duk_pop_n(thr, (duk_idx_t) (count - 1));
25699 }
25700
25701 /* [ ... buf ] */
25702
25703 (void) duk_buffer_to_string(thr, -1); /* Safe if inputs are safe. */
25704
25705 /* [ ... res ] */
25706 return;
25707
25708error_overflow:
25710 DUK_WO_NORETURN(return;);
25711}
25712
25715
25716 duk__concat_and_join_helper(thr, count, 0 /*is_join*/);
25717}
25718
25719#if defined(DUK_USE_PREFER_SIZE)
25722 duk_concat(thr, 2);
25723}
25724#else /* DUK_USE_PREFER_SIZE */
25726 duk_hstring *h1;
25727 duk_hstring *h2;
25728 duk_uint8_t *buf;
25729 duk_size_t len1;
25730 duk_size_t len2;
25731 duk_size_t len;
25732
25734 DUK_ASSERT(duk_get_top(thr) >= 2); /* Trusted caller. */
25735
25736 h1 = duk_to_hstring(thr, -2);
25737 h2 = duk_to_hstring(thr, -1);
25740 len = len1 + len2;
25741 if (DUK_UNLIKELY(len < len1 || /* wrapped */
25743 goto error_overflow;
25744 }
25745 buf = (duk_uint8_t *) duk_push_fixed_buffer_nozero(thr, len);
25746 DUK_ASSERT(buf != NULL);
25747
25748 duk_memcpy((void *) buf, (const void *) DUK_HSTRING_GET_DATA(h1), (size_t) len1);
25749 duk_memcpy((void *) (buf + len1), (const void *) DUK_HSTRING_GET_DATA(h2), (size_t) len2);
25750 (void) duk_buffer_to_string(thr, -1); /* Safe if inputs are safe. */
25751
25752 /* [ ... str1 str2 buf ] */
25753
25754 duk_replace(thr, -3);
25755 duk_pop_unsafe(thr);
25756 return;
25757
25758error_overflow:
25760 DUK_WO_NORETURN(return;);
25761}
25762#endif /* DUK_USE_PREFER_SIZE */
25763
25766
25767 duk__concat_and_join_helper(thr, count, 1 /*is_join*/);
25768}
25769
25770/* XXX: could map/decode be unified with duk_unicode_support.c code?
25771 * Case conversion needs also the character surroundings though.
25772 */
25773
25774DUK_EXTERNAL void duk_decode_string(duk_hthread *thr, duk_idx_t idx, duk_decode_char_function callback, void *udata) {
25775 duk_hstring *h_input;
25776 const duk_uint8_t *p, *p_start, *p_end;
25777 duk_codepoint_t cp;
25778
25780
25781 h_input = duk_require_hstring(thr, idx); /* Accept symbols. */
25782 DUK_ASSERT(h_input != NULL);
25783
25784 p_start = (const duk_uint8_t *) DUK_HSTRING_GET_DATA(h_input);
25785 p_end = p_start + DUK_HSTRING_GET_BYTELEN(h_input);
25786 p = p_start;
25787
25788 for (;;) {
25789 if (p >= p_end) {
25790 break;
25791 }
25792 cp = (duk_codepoint_t) duk_unicode_decode_xutf8_checked(thr, &p, p_start, p_end);
25793 callback(udata, cp);
25794 }
25795}
25796
25797DUK_EXTERNAL void duk_map_string(duk_hthread *thr, duk_idx_t idx, duk_map_char_function callback, void *udata) {
25798 duk_hstring *h_input;
25799 duk_bufwriter_ctx bw_alloc;
25801 const duk_uint8_t *p, *p_start, *p_end;
25802 duk_codepoint_t cp;
25803
25805
25806 idx = duk_normalize_index(thr, idx);
25807
25808 h_input = duk_require_hstring(thr, idx); /* Accept symbols. */
25809 DUK_ASSERT(h_input != NULL);
25810
25811 bw = &bw_alloc;
25812 DUK_BW_INIT_PUSHBUF(thr, bw, DUK_HSTRING_GET_BYTELEN(h_input)); /* Reasonable output estimate. */
25813
25814 p_start = (const duk_uint8_t *) DUK_HSTRING_GET_DATA(h_input);
25815 p_end = p_start + DUK_HSTRING_GET_BYTELEN(h_input);
25816 p = p_start;
25817
25818 for (;;) {
25819 /* XXX: could write output in chunks with fewer ensure calls,
25820 * but relative benefit would be small here.
25821 */
25822
25823 if (p >= p_end) {
25824 break;
25826 cp = (duk_codepoint_t) duk_unicode_decode_xutf8_checked(thr, &p, p_start, p_end);
25827 cp = callback(udata, cp);
25828
25829 DUK_BW_WRITE_ENSURE_XUTF8(thr, bw, cp);
25830 }
25831
25832 DUK_BW_COMPACT(thr, bw);
25833 (void) duk_buffer_to_string(thr, -1); /* Safe, extended UTF-8 encoded. */
25834 duk_replace(thr, idx);
25835}
25836
25837DUK_EXTERNAL void duk_substring(duk_hthread *thr, duk_idx_t idx, duk_size_t start_offset, duk_size_t end_offset) {
25838 duk_hstring *h;
25839 duk_hstring *res;
25840 duk_size_t start_byte_offset;
25841 duk_size_t end_byte_offset;
25842 duk_size_t charlen;
25843
25845
25846 idx = duk_require_normalize_index(thr, idx); /* Accept symbols. */
25847 h = duk_require_hstring(thr, idx);
25848 DUK_ASSERT(h != NULL);
25849
25850 charlen = DUK_HSTRING_GET_CHARLEN(h);
25851 if (end_offset >= charlen) {
25852 end_offset = charlen;
25853 }
25854 if (start_offset > end_offset) {
25855 start_offset = end_offset;
25856 }
25857
25858 DUK_ASSERT_DISABLE(start_offset >= 0);
25859 DUK_ASSERT(start_offset <= end_offset && start_offset <= DUK_HSTRING_GET_CHARLEN(h));
25860 DUK_ASSERT_DISABLE(end_offset >= 0);
25861 DUK_ASSERT(end_offset >= start_offset && end_offset <= DUK_HSTRING_GET_CHARLEN(h));
25862
25863 /* Guaranteed by string limits. */
25864 DUK_ASSERT(start_offset <= DUK_UINT32_MAX);
25865 DUK_ASSERT(end_offset <= DUK_UINT32_MAX);
25866
25867 start_byte_offset = (duk_size_t) duk_heap_strcache_offset_char2byte(thr, h, (duk_uint_fast32_t) start_offset);
25868 end_byte_offset = (duk_size_t) duk_heap_strcache_offset_char2byte(thr, h, (duk_uint_fast32_t) end_offset);
25869
25870 DUK_ASSERT(end_byte_offset >= start_byte_offset);
25871 DUK_ASSERT(end_byte_offset - start_byte_offset <= DUK_UINT32_MAX); /* Guaranteed by string limits. */
25872
25873 /* No size check is necessary. */
25875 DUK_HSTRING_GET_DATA(h) + start_byte_offset,
25876 (duk_uint32_t) (end_byte_offset - start_byte_offset));
25877
25878 duk_push_hstring(thr, res);
25879 duk_replace(thr, idx);
25880}
25881
25882/* XXX: this is quite clunky. Add Unicode helpers to scan backwards and
25883 * forwards with a callback to process codepoints?
25884 */
25886 duk_hstring *h;
25887 const duk_uint8_t *p, *p_start, *p_end, *p_tmp1, *p_tmp2; /* pointers for scanning */
25888 const duk_uint8_t *q_start, *q_end; /* start (incl) and end (excl) of trimmed part */
25889 duk_codepoint_t cp;
25890
25892
25893 idx = duk_require_normalize_index(thr, idx); /* Accept symbols. */
25894 h = duk_require_hstring(thr, idx);
25895 DUK_ASSERT(h != NULL);
25896
25897 p_start = DUK_HSTRING_GET_DATA(h);
25898 p_end = p_start + DUK_HSTRING_GET_BYTELEN(h);
25899
25900 p = p_start;
25901 while (p < p_end) {
25902 p_tmp1 = p;
25903 cp = (duk_codepoint_t) duk_unicode_decode_xutf8_checked(thr, &p_tmp1, p_start, p_end);
25905 break;
25906 }
25907 p = p_tmp1;
25908 }
25909 q_start = p;
25910 if (p == p_end) {
25911 /* Entire string is whitespace. */
25912 q_end = p;
25913 goto scan_done;
25914 }
25915
25916 p = p_end;
25917 while (p > p_start) {
25918 p_tmp1 = p;
25919 while (p > p_start) {
25920 p--;
25921 if (((*p) & 0xc0) != 0x80) {
25922 break;
25923 }
25924 }
25925 p_tmp2 = p;
25926
25927 cp = (duk_codepoint_t) duk_unicode_decode_xutf8_checked(thr, &p_tmp2, p_start, p_end);
25929 p = p_tmp1;
25930 break;
25931 }
25932 }
25933 q_end = p;
25934
25935scan_done:
25936 /* This may happen when forward and backward scanning disagree
25937 * (possible for non-extended-UTF-8 strings).
25938 */
25939 if (q_end < q_start) {
25940 q_end = q_start;
25941 }
25942
25943 DUK_ASSERT(q_start >= p_start && q_start <= p_end);
25944 DUK_ASSERT(q_end >= p_start && q_end <= p_end);
25945 DUK_ASSERT(q_end >= q_start);
25946
25947 DUK_DDD(DUK_DDDPRINT("trim: p_start=%p, p_end=%p, q_start=%p, q_end=%p",
25948 (const void *) p_start,
25949 (const void *) p_end,
25950 (const void *) q_start,
25951 (const void *) q_end));
25952
25953 if (q_start == p_start && q_end == p_end) {
25954 DUK_DDD(DUK_DDDPRINT("nothing was trimmed: avoid interning (hashing etc)"));
25955 return;
25956 }
25957
25958 duk_push_lstring(thr, (const char *) q_start, (duk_size_t) (q_end - q_start));
25959 duk_replace(thr, idx);
25960}
25961
25963 duk_hstring *h;
25965
25967
25968 /* XXX: Share code with String.prototype.charCodeAt? Main difference
25969 * is handling of clamped offsets.
25970 */
25971
25972 h = duk_require_hstring(thr, idx); /* Accept symbols. */
25973 DUK_ASSERT(h != NULL);
25974
25975 DUK_ASSERT_DISABLE(char_offset >= 0); /* Always true, arg is unsigned. */
25976 if (char_offset >= DUK_HSTRING_GET_CHARLEN(h)) {
25977 return 0;
25979
25980 DUK_ASSERT(char_offset <= DUK_UINT_MAX); /* Guaranteed by string limits. */
25981 cp = duk_hstring_char_code_at_raw(thr, h, (duk_uint_t) char_offset, 0 /*surrogate_aware*/);
25982 return (duk_codepoint_t) cp;
25983}
25984/*
25985 * Date/time.
25987
25988/* #include duk_internal.h -> already included */
25989
25991 /* ECMAScript time, with millisecond fractions. Exposed via
25992 * duk_get_now() for example.
25993 */
25995 return (duk_double_t) DUK_USE_DATE_GET_NOW(thr);
25996}
25997
25999 /* ECMAScript time without millisecond fractions. Exposed via
26000 * the Date built-in which doesn't allow fractions.
26001 */
26002 DUK_UNREF(thr);
26003 return (duk_double_t) DUK_FLOOR(DUK_USE_DATE_GET_NOW(thr));
26004}
26005
26007 DUK_UNREF(thr);
26008#if defined(DUK_USE_GET_MONOTONIC_TIME)
26009 return (duk_double_t) DUK_USE_GET_MONOTONIC_TIME(thr);
26010#else
26011 return (duk_double_t) DUK_USE_DATE_GET_NOW(thr);
26012#endif
26013}
26014
26017 DUK_UNREF(thr);
26018
26019 /* This API intentionally allows millisecond fractions. */
26021}
26022
26023#if 0 /* XXX: worth exposing? */
26024DUK_EXTERNAL duk_double_t duk_get_monotonic_time(duk_hthread *thr) {
26026 DUK_UNREF(thr);
26027
26028 return duk_time_get_monotonic_time(thr);
26029}
26030#endif
26031
26035 duk_uint_t flags;
26036
26038 DUK_ASSERT(comp != NULL); /* XXX: or check? */
26039 DUK_UNREF(thr);
26040
26041 /* Convert as one-based, but change month to zero-based to match the
26042 * ECMAScript Date built-in behavior 1:1.
26043 */
26045
26046 duk_bi_date_timeval_to_parts(timeval, parts, dparts, flags);
26047
26048 /* XXX: sub-millisecond accuracy for the API */
26050 DUK_ASSERT(dparts[DUK_DATE_IDX_MONTH] >= 1.0 && dparts[DUK_DATE_IDX_MONTH] <= 12.0);
26051 comp->year = dparts[DUK_DATE_IDX_YEAR];
26052 comp->month = dparts[DUK_DATE_IDX_MONTH] - 1.0;
26053 comp->day = dparts[DUK_DATE_IDX_DAY];
26054 comp->hours = dparts[DUK_DATE_IDX_HOUR];
26055 comp->minutes = dparts[DUK_DATE_IDX_MINUTE];
26056 comp->seconds = dparts[DUK_DATE_IDX_SECOND];
26057 comp->milliseconds = dparts[DUK_DATE_IDX_MILLISECOND];
26058 comp->weekday = dparts[DUK_DATE_IDX_WEEKDAY];
26059}
26060
26062 duk_double_t d;
26064 duk_uint_t flags;
26065
26067 DUK_ASSERT(comp != NULL); /* XXX: or check? */
26068 DUK_UNREF(thr);
26069
26070 /* Match Date constructor behavior (with UTC time). Month is given
26071 * as zero-based. Day-of-month is given as one-based so normalize
26072 * it to zero-based as the internal conversion helpers expects all
26073 * components to be zero-based.
26074 */
26075 flags = 0;
26076
26077 /* XXX: expensive conversion; use array format in API instead, or unify
26078 * time provider and time API to use same struct?
26079 */
26080
26081 dparts[DUK_DATE_IDX_YEAR] = comp->year;
26082 dparts[DUK_DATE_IDX_MONTH] = comp->month;
26083 dparts[DUK_DATE_IDX_DAY] = comp->day - 1.0;
26084 dparts[DUK_DATE_IDX_HOUR] = comp->hours;
26085 dparts[DUK_DATE_IDX_MINUTE] = comp->minutes;
26086 dparts[DUK_DATE_IDX_SECOND] = comp->seconds;
26087 dparts[DUK_DATE_IDX_MILLISECOND] = comp->milliseconds;
26088 dparts[DUK_DATE_IDX_WEEKDAY] = 0; /* ignored */
26089
26090 d = duk_bi_date_get_timeval_from_dparts(dparts, flags);
26091
26092 return d;
26093}
26094/*
26095 * Array built-ins
26096 *
26097 * Most Array built-ins are intentionally generic in ECMAScript, and are
26098 * intended to work even when the 'this' binding is not an Array instance.
26099 * This ECMAScript feature is also used by much real world code. For this
26100 * reason the implementations here don't assume exotic Array behavior or
26101 * e.g. presence of a .length property. However, some algorithms have a
26102 * fast path for duk_harray backed actual Array instances, enabled when
26103 * footprint is not a concern.
26104 *
26105 * XXX: the "Throw" flag should be set for (almost?) all [[Put]] and
26106 * [[Delete]] operations, but it's currently false throughout. Go through
26107 * all put/delete cases and check throw flag use. Need a new API primitive
26108 * which allows throws flag to be specified.
26109 *
26110 * XXX: array lengths above 2G won't work reliably. There are many places
26111 * where one needs a full signed 32-bit range ([-0xffffffff, 0xffffffff],
26112 * i.e. -33- bits). Although array 'length' cannot be written to be outside
26113 * the unsigned 32-bit range (E5.1 Section 15.4.5.1 throws a RangeError if so)
26114 * some intermediate values may be above 0xffffffff and this may not be always
26115 * correctly handled now (duk_uint32_t is not enough for all algorithms).
26116 * For instance, push() can legitimately write entries beyond length 0xffffffff
26117 * and cause a RangeError only at the end. To do this properly, the current
26118 * push() implementation tracks the array index using a 'double' instead of a
26119 * duk_uint32_t (which is somewhat awkward). See test-bi-array-push-maxlen.js.
26120 *
26121 * On using "put" vs. "def" prop
26122 * =============================
26123 *
26124 * Code below must be careful to use the appropriate primitive as it matters
26125 * for compliance. When using "put" there may be inherited properties in
26126 * Array.prototype which cause side effects when values are written. When
26127 * using "define" there are no such side effects, and many test262 test cases
26128 * check for this (for real world code, such side effects are very rare).
26129 * Both "put" and "define" are used in the E5.1 specification; as a rule,
26130 * "put" is used when modifying an existing array (or a non-array 'this'
26131 * binding) and "define" for setting values into a fresh result array.
26132 */
26133
26134/* #include duk_internal.h -> already included */
26135
26136/* Perform an intermediate join when this many elements have been pushed
26137 * on the value stack.
26138 */
26139#define DUK__ARRAY_MID_JOIN_LIMIT 4096
26141#if defined(DUK_USE_ARRAY_BUILTIN)
26142
26143/*
26144 * Shared helpers.
26145 */
26146
26147/* Shared entry code for many Array built-ins: the 'this' binding is pushed
26148 * on the value stack and object coerced, and the current .length is returned.
26149 * Note that length is left on stack (it could be popped, but that's not
26150 * usually necessary because call handling will clean it up automatically).
26151 */
26153 duk_uint32_t len;
26154
26155 /* XXX: push more directly? */
26159 len = duk_to_uint32(thr, -1);
26160
26161 /* -> [ ... ToObject(this) ToUint32(length) ] */
26162 return len;
26163}
26164
26166 /* Range limited to [0, 0x7fffffff] range, i.e. range that can be
26167 * represented with duk_int32_t. Use this when the method doesn't
26168 * handle the full 32-bit unsigned range correctly.
26169 */
26170 duk_uint32_t ret = duk__push_this_obj_len_u32(thr);
26171 if (DUK_UNLIKELY(ret >= 0x80000000UL)) {
26173 DUK_WO_NORETURN(return 0U;);
26174 }
26175 return ret;
26176}
26177
26178#if defined(DUK_USE_ARRAY_FASTPATH)
26179/* Check if 'this' binding is an Array instance (duk_harray) which satisfies
26180 * a few other guarantees for fast path operation. The fast path doesn't
26181 * need to handle all operations, even for duk_harrays, but must handle a
26182 * significant fraction to improve performance. Return a non-NULL duk_harray
26183 * pointer when all fast path criteria are met, NULL otherwise.
26184 */
26186 duk_tval *tv;
26187 duk_hobject *h;
26188 duk_uint_t flags_mask, flags_bits, flags_value;
26189
26190 DUK_ASSERT(thr->valstack_bottom > thr->valstack); /* because call in progress */
26191 tv = DUK_GET_THIS_TVAL_PTR(thr);
26192
26193 /* Fast path requires that 'this' is a duk_harray. Read only arrays
26194 * (ROM backed) are also rejected for simplicity.
26195 */
26196 if (!DUK_TVAL_IS_OBJECT(tv)) {
26197 DUK_DD(DUK_DDPRINT("reject array fast path: not an object"));
26198 return NULL;
26199 }
26200 h = DUK_TVAL_GET_OBJECT(tv);
26201 DUK_ASSERT(h != NULL);
26204 flags_value = DUK_HEAPHDR_GET_FLAGS_RAW((duk_heaphdr *) h);
26205 if ((flags_value & flags_mask) != flags_bits) {
26206 DUK_DD(DUK_DDPRINT("reject array fast path: object flag check failed"));
26207 return NULL;
26208 }
26209
26210 /* In some cases a duk_harray's 'length' may be larger than the
26211 * current array part allocation. Avoid the fast path in these
26212 * cases, so that all fast path code can safely assume that all
26213 * items in the range [0,length[ are backed by the current array
26214 * part allocation.
26215 */
26216 if (((duk_harray *) h)->length > DUK_HOBJECT_GET_ASIZE(h)) {
26217 DUK_DD(DUK_DDPRINT("reject array fast path: length > array part size"));
26218 return NULL;
26219 }
26220
26221 /* Guarantees for fast path. */
26222 DUK_ASSERT(h != NULL);
26224 DUK_ASSERT(((duk_harray *) h)->length <= DUK_HOBJECT_GET_ASIZE(h));
26225
26226 DUK_DD(DUK_DDPRINT("array fast path allowed for: %!O", (duk_heaphdr *) h));
26227 return (duk_harray *) h;
26228}
26229#endif /* DUK_USE_ARRAY_FASTPATH */
26230
26231/*
26232 * Constructor
26233 */
26234
26236 duk_idx_t nargs;
26237 duk_harray *a;
26238 duk_double_t d;
26239 duk_uint32_t len;
26240 duk_uint32_t len_prealloc;
26241
26242 nargs = duk_get_top(thr);
26243
26244 if (nargs == 1 && duk_is_number(thr, 0)) {
26245 /* XXX: expensive check (also shared elsewhere - so add a shared internal API call?) */
26246 d = duk_get_number(thr, 0);
26247 len = duk_to_uint32(thr, 0);
26248 if (!duk_double_equals((duk_double_t) len, d)) {
26250 }
26251
26252 /* For small lengths create a dense preallocated array.
26253 * For large arrays preallocate an initial part.
26254 */
26255 len_prealloc = len < 64 ? len : 64;
26256 a = duk_push_harray_with_size(thr, len_prealloc);
26257 DUK_ASSERT(a != NULL);
26258 DUK_ASSERT(!duk_is_bare_object(thr, -1));
26259 a->length = len;
26260 return 1;
26261 }
26262
26263 duk_pack(thr, nargs);
26264 return 1;
26265}
26266
26267/*
26268 * isArray()
26270
26272 DUK_ASSERT_TOP(thr, 1);
26274 return 1;
26275}
26276
26277/*
26278 * toString()
26279 */
26280
26284
26285 /* [ ... this func ] */
26286 if (!duk_is_callable(thr, -1)) {
26287 /* Fall back to the initial (original) Object.toString(). We don't
26288 * currently have pointers to the built-in functions, only the top
26289 * level global objects (like "Array") so this is now done in a bit
26290 * of a hacky manner. It would be cleaner to push the (original)
26291 * function and use duk_call_method().
26292 */
26293
26294 /* XXX: 'this' will be ToObject() coerced twice, which is incorrect
26295 * but should have no visible side effects.
26296 */
26297 DUK_DDD(DUK_DDDPRINT("this.join is not callable, fall back to (original) Object.toString"));
26298 duk_set_top(thr, 0);
26299 return duk_bi_object_prototype_to_string(thr); /* has access to 'this' binding */
26300 }
26301
26302 /* [ ... this func ] */
26303
26304 duk_insert(thr, -2);
26305
26306 /* [ ... func this ] */
26308 DUK_DDD(
26309 DUK_DDDPRINT("calling: func=%!iT, this=%!iT", (duk_tval *) duk_get_tval(thr, -2), (duk_tval *) duk_get_tval(thr, -1)));
26310 duk_call_method(thr, 0);
26311
26312 return 1;
26313}
26314
26315/*
26316 * concat()
26317 */
26318
26320 duk_idx_t i, n;
26321 duk_uint32_t j, idx, len;
26322 duk_hobject *h;
26323 duk_size_t tmp_len;
26324
26325 /* XXX: In ES2015 Array .length can be up to 2^53-1. The current
26326 * implementation is limited to 2^32-1.
26327 */
26328
26329 /* XXX: Fast path for array 'this' and array element. */
26330
26331 /* XXX: The insert here is a bit expensive if there are a lot of items.
26332 * It could also be special cased in the outermost for loop quite easily
26333 * (as the element is dup()'d anyway).
26334 */
26335
26337 duk_insert(thr, 0);
26338 n = duk_get_top(thr);
26339 duk_push_array(thr); /* -> [ ToObject(this) item1 ... itemN arr ] */
26340
26341 /* NOTE: The Array special behaviors are NOT invoked by duk_xdef_prop_index()
26342 * (which differs from the official algorithm). If no error is thrown, this
26343 * doesn't matter as the length is updated at the end. However, if an error
26344 * is thrown, the length will be unset. That shouldn't matter because the
26345 * caller won't get a reference to the intermediate value.
26346 */
26347
26348 idx = 0;
26349 for (i = 0; i < n; i++) {
26350 duk_bool_t spreadable;
26351 duk_bool_t need_has_check;
26352
26353 DUK_ASSERT_TOP(thr, n + 1);
26354
26355 /* [ ToObject(this) item1 ... itemN arr ] */
26356
26357 h = duk_get_hobject(thr, i);
26358
26359 if (h == NULL) {
26360 spreadable = 0;
26361 } else {
26362#if defined(DUK_USE_SYMBOL_BUILTIN)
26364 if (duk_is_undefined(thr, -1)) {
26365 spreadable = duk_js_isarray_hobject(h);
26366 } else {
26367 spreadable = duk_to_boolean(thr, -1);
26368 }
26370#else
26371 spreadable = duk_js_isarray_hobject(h);
26372#endif
26373 }
26374
26375 if (!spreadable) {
26376 duk_dup(thr, i);
26377 duk_xdef_prop_index_wec(thr, -2, idx);
26378 idx++;
26379 if (DUK_UNLIKELY(idx == 0U)) {
26380 /* Index after update is 0, and index written
26381 * was 0xffffffffUL which is no longer a valid
26382 * array index.
26383 */
26384 goto fail_wrap;
26385 }
26386 continue;
26387 }
26388
26389 DUK_ASSERT(duk_is_object(thr, i));
26390 need_has_check = (DUK_HOBJECT_IS_PROXY(h) != 0); /* Always 0 w/o Proxy support. */
26391
26392 /* [ ToObject(this) item1 ... itemN arr ] */
26393
26394 tmp_len = duk_get_length(thr, i);
26395 len = (duk_uint32_t) tmp_len;
26396 if (DUK_UNLIKELY(tmp_len != (duk_size_t) len)) {
26397 goto fail_wrap;
26398 }
26399 if (DUK_UNLIKELY(idx + len < idx)) {
26400 /* Result length must be at most 0xffffffffUL to be
26401 * a valid 32-bit array index.
26402 */
26403 goto fail_wrap;
26404 }
26405 for (j = 0; j < len; j++) {
26406 /* For a Proxy element, an explicit 'has' check is
26407 * needed to allow the Proxy to present gaps.
26408 */
26409 if (need_has_check) {
26410 if (duk_has_prop_index(thr, i, j)) {
26411 duk_get_prop_index(thr, i, j);
26412 duk_xdef_prop_index_wec(thr, -2, idx);
26413 }
26414 } else {
26415 if (duk_get_prop_index(thr, i, j)) {
26416 duk_xdef_prop_index_wec(thr, -2, idx);
26417 } else {
26418 duk_pop_undefined(thr);
26419 }
26420 }
26421 idx++;
26422 DUK_ASSERT(idx != 0U); /* Wrap check above. */
26423 }
26424 }
26425
26426 /* ES5.1 has a specification "bug" in that nonexistent trailing
26427 * elements don't affect the result .length. Test262 and other
26428 * engines disagree, and the specification bug was fixed in ES2015
26429 * (see NOTE 1 in https://www.ecma-international.org/ecma-262/6.0/#sec-array.prototype.concat).
26430 */
26431 duk_push_uarridx(thr, idx);
26433
26434 DUK_ASSERT_TOP(thr, n + 1);
26435 return 1;
26436
26437fail_wrap:
26439 DUK_WO_NORETURN(return 0;);
26440}
26441
26442/*
26443 * join(), toLocaleString()
26444 *
26445 * Note: checking valstack is necessary, but only in the per-element loop.
26446 *
26447 * Note: the trivial approach of pushing all the elements on the value stack
26448 * and then calling duk_join() fails when the array contains a large number
26449 * of elements. This problem can't be offloaded to duk_join() because the
26450 * elements to join must be handled here and have special handling. Current
26451 * approach is to do intermediate joins with very large number of elements.
26452 * There is no fancy handling; the prefix gets re-joined multiple times.
26453 */
26454
26456 duk_uint32_t len, count;
26457 duk_uint32_t idx;
26458 duk_small_int_t to_locale_string = duk_get_current_magic(thr);
26459 duk_idx_t valstack_required;
26460
26461 /* For join(), nargs is 1. For toLocaleString(), nargs is 0 and
26462 * setting the top essentially pushes an undefined to the stack,
26463 * thus defaulting to a comma separator.
26464 */
26465 duk_set_top(thr, 1);
26466 if (duk_is_undefined(thr, 0)) {
26467 duk_pop_undefined(thr);
26469 } else {
26470 duk_to_string(thr, 0);
26471 }
26472
26473 len = duk__push_this_obj_len_u32(thr);
26474
26475 /* [ sep ToObject(this) len ] */
26476
26477 DUK_DDD(DUK_DDDPRINT("sep=%!T, this=%!T, len=%lu",
26478 (duk_tval *) duk_get_tval(thr, 0),
26479 (duk_tval *) duk_get_tval(thr, 1),
26480 (unsigned long) len));
26481
26482 /* The extra (+4) is tight. */
26483 valstack_required = (duk_idx_t) ((len >= DUK__ARRAY_MID_JOIN_LIMIT ? DUK__ARRAY_MID_JOIN_LIMIT : len) + 4);
26484 duk_require_stack(thr, valstack_required);
26485
26486 duk_dup_0(thr);
26487
26488 /* [ sep ToObject(this) len sep ] */
26489
26490 count = 0;
26491 idx = 0;
26492 for (;;) {
26493 DUK_DDD(DUK_DDDPRINT("join idx=%ld", (long) idx));
26494 if (count >= DUK__ARRAY_MID_JOIN_LIMIT || /* intermediate join to avoid valstack overflow */
26495 idx >= len) { /* end of loop (careful with len==0) */
26496 /* [ sep ToObject(this) len sep str0 ... str(count-1) ] */
26497 DUK_DDD(DUK_DDDPRINT("mid/final join, count=%ld, idx=%ld, len=%ld", (long) count, (long) idx, (long) len));
26498 duk_join(thr, (duk_idx_t) count); /* -> [ sep ToObject(this) len str ] */
26499 duk_dup_0(thr); /* -> [ sep ToObject(this) len str sep ] */
26500 duk_insert(thr, -2); /* -> [ sep ToObject(this) len sep str ] */
26501 count = 1;
26502 }
26503 if (idx >= len) {
26504 /* if true, the stack already contains the final result */
26505 break;
26506 }
26507
26508 duk_get_prop_index(thr, 1, (duk_uarridx_t) idx);
26509 if (duk_is_null_or_undefined(thr, -1)) {
26512 } else {
26513 if (to_locale_string) {
26514 duk_to_object(thr, -1);
26516 duk_insert(thr, -2); /* -> [ ... toLocaleString ToObject(val) ] */
26517 duk_call_method(thr, 0);
26518 }
26519 duk_to_string(thr, -1);
26520 }
26521
26522 count++;
26523 idx++;
26525
26526 /* [ sep ToObject(this) len sep result ] */
26527
26528 return 1;
26529}
26530
26531/*
26532 * pop(), push()
26533 */
26534
26535#if defined(DUK_USE_ARRAY_FASTPATH)
26537 duk_tval *tv_arraypart;
26538 duk_tval *tv_val;
26539 duk_uint32_t len;
26540
26541 tv_arraypart = DUK_HOBJECT_A_GET_BASE(thr->heap, (duk_hobject *) h_arr);
26542 len = h_arr->length;
26543 if (len <= 0) {
26544 /* nop, return undefined */
26545 return 0;
26546 }
26547
26548 len--;
26549 h_arr->length = len;
26550
26551 /* Fast path doesn't check for an index property inherited from
26552 * Array.prototype. This is quite often acceptable; if not,
26553 * disable fast path.
26554 */
26556 tv_val = tv_arraypart + len;
26557 if (DUK_TVAL_IS_UNUSED(tv_val)) {
26558 /* No net refcount change. Value stack already has
26559 * 'undefined' based on value stack init policy.
26560 */
26563 } else {
26564 /* No net refcount change. */
26565 DUK_TVAL_SET_TVAL(thr->valstack_top, tv_val);
26566 DUK_TVAL_SET_UNUSED(tv_val);
26567 }
26568 thr->valstack_top++;
26569
26570 /* XXX: there's no shrink check in the fast path now */
26571
26572 return 1;
26573}
26574#endif /* DUK_USE_ARRAY_FASTPATH */
26575
26577 duk_uint32_t len;
26578 duk_uint32_t idx;
26579#if defined(DUK_USE_ARRAY_FASTPATH)
26580 duk_harray *h_arr;
26581#endif
26582
26583 DUK_ASSERT_TOP(thr, 0);
26584
26585#if defined(DUK_USE_ARRAY_FASTPATH)
26586 h_arr = duk__arraypart_fastpath_this(thr);
26587 if (h_arr) {
26588 return duk__array_pop_fastpath(thr, h_arr);
26589 }
26590#endif
26591
26592 /* XXX: Merge fastpath check into a related call (push this, coerce length, etc)? */
26593
26594 len = duk__push_this_obj_len_u32(thr);
26595 if (len == 0) {
26596 duk_push_int(thr, 0);
26598 return 0;
26599 }
26600 idx = len - 1;
26601
26602 duk_get_prop_index(thr, 0, (duk_uarridx_t) idx);
26603 duk_del_prop_index(thr, 0, (duk_uarridx_t) idx);
26604 duk_push_u32(thr, idx);
26606 return 1;
26607}
26608
26609#if defined(DUK_USE_ARRAY_FASTPATH)
26611 duk_tval *tv_arraypart;
26612 duk_tval *tv_src;
26613 duk_tval *tv_dst;
26614 duk_uint32_t len;
26615 duk_idx_t i, n;
26616
26617 len = h_arr->length;
26618 tv_arraypart = DUK_HOBJECT_A_GET_BASE(thr->heap, (duk_hobject *) h_arr);
26619
26620 n = (duk_idx_t) (thr->valstack_top - thr->valstack_bottom);
26621 DUK_ASSERT(n >= 0);
26622 DUK_ASSERT((duk_uint32_t) n <= DUK_UINT32_MAX);
26623 if (DUK_UNLIKELY(len + (duk_uint32_t) n < len)) {
26624 DUK_D(DUK_DPRINT("Array.prototype.push() would go beyond 32-bit length, throw"));
26625 DUK_DCERROR_RANGE_INVALID_LENGTH(thr); /* != 0 return value returned as is by caller */
26626 }
26627 if (len + (duk_uint32_t) n > DUK_HOBJECT_GET_ASIZE((duk_hobject *) h_arr)) {
26628 /* Array part would need to be extended. Rely on slow path
26629 * for now.
26630 *
26631 * XXX: Rework hobject code a bit and add extend support.
26632 */
26633 return 0;
26634 }
26635
26636 tv_src = thr->valstack_bottom;
26637 tv_dst = tv_arraypart + len;
26638 for (i = 0; i < n; i++) {
26639 /* No net refcount change; reset value stack values to
26640 * undefined to satisfy value stack init policy.
26641 */
26642 DUK_TVAL_SET_TVAL(tv_dst, tv_src);
26643 DUK_TVAL_SET_UNDEFINED(tv_src);
26644 tv_src++;
26645 tv_dst++;
26646 }
26647 thr->valstack_top = thr->valstack_bottom;
26648 len += (duk_uint32_t) n;
26649 h_arr->length = len;
26650
26651 DUK_ASSERT((duk_uint_t) len == len);
26652 duk_push_uint(thr, (duk_uint_t) len);
26653 return 1;
26654}
26655#endif /* DUK_USE_ARRAY_FASTPATH */
26656
26658 /* Note: 'this' is not necessarily an Array object. The push()
26659 * algorithm is supposed to work for other kinds of objects too,
26660 * so the algorithm has e.g. an explicit update for the 'length'
26661 * property which is normally "magical" in arrays.
26662 */
26663
26664 duk_uint32_t len;
26665 duk_idx_t i, n;
26666#if defined(DUK_USE_ARRAY_FASTPATH)
26667 duk_harray *h_arr;
26668#endif
26669
26670#if defined(DUK_USE_ARRAY_FASTPATH)
26671 h_arr = duk__arraypart_fastpath_this(thr);
26672 if (h_arr) {
26673 duk_ret_t rc;
26674 rc = duk__array_push_fastpath(thr, h_arr);
26675 if (rc != 0) {
26676 return rc;
26677 }
26678 DUK_DD(DUK_DDPRINT("array push() fast path exited, resize case"));
26679 }
26680#endif
26681
26682 n = duk_get_top(thr);
26683 len = duk__push_this_obj_len_u32(thr);
26684
26685 /* [ arg1 ... argN obj length ] */
26686
26687 /* Technically Array.prototype.push() can create an Array with length
26688 * longer than 2^32-1, i.e. outside the 32-bit range. The final length
26689 * is *not* wrapped to 32 bits in the specification.
26690 *
26691 * This implementation tracks length with a uint32 because it's much
26692 * more practical.
26693 *
26694 * See: test-bi-array-push-maxlen.js.
26695 */
26696
26697 if (len + (duk_uint32_t) n < len) {
26698 DUK_D(DUK_DPRINT("Array.prototype.push() would go beyond 32-bit length, throw"));
26700 }
26701
26702 for (i = 0; i < n; i++) {
26703 duk_dup(thr, i);
26704 duk_put_prop_index(thr, -3, (duk_uarridx_t) (len + (duk_uint32_t) i));
26705 }
26706 len += (duk_uint32_t) n;
26707
26708 duk_push_u32(thr, len);
26709 duk_dup_top(thr);
26711
26712 /* [ arg1 ... argN obj length new_length ] */
26713 return 1;
26715
26716/*
26717 * sort()
26718 *
26719 * Currently qsort with random pivot. This is now really, really slow,
26720 * because there is no fast path for array parts.
26721 *
26722 * Signed indices are used because qsort() leaves and degenerate cases
26723 * may use a negative offset.
26724 */
26725
26727 duk_bool_t have1, have2;
26728 duk_bool_t undef1, undef2;
26729 duk_small_int_t ret;
26730 duk_idx_t idx_obj = 1; /* fixed offsets in valstack */
26731 duk_idx_t idx_fn = 0;
26732 duk_hstring *h1, *h2;
26733
26734 /* Fast exit if indices are identical. This is valid for a non-existent property,
26735 * for an undefined value, and almost always for ToString() coerced comparison of
26736 * arbitrary values (corner cases where this is not the case include e.g. a an
26737 * object with varying ToString() coercion).
26738 *
26739 * The specification does not prohibit "caching" of values read from the array, so
26740 * assuming equality for comparing an index with itself falls into the category of
26741 * "caching".
26742 *
26743 * Also, compareFn may be inconsistent, so skipping a call to compareFn here may
26744 * have an effect on the final result. The specification does not require any
26745 * specific behavior for inconsistent compare functions, so again, this fast path
26746 * is OK.
26747 */
26748
26749 if (idx1 == idx2) {
26750 DUK_DDD(DUK_DDDPRINT("duk__array_sort_compare: idx1=%ld, idx2=%ld -> indices identical, quick exit",
26751 (long) idx1,
26752 (long) idx2));
26753 return 0;
26754 }
26755
26756 have1 = duk_get_prop_index(thr, idx_obj, (duk_uarridx_t) idx1);
26757 have2 = duk_get_prop_index(thr, idx_obj, (duk_uarridx_t) idx2);
26758
26759 DUK_DDD(DUK_DDDPRINT("duk__array_sort_compare: idx1=%ld, idx2=%ld, have1=%ld, have2=%ld, val1=%!T, val2=%!T",
26760 (long) idx1,
26761 (long) idx2,
26762 (long) have1,
26763 (long) have2,
26764 (duk_tval *) duk_get_tval(thr, -2),
26765 (duk_tval *) duk_get_tval(thr, -1)));
26766
26767 if (have1) {
26768 if (have2) {
26769 ;
26770 } else {
26771 ret = -1;
26772 goto pop_ret;
26773 }
26774 } else {
26775 if (have2) {
26776 ret = 1;
26777 goto pop_ret;
26778 } else {
26779 ret = 0;
26780 goto pop_ret;
26781 }
26782 }
26783
26784 undef1 = duk_is_undefined(thr, -2);
26785 undef2 = duk_is_undefined(thr, -1);
26786 if (undef1) {
26787 if (undef2) {
26788 ret = 0;
26789 goto pop_ret;
26790 } else {
26791 ret = 1;
26792 goto pop_ret;
26793 }
26794 } else {
26795 if (undef2) {
26796 ret = -1;
26797 goto pop_ret;
26798 } else {
26799 ;
26800 }
26801 }
26802
26803 if (!duk_is_undefined(thr, idx_fn)) {
26804 duk_double_t d;
26805
26806 /* No need to check callable; duk_call() will do that. */
26807 duk_dup(thr, idx_fn); /* -> [ ... x y fn ] */
26808 duk_insert(thr, -3); /* -> [ ... fn x y ] */
26809 duk_call(thr, 2); /* -> [ ... res ] */
26810
26811 /* ES5 is a bit vague about what to do if the return value is
26812 * not a number. ES2015 provides a concrete description:
26813 * http://www.ecma-international.org/ecma-262/6.0/#sec-sortcompare.
26814 */
26815
26816 d = duk_to_number_m1(thr);
26817 if (d < 0.0) {
26818 ret = -1;
26819 } else if (d > 0.0) {
26820 ret = 1;
26821 } else {
26822 /* Because NaN compares to false, NaN is handled here
26823 * without an explicit check above.
26824 */
26825 ret = 0;
26826 }
26827
26829 DUK_DDD(DUK_DDDPRINT("-> result %ld (from comparefn, after coercion)", (long) ret));
26830 return ret;
26831 }
26832
26833 /* string compare is the default (a bit oddly) */
26834
26835 /* XXX: any special handling for plain array; causes repeated coercion now? */
26836 h1 = duk_to_hstring(thr, -2);
26837 h2 = duk_to_hstring_m1(thr);
26838 DUK_ASSERT(h1 != NULL);
26839 DUK_ASSERT(h2 != NULL);
26840
26841 ret = duk_js_string_compare(h1, h2); /* retval is directly usable */
26842 goto pop_ret;
26843
26844pop_ret:
26845 duk_pop_2_unsafe(thr);
26846 DUK_DDD(DUK_DDDPRINT("-> result %ld", (long) ret));
26847 return ret;
26848}
26849
26851 duk_bool_t have_l, have_r;
26852 duk_idx_t idx_obj = 1; /* fixed offset in valstack */
26853
26854 if (l == r) {
26855 return;
26856 }
26857
26858 /* swap elements; deal with non-existent elements correctly */
26859 have_l = duk_get_prop_index(thr, idx_obj, (duk_uarridx_t) l);
26860 have_r = duk_get_prop_index(thr, idx_obj, (duk_uarridx_t) r);
26861
26862 if (have_r) {
26863 /* right exists, [[Put]] regardless whether or not left exists */
26864 duk_put_prop_index(thr, idx_obj, (duk_uarridx_t) l);
26865 } else {
26866 duk_del_prop_index(thr, idx_obj, (duk_uarridx_t) l);
26867 duk_pop_undefined(thr);
26868 }
26869
26870 if (have_l) {
26871 duk_put_prop_index(thr, idx_obj, (duk_uarridx_t) r);
26872 } else {
26873 duk_del_prop_index(thr, idx_obj, (duk_uarridx_t) r);
26874 duk_pop_undefined(thr);
26875 }
26876}
26877
26878#if defined(DUK_USE_DEBUG_LEVEL) && (DUK_USE_DEBUG_LEVEL >= 2)
26879/* Debug print which visualizes the qsort partitioning process. */
26880DUK_LOCAL void duk__debuglog_qsort_state(duk_hthread *thr, duk_int_t lo, duk_int_t hi, duk_int_t pivot) {
26881 char buf[4096];
26882 char *ptr = buf;
26883 duk_int_t i, n;
26884 n = (duk_int_t) duk_get_length(thr, 1);
26885 if (n > 4000) {
26886 n = 4000;
26887 }
26888 *ptr++ = '[';
26889 for (i = 0; i < n; i++) {
26890 if (i == pivot) {
26891 *ptr++ = '|';
26892 } else if (i == lo) {
26893 *ptr++ = '<';
26894 } else if (i == hi) {
26895 *ptr++ = '>';
26896 } else if (i >= lo && i <= hi) {
26897 *ptr++ = '-';
26898 } else {
26899 *ptr++ = ' ';
26900 }
26901 }
26902 *ptr++ = ']';
26903 *ptr++ = '\0';
26904
26905 DUK_DDD(DUK_DDDPRINT("%s (lo=%ld, hi=%ld, pivot=%ld)", (const char *) buf, (long) lo, (long) hi, (long) pivot));
26906}
26907#endif
26908
26910 duk_int_t p, l, r;
26911
26912 /* The lo/hi indices may be crossed and hi < 0 is possible at entry. */
26913
26914 DUK_DDD(DUK_DDDPRINT("duk__array_qsort: lo=%ld, hi=%ld, obj=%!T", (long) lo, (long) hi, (duk_tval *) duk_get_tval(thr, 1)));
26915
26916 DUK_ASSERT_TOP(thr, 3);
26917
26918 /* In some cases it may be that lo > hi, or hi < 0; these
26919 * degenerate cases happen e.g. for empty arrays, and in
26920 * recursion leaves.
26921 */
26922
26923 /* trivial cases */
26924 if (hi - lo < 1) {
26925 DUK_DDD(DUK_DDDPRINT("degenerate case, return immediately"));
26926 return;
26927 }
26928 DUK_ASSERT(hi > lo);
26929 DUK_ASSERT(hi - lo + 1 >= 2);
26930
26931 /* randomized pivot selection */
26932 p = lo + (duk_int_t) (duk_util_get_random_double(thr) * (duk_double_t) (hi - lo + 1));
26933 DUK_ASSERT(p >= lo && p <= hi);
26934 DUK_DDD(DUK_DDDPRINT("lo=%ld, hi=%ld, chose pivot p=%ld", (long) lo, (long) hi, (long) p));
26935
26936 /* move pivot out of the way */
26937 duk__array_sort_swap(thr, p, lo);
26938 p = lo;
26939 DUK_DDD(DUK_DDDPRINT("pivot moved out of the way: %!T", (duk_tval *) duk_get_tval(thr, 1)));
26940
26941 l = lo + 1;
26942 r = hi;
26943 for (;;) {
26944 /* find elements to swap */
26945 for (;;) {
26946 DUK_DDD(DUK_DDDPRINT("left scan: l=%ld, r=%ld, p=%ld", (long) l, (long) r, (long) p));
26947 if (l >= hi) {
26948 break;
26949 }
26950 if (duk__array_sort_compare(thr, l, p) >= 0) { /* !(l < p) */
26951 break;
26952 }
26953 l++;
26954 }
26955 for (;;) {
26956 DUK_DDD(DUK_DDDPRINT("right scan: l=%ld, r=%ld, p=%ld", (long) l, (long) r, (long) p));
26957 if (r <= lo) {
26958 break;
26959 }
26960 if (duk__array_sort_compare(thr, p, r) >= 0) { /* !(p < r) */
26961 break;
26962 }
26963 r--;
26964 }
26965 if (l >= r) {
26966 goto done;
26967 }
26968 DUK_ASSERT(l < r);
26969
26970 DUK_DDD(DUK_DDDPRINT("swap %ld and %ld", (long) l, (long) r));
26971
26972 duk__array_sort_swap(thr, l, r);
26973
26974 DUK_DDD(DUK_DDDPRINT("after swap: %!T", (duk_tval *) duk_get_tval(thr, 1)));
26975 l++;
26976 r--;
26977 }
26978done:
26979 /* Note that 'l' and 'r' may cross, i.e. r < l */
26980 DUK_ASSERT(l >= lo && l <= hi);
26981 DUK_ASSERT(r >= lo && r <= hi);
26982
26983 /* XXX: there's no explicit recursion bound here now. For the average
26984 * qsort recursion depth O(log n) that's not really necessary: e.g. for
26985 * 2**32 recursion depth would be about 32 which is OK. However, qsort
26986 * worst case recursion depth is O(n) which may be a problem.
26987 */
26988
26989 /* move pivot to its final place */
26990 DUK_DDD(DUK_DDDPRINT("before final pivot swap: %!T", (duk_tval *) duk_get_tval(thr, 1)));
26991 duk__array_sort_swap(thr, lo, r);
26992
26993#if defined(DUK_USE_DEBUG_LEVEL) && (DUK_USE_DEBUG_LEVEL >= 2)
26994 duk__debuglog_qsort_state(thr, lo, hi, r);
26995#endif
26996
26997 DUK_DDD(DUK_DDDPRINT("recurse: pivot=%ld, obj=%!T", (long) r, (duk_tval *) duk_get_tval(thr, 1)));
26998 duk__array_qsort(thr, lo, r - 1);
26999 duk__array_qsort(thr, r + 1, hi);
27000}
27001
27003 duk_uint32_t len;
27004
27005 /* XXX: len >= 0x80000000 won't work below because a signed type
27006 * is needed by qsort.
27007 */
27009
27010 /* stack[0] = compareFn
27011 * stack[1] = ToObject(this)
27012 * stack[2] = ToUint32(length)
27013 */
27014
27015 if (len > 0) {
27016 /* avoid degenerate cases, so that (len - 1) won't underflow */
27017 duk__array_qsort(thr, (duk_int_t) 0, (duk_int_t) (len - 1));
27018 }
27019
27020 DUK_ASSERT_TOP(thr, 3);
27022 return 1; /* return ToObject(this) */
27023}
27024
27025/*
27026 * splice()
27027 */
27028
27029/* XXX: this compiles to over 500 bytes now, even without special handling
27030 * for an array part. Uses signed ints so does not handle full array range correctly.
27031 */
27032
27033/* XXX: can shift() / unshift() use the same helper?
27034 * shift() is (close to?) <--> splice(0, 1)
27035 * unshift is (close to?) <--> splice(0, 0, [items])?
27036 */
27037
27039 duk_idx_t nargs;
27040 duk_uint32_t len_u32;
27041 duk_int_t len;
27042 duk_bool_t have_delcount;
27043 duk_int_t item_count;
27044 duk_int_t act_start;
27045 duk_int_t del_count;
27046 duk_int_t i, n;
27047
27048 DUK_UNREF(have_delcount);
27049
27050 nargs = duk_get_top(thr);
27051 if (nargs < 2) {
27052 duk_set_top(thr, 2);
27053 nargs = 2;
27054 have_delcount = 0;
27055 } else {
27056 have_delcount = 1;
27057 }
27058
27059 /* XXX: len >= 0x80000000 won't work below because we need to be
27060 * able to represent -len.
27061 */
27063 len = (duk_int_t) len_u32;
27064 DUK_ASSERT(len >= 0);
27065
27066 act_start = duk_to_int_clamped(thr, 0, -len, len);
27067 if (act_start < 0) {
27068 act_start = len + act_start;
27069 }
27070 DUK_ASSERT(act_start >= 0 && act_start <= len);
27071
27072#if defined(DUK_USE_NONSTD_ARRAY_SPLICE_DELCOUNT)
27073 if (have_delcount) {
27074#endif
27075 del_count = duk_to_int_clamped(thr, 1, 0, len - act_start);
27076#if defined(DUK_USE_NONSTD_ARRAY_SPLICE_DELCOUNT)
27077 } else {
27078 /* E5.1 standard behavior when deleteCount is not given would be
27079 * to treat it just like if 'undefined' was given, which coerces
27080 * ultimately to 0. Real world behavior is to splice to the end
27081 * of array, see test-bi-array-proto-splice-no-delcount.js.
27082 */
27083 del_count = len - act_start;
27084 }
27085#endif
27086
27087 DUK_ASSERT(nargs >= 2);
27088 item_count = (duk_int_t) (nargs - 2);
27089
27090 DUK_ASSERT(del_count >= 0 && del_count <= len - act_start);
27091 DUK_ASSERT(del_count + act_start <= len);
27092
27093 /* For now, restrict result array into 32-bit length range. */
27094 if (((duk_double_t) len) - ((duk_double_t) del_count) + ((duk_double_t) item_count) > (duk_double_t) DUK_UINT32_MAX) {
27095 DUK_D(DUK_DPRINT("Array.prototype.splice() would go beyond 32-bit length, throw"));
27097 }
27098
27099 duk_push_array(thr);
27100
27101 /* stack[0] = start
27102 * stack[1] = deleteCount
27103 * stack[2...nargs-1] = items
27104 * stack[nargs] = ToObject(this) -3
27105 * stack[nargs+1] = ToUint32(length) -2
27106 * stack[nargs+2] = result array -1
27107 */
27108
27109 DUK_ASSERT_TOP(thr, nargs + 3);
27110
27111 /* Step 9: copy elements-to-be-deleted into the result array */
27112
27113 for (i = 0; i < del_count; i++) {
27114 if (duk_get_prop_index(thr, -3, (duk_uarridx_t) (act_start + i))) {
27115 duk_xdef_prop_index_wec(thr, -2, (duk_uarridx_t) i); /* throw flag irrelevant (false in std alg) */
27116 } else {
27117 duk_pop_undefined(thr);
27118 }
27119 }
27120 duk_push_u32(thr, (duk_uint32_t) del_count);
27122
27123 /* Steps 12 and 13: reorganize elements to make room for itemCount elements */
27124
27125 if (item_count < del_count) {
27126 /* [ A B C D E F G H ] rel_index = 2, del_count 3, item count 1
27127 * -> [ A B F G H ] (conceptual intermediate step)
27128 * -> [ A B . F G H ] (placeholder marked)
27129 * [ A B C F G H ] (actual result at this point, C will be replaced)
27130 */
27131
27132 DUK_ASSERT_TOP(thr, nargs + 3);
27133
27134 n = len - del_count;
27135 for (i = act_start; i < n; i++) {
27136 if (duk_get_prop_index(thr, -3, (duk_uarridx_t) (i + del_count))) {
27137 duk_put_prop_index(thr, -4, (duk_uarridx_t) (i + item_count));
27138 } else {
27139 duk_pop_undefined(thr);
27140 duk_del_prop_index(thr, -3, (duk_uarridx_t) (i + item_count));
27141 }
27142 }
27143
27144 DUK_ASSERT_TOP(thr, nargs + 3);
27145
27146 /* loop iterator init and limit changed from standard algorithm */
27147 n = len - del_count + item_count;
27148 for (i = len - 1; i >= n; i--) {
27149 duk_del_prop_index(thr, -3, (duk_uarridx_t) i);
27150 }
27151
27152 DUK_ASSERT_TOP(thr, nargs + 3);
27153 } else if (item_count > del_count) {
27154 /* [ A B C D E F G H ] rel_index = 2, del_count 3, item count 4
27155 * -> [ A B F G H ] (conceptual intermediate step)
27156 * -> [ A B . . . . F G H ] (placeholder marked)
27157 * [ A B C D E F F G H ] (actual result at this point)
27158 */
27159
27160 DUK_ASSERT_TOP(thr, nargs + 3);
27161
27162 /* loop iterator init and limit changed from standard algorithm */
27163 for (i = len - del_count - 1; i >= act_start; i--) {
27164 if (duk_get_prop_index(thr, -3, (duk_uarridx_t) (i + del_count))) {
27165 duk_put_prop_index(thr, -4, (duk_uarridx_t) (i + item_count));
27166 } else {
27167 duk_pop_undefined(thr);
27168 duk_del_prop_index(thr, -3, (duk_uarridx_t) (i + item_count));
27169 }
27170 }
27171
27172 DUK_ASSERT_TOP(thr, nargs + 3);
27173 } else {
27174 /* [ A B C D E F G H ] rel_index = 2, del_count 3, item count 3
27175 * -> [ A B F G H ] (conceptual intermediate step)
27176 * -> [ A B . . . F G H ] (placeholder marked)
27177 * [ A B C D E F G H ] (actual result at this point)
27178 */
27179 }
27180 DUK_ASSERT_TOP(thr, nargs + 3);
27181
27182 /* Step 15: insert itemCount elements into the hole made above */
27183
27184 for (i = 0; i < item_count; i++) {
27185 duk_dup(thr, i + 2); /* args start at index 2 */
27186 duk_put_prop_index(thr, -4, (duk_uarridx_t) (act_start + i));
27187 }
27188
27189 /* Step 16: update length; note that the final length may be above 32 bit range
27190 * (but we checked above that this isn't the case here)
27191 */
27192
27193 duk_push_u32(thr, (duk_uint32_t) (len - del_count + item_count));
27195
27196 /* result array is already at the top of stack */
27197 DUK_ASSERT_TOP(thr, nargs + 3);
27198 return 1;
27199}
27200
27201/*
27202 * reverse()
27203 */
27204
27206 duk_uint32_t len;
27207 duk_uint32_t middle;
27208 duk_uint32_t lower, upper;
27209 duk_bool_t have_lower, have_upper;
27210
27211 len = duk__push_this_obj_len_u32(thr);
27212 middle = len / 2;
27213
27214 /* If len <= 1, middle will be 0 and for-loop bails out
27215 * immediately (0 < 0 -> false).
27216 */
27217
27218 for (lower = 0; lower < middle; lower++) {
27219 DUK_ASSERT(len >= 2);
27220 DUK_ASSERT_TOP(thr, 2);
27221
27222 DUK_ASSERT(len >= lower + 1);
27223 upper = len - lower - 1;
27224
27225 have_lower = duk_get_prop_index(thr, -2, (duk_uarridx_t) lower);
27226 have_upper = duk_get_prop_index(thr, -3, (duk_uarridx_t) upper);
27227
27228 /* [ ToObject(this) ToUint32(length) lowerValue upperValue ] */
27229
27230 if (have_upper) {
27231 duk_put_prop_index(thr, -4, (duk_uarridx_t) lower);
27232 } else {
27233 duk_del_prop_index(thr, -4, (duk_uarridx_t) lower);
27234 duk_pop_undefined(thr);
27235 }
27236
27237 if (have_lower) {
27238 duk_put_prop_index(thr, -3, (duk_uarridx_t) upper);
27239 } else {
27240 duk_del_prop_index(thr, -3, (duk_uarridx_t) upper);
27241 duk_pop_undefined(thr);
27242 }
27243
27245 }
27246
27247 DUK_ASSERT_TOP(thr, 2);
27248 duk_pop_unsafe(thr); /* -> [ ToObject(this) ] */
27249 return 1;
27250}
27251
27252/*
27253 * slice()
27254 */
27255
27257 duk_uint32_t len_u32;
27258 duk_int_t len;
27259 duk_int_t start, end;
27260 duk_int_t i;
27261 duk_uarridx_t idx;
27262 duk_uint32_t res_length = 0;
27263
27264 /* XXX: len >= 0x80000000 won't work below because we need to be
27265 * able to represent -len.
27266 */
27268 len = (duk_int_t) len_u32;
27269 DUK_ASSERT(len >= 0);
27270
27271 duk_push_array(thr);
27272
27273 /* stack[0] = start
27274 * stack[1] = end
27275 * stack[2] = ToObject(this)
27276 * stack[3] = ToUint32(length)
27277 * stack[4] = result array
27278 */
27279
27280 start = duk_to_int_clamped(thr, 0, -len, len);
27281 if (start < 0) {
27282 start = len + start;
27283 }
27284 /* XXX: could duk_is_undefined() provide defaulting undefined to 'len'
27285 * (the upper limit)?
27286 */
27287 if (duk_is_undefined(thr, 1)) {
27288 end = len;
27289 } else {
27290 end = duk_to_int_clamped(thr, 1, -len, len);
27291 if (end < 0) {
27292 end = len + end;
27293 }
27294 }
27295 DUK_ASSERT(start >= 0 && start <= len);
27296 DUK_ASSERT(end >= 0 && end <= len);
27297
27298 idx = 0;
27299 for (i = start; i < end; i++) {
27300 DUK_ASSERT_TOP(thr, 5);
27301 if (duk_get_prop_index(thr, 2, (duk_uarridx_t) i)) {
27302 duk_xdef_prop_index_wec(thr, 4, idx);
27303 res_length = idx + 1;
27304 } else {
27305 duk_pop_undefined(thr);
27306 }
27307 idx++;
27308 DUK_ASSERT_TOP(thr, 5);
27309 }
27311 duk_push_u32(thr, res_length);
27313
27314 DUK_ASSERT_TOP(thr, 5);
27315 return 1;
27316}
27317
27318/*
27319 * shift()
27320 */
27321
27323 duk_uint32_t len;
27324 duk_uint32_t i;
27325
27326 len = duk__push_this_obj_len_u32(thr);
27327 if (len == 0) {
27328 duk_push_int(thr, 0);
27330 return 0;
27331 }
27332
27333 duk_get_prop_index(thr, 0, 0);
27334
27335 /* stack[0] = object (this)
27336 * stack[1] = ToUint32(length)
27337 * stack[2] = elem at index 0 (retval)
27338 */
27339
27340 for (i = 1; i < len; i++) {
27341 DUK_ASSERT_TOP(thr, 3);
27342 if (duk_get_prop_index(thr, 0, (duk_uarridx_t) i)) {
27343 /* fromPresent = true */
27344 duk_put_prop_index(thr, 0, (duk_uarridx_t) (i - 1));
27345 } else {
27346 /* fromPresent = false */
27347 duk_del_prop_index(thr, 0, (duk_uarridx_t) (i - 1));
27348 duk_pop_undefined(thr);
27349 }
27350 }
27351 duk_del_prop_index(thr, 0, (duk_uarridx_t) (len - 1));
27353 duk_push_u32(thr, (duk_uint32_t) (len - 1));
27355
27356 DUK_ASSERT_TOP(thr, 3);
27357 return 1;
27358}
27359
27360/*
27361 * unshift()
27362 */
27363
27365 duk_idx_t nargs;
27366 duk_uint32_t len;
27367 duk_uint32_t i;
27368
27369 nargs = duk_get_top(thr);
27370 len = duk__push_this_obj_len_u32(thr);
27371
27372 /* stack[0...nargs-1] = unshift args (vararg)
27373 * stack[nargs] = ToObject(this)
27374 * stack[nargs+1] = ToUint32(length)
27375 */
27376
27377 DUK_ASSERT_TOP(thr, nargs + 2);
27378
27379 /* Note: unshift() may operate on indices above unsigned 32-bit range
27380 * and the final length may be >= 2**32. However, we restrict the
27381 * final result to 32-bit range for practicality.
27382 */
27383
27384 if (len + (duk_uint32_t) nargs < len) {
27385 DUK_D(DUK_DPRINT("Array.prototype.unshift() would go beyond 32-bit length, throw"));
27387 }
27388
27389 i = len;
27390 while (i > 0) {
27391 DUK_ASSERT_TOP(thr, nargs + 2);
27392 i--;
27393 /* k+argCount-1; note that may be above 32-bit range */
27394
27395 if (duk_get_prop_index(thr, -2, (duk_uarridx_t) i)) {
27396 /* fromPresent = true */
27397 /* [ ... ToObject(this) ToUint32(length) val ] */
27399 thr,
27400 -3,
27401 (duk_uarridx_t) (i + (duk_uint32_t) nargs)); /* -> [ ... ToObject(this) ToUint32(length) ] */
27402 } else {
27403 /* fromPresent = false */
27404 /* [ ... ToObject(this) ToUint32(length) val ] */
27405 duk_pop_undefined(thr);
27407 thr,
27408 -2,
27409 (duk_uarridx_t) (i + (duk_uint32_t) nargs)); /* -> [ ... ToObject(this) ToUint32(length) ] */
27410 }
27411 DUK_ASSERT_TOP(thr, nargs + 2);
27412 }
27413
27414 for (i = 0; i < (duk_uint32_t) nargs; i++) {
27415 DUK_ASSERT_TOP(thr, nargs + 2);
27416 duk_dup(thr, (duk_idx_t) i); /* -> [ ... ToObject(this) ToUint32(length) arg[i] ] */
27417 duk_put_prop_index(thr, -3, (duk_uarridx_t) i);
27418 DUK_ASSERT_TOP(thr, nargs + 2);
27419 }
27421 DUK_ASSERT_TOP(thr, nargs + 2);
27422 duk_push_u32(thr, len + (duk_uint32_t) nargs);
27423 duk_dup_top(thr); /* -> [ ... ToObject(this) ToUint32(length) final_len final_len ] */
27425 return 1;
27426}
27427
27428/*
27429 * indexOf(), lastIndexOf()
27430 */
27431
27433 duk_idx_t nargs;
27434 duk_int_t i, len;
27435 duk_int_t from_idx;
27436 duk_small_int_t idx_step = duk_get_current_magic(thr); /* idx_step is +1 for indexOf, -1 for lastIndexOf */
27437
27438 /* lastIndexOf() needs to be a vararg function because we must distinguish
27439 * between an undefined fromIndex and a "not given" fromIndex; indexOf() is
27440 * made vararg for symmetry although it doesn't strictly need to be.
27441 */
27442
27443 nargs = duk_get_top(thr);
27444 duk_set_top(thr, 2);
27445
27446 /* XXX: must be able to represent -len */
27448 if (len == 0) {
27449 goto not_found;
27450 }
27451
27452 /* Index clamping is a bit tricky, we must ensure that we'll only iterate
27453 * through elements that exist and that the specific requirements from E5.1
27454 * Sections 15.4.4.14 and 15.4.4.15 are fulfilled; especially:
27455 *
27456 * - indexOf: clamp to [-len,len], negative handling -> [0,len],
27457 * if clamped result is len, for-loop bails out immediately
27458 *
27459 * - lastIndexOf: clamp to [-len-1, len-1], negative handling -> [-1, len-1],
27460 * if clamped result is -1, for-loop bails out immediately
27461 *
27462 * If fromIndex is not given, ToInteger(undefined) = 0, which is correct
27463 * for indexOf() but incorrect for lastIndexOf(). Hence special handling,
27464 * and why lastIndexOf() needs to be a vararg function.
27465 */
27466
27467 if (nargs >= 2) {
27468 /* indexOf: clamp fromIndex to [-len, len]
27469 * (if fromIndex == len, for-loop terminates directly)
27470 *
27471 * lastIndexOf: clamp fromIndex to [-len - 1, len - 1]
27472 * (if clamped to -len-1 -> fromIndex becomes -1, terminates for-loop directly)
27473 */
27474 from_idx = duk_to_int_clamped(thr, 1, (idx_step > 0 ? -len : -len - 1), (idx_step > 0 ? len : len - 1));
27475 if (from_idx < 0) {
27476 /* for lastIndexOf, result may be -1 (mark immediate termination) */
27477 from_idx = len + from_idx;
27478 }
27479 } else {
27480 /* for indexOf, ToInteger(undefined) would be 0, i.e. correct, but
27481 * handle both indexOf and lastIndexOf specially here.
27482 */
27483 if (idx_step > 0) {
27484 from_idx = 0;
27485 } else {
27486 from_idx = len - 1;
27487 }
27488 }
27489
27490 /* stack[0] = searchElement
27491 * stack[1] = fromIndex
27492 * stack[2] = object
27493 * stack[3] = length (not needed, but not popped above)
27494 */
27495
27496 for (i = from_idx; i >= 0 && i < len; i += idx_step) {
27497 DUK_ASSERT_TOP(thr, 4);
27498
27499 if (duk_get_prop_index(thr, 2, (duk_uarridx_t) i)) {
27500 DUK_ASSERT_TOP(thr, 5);
27501 if (duk_strict_equals(thr, 0, 4)) {
27502 duk_push_int(thr, i);
27503 return 1;
27504 }
27505 }
27506
27510not_found:
27512 return 1;
27513}
27514
27515/*
27516 * every(), some(), forEach(), map(), filter()
27517 */
27519#define DUK__ITER_EVERY 0
27520#define DUK__ITER_SOME 1
27521#define DUK__ITER_FOREACH 2
27522#define DUK__ITER_MAP 3
27523#define DUK__ITER_FILTER 4
27524
27525/* XXX: This helper is a bit awkward because the handling for the different iteration
27526 * callers is quite different. This now compiles to a bit less than 500 bytes, so with
27527 * 5 callers the net result is about 100 bytes / caller.
27528 */
27529
27531 duk_uint32_t len;
27532 duk_uint32_t i;
27533 duk_uarridx_t k;
27534 duk_bool_t bval;
27535 duk_small_int_t iter_type = duk_get_current_magic(thr);
27536 duk_uint32_t res_length = 0;
27537
27538 /* each call this helper serves has nargs==2 */
27539 DUK_ASSERT_TOP(thr, 2);
27540
27541 len = duk__push_this_obj_len_u32(thr);
27542 duk_require_callable(thr, 0);
27543 /* if thisArg not supplied, behave as if undefined was supplied */
27544
27545 if (iter_type == DUK__ITER_MAP || iter_type == DUK__ITER_FILTER) {
27546 duk_push_array(thr);
27547 } else {
27548 duk_push_undefined(thr);
27549 }
27550
27551 /* stack[0] = callback
27552 * stack[1] = thisArg
27553 * stack[2] = object
27554 * stack[3] = ToUint32(length) (unused, but avoid unnecessary pop)
27555 * stack[4] = result array (or undefined)
27556 */
27557
27558 k = 0; /* result index for filter() */
27559 for (i = 0; i < len; i++) {
27560 DUK_ASSERT_TOP(thr, 5);
27561
27562 if (!duk_get_prop_index(thr, 2, (duk_uarridx_t) i)) {
27563 /* For 'map' trailing missing elements don't invoke the
27564 * callback but count towards the result length.
27565 */
27566 if (iter_type == DUK__ITER_MAP) {
27567 res_length = i + 1;
27568 }
27569 duk_pop_undefined(thr);
27570 continue;
27571 }
27572
27573 /* The original value needs to be preserved for filter(), hence
27574 * this funny order. We can't re-get the value because of side
27575 * effects.
27576 */
27577
27578 duk_dup_0(thr);
27579 duk_dup_1(thr);
27580 duk_dup_m3(thr);
27581 duk_push_u32(thr, i);
27582 duk_dup_2(thr); /* [ ... val callback thisArg val i obj ] */
27583 duk_call_method(thr, 3); /* -> [ ... val retval ] */
27584
27585 switch (iter_type) {
27586 case DUK__ITER_EVERY:
27587 bval = duk_to_boolean(thr, -1);
27588 if (!bval) {
27589 /* stack top contains 'false' */
27590 return 1;
27591 }
27592 break;
27593 case DUK__ITER_SOME:
27594 bval = duk_to_boolean(thr, -1);
27595 if (bval) {
27596 /* stack top contains 'true' */
27597 return 1;
27598 }
27599 break;
27600 case DUK__ITER_FOREACH:
27601 /* nop */
27602 break;
27603 case DUK__ITER_MAP:
27604 duk_dup_top(thr);
27605 duk_xdef_prop_index_wec(thr, 4, (duk_uarridx_t) i); /* retval to result[i] */
27606 res_length = i + 1;
27607 break;
27608 case DUK__ITER_FILTER:
27609 bval = duk_to_boolean(thr, -1);
27610 if (bval) {
27611 duk_dup_m2(thr); /* orig value */
27613 k++;
27614 res_length = k;
27615 }
27616 break;
27617 default:
27619 break;
27620 }
27621 duk_pop_2_unsafe(thr);
27622
27623 DUK_ASSERT_TOP(thr, 5);
27624 }
27625
27626 switch (iter_type) {
27627 case DUK__ITER_EVERY:
27628 duk_push_true(thr);
27629 break;
27630 case DUK__ITER_SOME:
27631 duk_push_false(thr);
27632 break;
27633 case DUK__ITER_FOREACH:
27634 duk_push_undefined(thr);
27635 break;
27636 case DUK__ITER_MAP:
27637 case DUK__ITER_FILTER:
27638 DUK_ASSERT_TOP(thr, 5);
27639 DUK_ASSERT(duk_is_array(thr, -1)); /* topmost element is the result array already */
27640 duk_push_u32(thr, res_length);
27642 break;
27643 default:
27645 break;
27646 }
27647
27648 return 1;
27649}
27650
27651/*
27652 * reduce(), reduceRight()
27653 */
27654
27656 duk_idx_t nargs;
27657 duk_bool_t have_acc;
27658 duk_uint32_t i, len;
27659 duk_small_int_t idx_step = duk_get_current_magic(thr); /* idx_step is +1 for reduce, -1 for reduceRight */
27660
27661 /* We're a varargs function because we need to detect whether
27662 * initialValue was given or not.
27663 */
27664 nargs = duk_get_top(thr);
27665 DUK_DDD(DUK_DDDPRINT("nargs=%ld", (long) nargs));
27666
27667 duk_set_top(thr, 2);
27668 len = duk__push_this_obj_len_u32(thr);
27669 duk_require_callable(thr, 0);
27670
27671 /* stack[0] = callback fn
27672 * stack[1] = initialValue
27673 * stack[2] = object (coerced this)
27674 * stack[3] = length (not needed, but not popped above)
27675 * stack[4] = accumulator
27676 */
27677
27678 have_acc = 0;
27679 if (nargs >= 2) {
27680 duk_dup_1(thr);
27681 have_acc = 1;
27682 }
27683 DUK_DDD(DUK_DDDPRINT("have_acc=%ld, acc=%!T", (long) have_acc, (duk_tval *) duk_get_tval(thr, 3)));
27684
27685 /* For len == 0, i is initialized to len - 1 which underflows.
27686 * The condition (i < len) will then exit the for-loop on the
27687 * first round which is correct. Similarly, loop termination
27688 * happens by i underflowing.
27689 */
27690
27691 for (i = (idx_step >= 0 ? 0 : len - 1); i < len; /* i >= 0 would always be true */
27692 i += (duk_uint32_t) idx_step) {
27693 DUK_DDD(DUK_DDDPRINT("i=%ld, len=%ld, have_acc=%ld, top=%ld, acc=%!T",
27694 (long) i,
27695 (long) len,
27696 (long) have_acc,
27697 (long) duk_get_top(thr),
27698 (duk_tval *) duk_get_tval(thr, 4)));
27699
27700 DUK_ASSERT((have_acc && duk_get_top(thr) == 5) || (!have_acc && duk_get_top(thr) == 4));
27701
27702 if (!duk_has_prop_index(thr, 2, (duk_uarridx_t) i)) {
27703 continue;
27704 }
27705
27706 if (!have_acc) {
27707 DUK_ASSERT_TOP(thr, 4);
27708 duk_get_prop_index(thr, 2, (duk_uarridx_t) i);
27709 have_acc = 1;
27710 DUK_ASSERT_TOP(thr, 5);
27711 } else {
27712 DUK_ASSERT_TOP(thr, 5);
27713 duk_dup_0(thr);
27714 duk_dup(thr, 4);
27715 duk_get_prop_index(thr, 2, (duk_uarridx_t) i);
27716 duk_push_u32(thr, i);
27717 duk_dup_2(thr);
27718 DUK_DDD(DUK_DDDPRINT("calling reduce function: func=%!T, prev=%!T, curr=%!T, idx=%!T, obj=%!T",
27719 (duk_tval *) duk_get_tval(thr, -5),
27720 (duk_tval *) duk_get_tval(thr, -4),
27721 (duk_tval *) duk_get_tval(thr, -3),
27722 (duk_tval *) duk_get_tval(thr, -2),
27723 (duk_tval *) duk_get_tval(thr, -1)));
27724 duk_call(thr, 4);
27725 DUK_DDD(DUK_DDDPRINT("-> result: %!T", (duk_tval *) duk_get_tval(thr, -1)));
27726 duk_replace(thr, 4);
27727 DUK_ASSERT_TOP(thr, 5);
27728 }
27729 }
27730
27731 if (!have_acc) {
27733 }
27734
27735 DUK_ASSERT_TOP(thr, 5);
27736 return 1;
27737}
27738
27739#endif /* DUK_USE_ARRAY_BUILTIN */
27740
27741/* automatic undefs */
27742#undef DUK__ARRAY_MID_JOIN_LIMIT
27743#undef DUK__ITER_EVERY
27744#undef DUK__ITER_FILTER
27745#undef DUK__ITER_FOREACH
27746#undef DUK__ITER_MAP
27747#undef DUK__ITER_SOME
27748/*
27749 * Boolean built-ins
27750 */
27751
27752/* #include duk_internal.h -> already included */
27753
27754#if defined(DUK_USE_BOOLEAN_BUILTIN)
27755
27756/* Shared helper to provide toString() and valueOf(). Checks 'this', gets
27757 * the primitive value to stack top, and optionally coerces with ToString().
27758 */
27760 duk_tval *tv;
27761 duk_hobject *h;
27762 duk_small_int_t coerce_tostring = duk_get_current_magic(thr);
27763
27764 /* XXX: there is room to use a shared helper here, many built-ins
27765 * check the 'this' type, and if it's an object, check its class,
27766 * then get its internal value, etc.
27767 */
27768
27769 duk_push_this(thr);
27770 tv = duk_get_tval(thr, -1);
27771 DUK_ASSERT(tv != NULL);
27772
27773 if (DUK_TVAL_IS_BOOLEAN(tv)) {
27774 goto type_ok;
27775 } else if (DUK_TVAL_IS_OBJECT(tv)) {
27776 h = DUK_TVAL_GET_OBJECT(tv);
27777 DUK_ASSERT(h != NULL);
27778
27781 DUK_ASSERT(duk_is_boolean(thr, -1));
27782 goto type_ok;
27783 }
27785
27787 /* never here */
27788
27789type_ok:
27790 if (coerce_tostring) {
27791 duk_to_string(thr, -1);
27792 }
27793 return 1;
27794}
27795
27797 duk_hobject *h_this;
27798
27799 duk_to_boolean(thr, 0);
27800
27801 if (duk_is_constructor_call(thr)) {
27802 /* XXX: helper; rely on Boolean.prototype as being non-writable, non-configurable */
27803 duk_push_this(thr);
27804 h_this = duk_known_hobject(thr, -1);
27806
27808
27809 duk_dup_0(thr); /* -> [ val obj val ] */
27811 } /* unbalanced stack */
27812
27813 return 1;
27814}
27815
27816#endif /* DUK_USE_BOOLEAN_BUILTIN */
27817/*
27818 * ES2015 TypedArray and Node.js Buffer built-ins
27820
27821/* #include duk_internal.h -> already included */
27822
27823/*
27824 * Helpers for buffer handling, enabled with DUK_USE_BUFFEROBJECT_SUPPORT.
27825 */
27826
27827#if defined(DUK_USE_BUFFEROBJECT_SUPPORT)
27828/* Map class number (minus DUK_HOBJECT_CLASS_BUFOBJ_MIN) to a bidx for the
27829 * default internal prototype.
27830 */
27831static const duk_uint8_t duk__buffer_proto_from_classnum[] = {
27836};
27837
27838/* Map DUK_HBUFOBJ_ELEM_xxx to duk_hobject class number.
27839 * Sync with duk_hbufobj.h and duk_hobject.h.
27840 */
27846
27847/* Map DUK_HBUFOBJ_ELEM_xxx to prototype object built-in index.
27848 * Sync with duk_hbufobj.h.
27849 */
27850static const duk_uint8_t duk__buffer_proto_from_elemtype[9] = {
27854};
27855
27856/* Map DUK__FLD_xxx to byte size. */
27857static const duk_uint8_t duk__buffer_nbytes_from_fldtype[6] = {
27858 1, /* DUK__FLD_8BIT */
27859 2, /* DUK__FLD_16BIT */
27860 4, /* DUK__FLD_32BIT */
27861 4, /* DUK__FLD_FLOAT */
27862 8, /* DUK__FLD_DOUBLE */
27863 0 /* DUK__FLD_VARINT; not relevant here */
27864};
27865
27866/* Bitfield for each DUK_HBUFOBJ_ELEM_xxx indicating which element types
27867 * are compatible with a blind byte copy for the TypedArray set() method (also
27868 * used for TypedArray constructor). Array index is target buffer elem type,
27869 * bitfield indicates compatible source types. The types must have same byte
27870 * size and they must be coercion compatible.
27871 */
27872#if !defined(DUK_USE_PREFER_SIZE)
27873static duk_uint16_t duk__buffer_elemtype_copy_compatible[9] = {
27874 /* xxx -> DUK_HBUFOBJ_ELEM_UINT8 */
27876
27877 /* xxx -> DUK_HBUFOBJ_ELEM_UINT8CLAMPED
27878 * Note: INT8 is -not- copy compatible, e.g. -1 would coerce to 0x00.
27879 */
27881
27882 /* xxx -> DUK_HBUFOBJ_ELEM_INT8 */
27884
27885 /* xxx -> DUK_HBUFOBJ_ELEM_UINT16 */
27887
27888 /* xxx -> DUK_HBUFOBJ_ELEM_INT16 */
27890
27891 /* xxx -> DUK_HBUFOBJ_ELEM_UINT32 */
27894 /* xxx -> DUK_HBUFOBJ_ELEM_INT32 */
27896
27897 /* xxx -> DUK_HBUFOBJ_ELEM_FLOAT32 */
27899
27900 /* xxx -> DUK_HBUFOBJ_ELEM_FLOAT64 */
27902};
27903#endif /* !DUK_USE_PREFER_SIZE */
27904
27906 duk_tval *tv_dst;
27907 duk_hbufobj *res;
27908
27909 duk_push_this(thr);
27911 res = (duk_hbufobj *) duk_to_hobject(thr, -1);
27913 DUK_DD(DUK_DDPRINT("promoted 'this' automatically to an ArrayBuffer: %!iT", duk_get_tval(thr, -1)));
27914
27915 tv_dst = duk_get_borrowed_this_tval(thr);
27916 DUK_TVAL_SET_OBJECT_UPDREF(thr, tv_dst, (duk_hobject *) res);
27918
27919 return res;
27920}
27921
27922#define DUK__BUFOBJ_FLAG_THROW (1 << 0)
27923#define DUK__BUFOBJ_FLAG_PROMOTE (1 << 1)
27924
27925/* Shared helper. When DUK__BUFOBJ_FLAG_PROMOTE is given, the return value is
27926 * always a duk_hbufobj *. Without the flag the return value can also be a
27927 * plain buffer, and the caller must check for it using DUK_HEAPHDR_IS_BUFFER().
27928 */
27930 duk_tval *tv;
27931 duk_hbufobj *h_this;
27932
27933 DUK_ASSERT(thr != NULL);
27934
27936 DUK_ASSERT(tv != NULL);
27937
27938 if (DUK_TVAL_IS_OBJECT(tv)) {
27939 h_this = (duk_hbufobj *) DUK_TVAL_GET_OBJECT(tv);
27940 DUK_ASSERT(h_this != NULL);
27941 if (DUK_HOBJECT_IS_BUFOBJ((duk_hobject *) h_this)) {
27943 return (duk_heaphdr *) h_this;
27944 }
27945 } else if (DUK_TVAL_IS_BUFFER(tv)) {
27946 if (flags & DUK__BUFOBJ_FLAG_PROMOTE) {
27947 /* Promote a plain buffer to a Uint8Array. This is very
27948 * inefficient but allows plain buffer to be used wherever an
27949 * Uint8Array is used with very small cost; hot path functions
27950 * like index read/write calls should provide direct buffer
27951 * support to avoid promotion.
27952 */
27953 /* XXX: make this conditional to a flag if call sites need it? */
27954 h_this = duk__hbufobj_promote_this(thr);
27955 DUK_ASSERT(h_this != NULL);
27957 return (duk_heaphdr *) h_this;
27958 } else {
27959 /* XXX: ugly, share return pointer for duk_hbuffer. */
27961 }
27962 }
27963
27964 if (flags & DUK__BUFOBJ_FLAG_THROW) {
27966 DUK_WO_NORETURN(return NULL;);
27968 return NULL;
27969}
27970
27971/* Check that 'this' is a duk_hbufobj and return a pointer to it. */
27974}
27975
27976/* Check that 'this' is a duk_hbufobj and return a pointer to it
27977 * (NULL if not).
27978 */
27981}
27982
27983/* Check that value is a duk_hbufobj and return a pointer to it. */
27985 duk_tval *tv;
27986 duk_hbufobj *h_obj;
27987
27988 /* Don't accept relative indices now. */
27989 DUK_ASSERT(idx >= 0);
27990
27991 tv = duk_require_tval(thr, idx);
27992 DUK_ASSERT(tv != NULL);
27993 if (DUK_TVAL_IS_OBJECT(tv)) {
27994 h_obj = (duk_hbufobj *) DUK_TVAL_GET_OBJECT(tv);
27995 DUK_ASSERT(h_obj != NULL);
27996 if (DUK_HOBJECT_IS_BUFOBJ((duk_hobject *) h_obj)) {
27998 return h_obj;
28000 } else if (DUK_TVAL_IS_BUFFER(tv)) {
28001 h_obj = (duk_hbufobj *) duk_to_hobject(thr, idx);
28002 DUK_ASSERT(h_obj != NULL);
28004 return h_obj;
28005 }
28006
28008 DUK_WO_NORETURN(return NULL;);
28009}
28010
28012 DUK_ASSERT(thr != NULL);
28013 DUK_ASSERT(h_bufobj != NULL);
28014 DUK_ASSERT(h_bufobj->buf == NULL); /* no need to decref */
28015 DUK_ASSERT(h_val != NULL);
28016 DUK_HBUFOBJ_ASSERT_VALID(h_bufobj);
28017 DUK_UNREF(thr);
28019 h_bufobj->buf = h_val;
28020 DUK_HBUFFER_INCREF(thr, h_val);
28021 h_bufobj->length = (duk_uint_t) DUK_HBUFFER_GET_SIZE(h_val);
28022 DUK_ASSERT(h_bufobj->shift == 0);
28024 DUK_ASSERT(h_bufobj->is_typedarray == 0);
28025
28026 DUK_HBUFOBJ_ASSERT_VALID(h_bufobj);
28027}
28028
28029/* Shared offset/length coercion helper. */
28031 duk_hbufobj *h_bufarg,
28032 duk_idx_t idx_offset,
28033 duk_idx_t idx_length,
28034 duk_uint_t *out_offset,
28035 duk_uint_t *out_length,
28036 duk_bool_t throw_flag) {
28037 duk_int_t offset_signed;
28038 duk_int_t length_signed;
28039 duk_uint_t offset;
28040 duk_uint_t length;
28041
28042 offset_signed = duk_to_int(thr, idx_offset);
28043 if (offset_signed < 0) {
28044 goto fail_range;
28045 }
28046 offset = (duk_uint_t) offset_signed;
28047 if (offset > h_bufarg->length) {
28048 goto fail_range;
28049 }
28050 DUK_ASSERT_DISABLE(offset >= 0); /* unsigned */
28051 DUK_ASSERT(offset <= h_bufarg->length);
28052
28053 if (duk_is_undefined(thr, idx_length)) {
28054 DUK_ASSERT(h_bufarg->length >= offset);
28055 length = h_bufarg->length - offset; /* >= 0 */
28056 } else {
28057 length_signed = duk_to_int(thr, idx_length);
28058 if (length_signed < 0) {
28059 goto fail_range;
28060 }
28061 length = (duk_uint_t) length_signed;
28062 DUK_ASSERT(h_bufarg->length >= offset);
28063 if (length > h_bufarg->length - offset) {
28064 /* Unlike for negative arguments, some call sites
28065 * want length to be clamped if it's positive.
28066 */
28067 if (throw_flag) {
28068 goto fail_range;
28069 } else {
28070 length = h_bufarg->length - offset;
28071 }
28072 }
28073 }
28074 DUK_ASSERT_DISABLE(length >= 0); /* unsigned */
28075 DUK_ASSERT(offset + length <= h_bufarg->length);
28076
28077 *out_offset = offset;
28078 *out_length = length;
28079 return;
28080
28081fail_range:
28083 DUK_WO_NORETURN(return;);
28084}
28085
28086/* Shared lenient buffer length clamping helper. No negative indices, no
28087 * element/byte shifting.
28088 */
28090 duk_int_t buffer_length,
28091 duk_idx_t idx_start,
28092 duk_idx_t idx_end,
28093 duk_int_t *out_start_offset,
28094 duk_int_t *out_end_offset) {
28095 duk_int_t start_offset;
28096 duk_int_t end_offset;
28097
28098 DUK_ASSERT(out_start_offset != NULL);
28099 DUK_ASSERT(out_end_offset != NULL);
28100
28101 /* undefined coerces to zero which is correct */
28102 start_offset = duk_to_int_clamped(thr, idx_start, 0, buffer_length);
28103 if (duk_is_undefined(thr, idx_end)) {
28104 end_offset = buffer_length;
28105 } else {
28106 end_offset = duk_to_int_clamped(thr, idx_end, start_offset, buffer_length);
28107 }
28108
28109 DUK_ASSERT(start_offset >= 0);
28110 DUK_ASSERT(start_offset <= buffer_length);
28111 DUK_ASSERT(end_offset >= 0);
28112 DUK_ASSERT(end_offset <= buffer_length);
28113 DUK_ASSERT(start_offset <= end_offset);
28115 *out_start_offset = start_offset;
28116 *out_end_offset = end_offset;
28117}
28118
28119/* Shared lenient buffer length clamping helper. Indices are treated as
28120 * element indices (though output values are byte offsets) which only
28121 * really matters for TypedArray views as other buffer object have a zero
28122 * shift. Negative indices are counted from end of input slice; crossed
28123 * indices are clamped to zero length; and final indices are clamped
28124 * against input slice. Used for e.g. ArrayBuffer slice().
28125 */
28127 duk_int_t buffer_length,
28128 duk_uint8_t buffer_shift,
28129 duk_idx_t idx_start,
28130 duk_idx_t idx_end,
28131 duk_int_t *out_start_offset,
28132 duk_int_t *out_end_offset) {
28133 duk_int_t start_offset;
28134 duk_int_t end_offset;
28135
28136 DUK_ASSERT(out_start_offset != NULL);
28137 DUK_ASSERT(out_end_offset != NULL);
28138
28139 buffer_length >>= buffer_shift; /* as (full) elements */
28140
28141 /* Resolve start/end offset as element indices first; arguments
28142 * at idx_start/idx_end are element offsets. Working with element
28143 * indices first also avoids potential for wrapping.
28144 */
28145
28146 start_offset = duk_to_int(thr, idx_start);
28147 if (start_offset < 0) {
28148 start_offset = buffer_length + start_offset;
28149 }
28150 if (duk_is_undefined(thr, idx_end)) {
28151 end_offset = buffer_length;
28152 } else {
28153 end_offset = duk_to_int(thr, idx_end);
28154 if (end_offset < 0) {
28155 end_offset = buffer_length + end_offset;
28156 }
28157 }
28158 /* Note: start_offset/end_offset can still be < 0 here. */
28159
28160 if (start_offset < 0) {
28161 start_offset = 0;
28162 } else if (start_offset > buffer_length) {
28163 start_offset = buffer_length;
28164 }
28165 if (end_offset < start_offset) {
28166 end_offset = start_offset;
28167 } else if (end_offset > buffer_length) {
28168 end_offset = buffer_length;
28169 }
28170 DUK_ASSERT(start_offset >= 0);
28171 DUK_ASSERT(start_offset <= buffer_length);
28172 DUK_ASSERT(end_offset >= 0);
28173 DUK_ASSERT(end_offset <= buffer_length);
28174 DUK_ASSERT(start_offset <= end_offset);
28175
28176 /* Convert indices to byte offsets. */
28177 start_offset <<= buffer_shift;
28178 end_offset <<= buffer_shift;
28179
28180 *out_start_offset = start_offset;
28181 *out_end_offset = end_offset;
28182}
28183
28185 if (duk_is_buffer(thr, idx)) {
28186 duk_to_object(thr, idx);
28187 }
28188}
28189
28191 /* Push Uint8Array which will share the same underlying buffer as
28192 * the plain buffer argument. Also create an ArrayBuffer with the
28193 * same backing for the result .buffer property.
28194 */
28195
28196 duk_push_hbuffer(thr, h_buf);
28198 duk_remove_m2(thr);
28199
28200#if 0
28201 /* More verbose equivalent; maybe useful if e.g. .buffer is omitted. */
28202 h_bufobj = duk_push_bufobj_raw(thr,
28207 DUK_ASSERT(h_bufobj != NULL);
28208 duk__set_bufobj_buffer(thr, h_bufobj, h_buf);
28209 h_bufobj->is_typedarray = 1;
28210 DUK_HBUFOBJ_ASSERT_VALID(h_bufobj);
28211
28212 h_arrbuf = duk_push_bufobj_raw(thr,
28217 DUK_ASSERT(h_arrbuf != NULL);
28218 duk__set_bufobj_buffer(thr, h_arrbuf, h_buf);
28219 DUK_ASSERT(h_arrbuf->is_typedarray == 0);
28220 DUK_HBUFOBJ_ASSERT_VALID(h_arrbuf);
28221
28222 DUK_ASSERT(h_bufobj->buf_prop == NULL);
28223 h_bufobj->buf_prop = (duk_hobject *) h_arrbuf;
28224 DUK_ASSERT(h_arrbuf != NULL);
28225 DUK_HBUFOBJ_INCREF(thr, h_arrbuf);
28226 duk_pop(thr);
28227#endif
28228}
28229
28230/* Indexed read helper for buffer objects, also called from outside this file. */
28232 duk_hbufobj *h_bufobj,
28233 duk_uint8_t *p,
28234 duk_small_uint_t elem_size) {
28236
28237 DUK_ASSERT(elem_size > 0);
28238 duk_memcpy((void *) du.uc, (const void *) p, (size_t) elem_size);
28239
28240 switch (h_bufobj->elem_type) {
28243 duk_push_uint(thr, (duk_uint_t) du.uc[0]);
28244 break;
28246 duk_push_int(thr, (duk_int_t) (duk_int8_t) du.uc[0]);
28247 break;
28249 duk_push_uint(thr, (duk_uint_t) du.us[0]);
28250 break;
28252 duk_push_int(thr, (duk_int_t) (duk_int16_t) du.us[0]);
28253 break;
28255 duk_push_uint(thr, (duk_uint_t) du.ui[0]);
28256 break;
28258 duk_push_int(thr, (duk_int_t) (duk_int32_t) du.ui[0]);
28259 break;
28261 duk_push_number(thr, (duk_double_t) du.f[0]);
28262 break;
28264 duk_push_number(thr, (duk_double_t) du.d);
28265 break;
28266 default:
28268 }
28269}
28270
28271/* Indexed write helper for buffer objects, also called from outside this file. */
28272DUK_INTERNAL void duk_hbufobj_validated_write(duk_hthread *thr, duk_hbufobj *h_bufobj, duk_uint8_t *p, duk_small_uint_t elem_size) {
28274
28275 /* NOTE! Caller must ensure that any side effects from the
28276 * coercions below are safe. If that cannot be guaranteed
28277 * (which is normally the case), caller must coerce the
28278 * argument using duk_to_number() before any pointer
28279 * validations; the result of duk_to_number() always coerces
28280 * without side effects here.
28281 */
28282
28283 switch (h_bufobj->elem_type) {
28285 du.uc[0] = (duk_uint8_t) duk_to_uint32(thr, -1);
28286 break;
28288 du.uc[0] = (duk_uint8_t) duk_to_uint8clamped(thr, -1);
28289 break;
28291 du.uc[0] = (duk_uint8_t) duk_to_int32(thr, -1);
28292 break;
28294 du.us[0] = (duk_uint16_t) duk_to_uint32(thr, -1);
28295 break;
28297 du.us[0] = (duk_uint16_t) duk_to_int32(thr, -1);
28298 break;
28300 du.ui[0] = (duk_uint32_t) duk_to_uint32(thr, -1);
28301 break;
28303 du.ui[0] = (duk_uint32_t) duk_to_int32(thr, -1);
28304 break;
28306 /* A double-to-float cast is undefined behavior in C99 if
28307 * the cast is out-of-range, so use a helper. Example:
28308 * runtime error: value -1e+100 is outside the range of representable values of type 'float'
28309 */
28311 break;
28313 du.d = (duk_double_t) duk_to_number_m1(thr);
28314 break;
28315 default:
28317 }
28318
28319 DUK_ASSERT(elem_size > 0);
28320 duk_memcpy((void *) p, (const void *) du.uc, (size_t) elem_size);
28321}
28322
28323/* Helper to create a fixed buffer from argument value at index 0.
28324 * Node.js and allocPlain() compatible.
28325 */
28327 duk_int_t len;
28328 duk_int_t i;
28329 duk_size_t buf_size;
28330 duk_uint8_t *buf;
28331
28332 switch (duk_get_type(thr, 0)) {
28333 case DUK_TYPE_NUMBER: {
28334 len = duk_to_int_clamped(thr, 0, 0, DUK_INT_MAX);
28335 (void) duk_push_fixed_buffer_zero(thr, (duk_size_t) len);
28336 break;
28337 }
28338 case DUK_TYPE_BUFFER: { /* Treat like Uint8Array. */
28339 goto slow_copy;
28340 }
28341 case DUK_TYPE_OBJECT: {
28342 duk_hobject *h;
28343 duk_hbufobj *h_bufobj;
28344
28345 /* For Node.js Buffers "Passing an ArrayBuffer returns a Buffer
28346 * that shares allocated memory with the given ArrayBuffer."
28347 * https://nodejs.org/api/buffer.html#buffer_buffer_from_buffer_alloc_and_buffer_allocunsafe
28348 */
28349
28350 h = duk_known_hobject(thr, 0);
28353 h_bufobj = (duk_hbufobj *) h;
28354 if (DUK_UNLIKELY(h_bufobj->buf == NULL)) {
28356 DUK_WO_NORETURN(return NULL;);
28357 }
28358 if (DUK_UNLIKELY(h_bufobj->offset != 0 || h_bufobj->length != DUK_HBUFFER_GET_SIZE(h_bufobj->buf))) {
28359 /* No support for ArrayBuffers with slice
28360 * offset/length.
28361 */
28363 DUK_WO_NORETURN(return NULL;);
28364 }
28365 duk_push_hbuffer(thr, h_bufobj->buf);
28366 return h_bufobj->buf;
28367 }
28368 goto slow_copy;
28369 }
28370 case DUK_TYPE_STRING: {
28371 /* ignore encoding for now */
28373 duk_dup_0(thr);
28374 (void) duk_to_buffer(thr, -1, &buf_size);
28375 break;
28376 }
28377 default:
28379 DUK_WO_NORETURN(return NULL;);
28380 }
28381
28382done:
28383 DUK_ASSERT(duk_is_buffer(thr, -1));
28384 return duk_known_hbuffer(thr, -1);
28385
28386slow_copy:
28387 /* XXX: fast path for typed arrays and other buffer objects? */
28388
28390 len = duk_to_int_clamped(thr, -1, 0, DUK_INT_MAX);
28391 duk_pop(thr);
28392 buf = (duk_uint8_t *) duk_push_fixed_buffer_nozero(thr, (duk_size_t) len); /* no zeroing, all indices get initialized */
28393 for (i = 0; i < len; i++) {
28394 /* XXX: fast path for array or buffer arguments? */
28395 duk_get_prop_index(thr, 0, (duk_uarridx_t) i);
28396 buf[i] = (duk_uint8_t) (duk_to_uint32(thr, -1) & 0xffU);
28397 duk_pop(thr);
28398 }
28399 goto done;
28401#endif /* DUK_USE_BUFFEROBJECT_SUPPORT */
28402
28403/*
28404 * Node.js Buffer constructor
28405 *
28406 * Node.js Buffers are just Uint8Arrays with internal prototype set to
28407 * Buffer.prototype so they're handled otherwise the same as Uint8Array.
28408 * However, the constructor arguments are very different so a separate
28409 * constructor entry point is used.
28410 */
28411#if defined(DUK_USE_BUFFEROBJECT_SUPPORT)
28413 duk_hbuffer *h_buf;
28414
28416 DUK_ASSERT(h_buf != NULL);
28417
28420 duk_set_prototype(thr, -2);
28422 /* XXX: a more direct implementation */
28423
28424 return 1;
28425}
28426#endif /* DUK_USE_BUFFEROBJECT_SUPPORT */
28427
28428/*
28429 * ArrayBuffer, DataView, and TypedArray constructors
28430 */
28431
28432#if defined(DUK_USE_BUFFEROBJECT_SUPPORT)
28434 duk_hbufobj *h_bufobj;
28435 duk_hbuffer *h_val;
28436 duk_int_t len;
28437
28439
28441
28442 len = duk_to_int(thr, 0);
28443 if (len < 0) {
28444 goto fail_length;
28445 }
28446 (void) duk_push_fixed_buffer_zero(thr, (duk_size_t) len);
28447 h_val = (duk_hbuffer *) duk_known_hbuffer(thr, -1);
28448
28449 h_bufobj = duk_push_bufobj_raw(thr,
28453 DUK_ASSERT(h_bufobj != NULL);
28454
28455 duk__set_bufobj_buffer(thr, h_bufobj, h_val);
28456 DUK_HBUFOBJ_ASSERT_VALID(h_bufobj);
28457
28458 return 1;
28459
28460fail_length:
28462}
28463#endif /* DUK_USE_BUFFEROBJECT_SUPPORT */
28464
28465/* Format of magic, bits:
28466 * 0...1: elem size shift (0-3)
28467 * 2...5: elem type (DUK_HBUFOBJ_ELEM_xxx)
28468 *
28469 * XXX: add prototype bidx explicitly to magic instead of using a mapping?
28470 */
28471
28472#if defined(DUK_USE_BUFFEROBJECT_SUPPORT)
28474 duk_tval *tv;
28475 duk_hobject *h_obj;
28476 duk_hbufobj *h_bufobj = NULL;
28477 duk_hbufobj *h_bufarg = NULL;
28478 duk_hbuffer *h_val;
28479 duk_small_uint_t magic;
28480 duk_small_uint_t shift;
28481 duk_small_uint_t elem_type;
28482 duk_small_uint_t elem_size;
28483 duk_small_uint_t class_num;
28484 duk_small_uint_t proto_bidx;
28485 duk_uint_t align_mask;
28486 duk_uint_t elem_length;
28487 duk_int_t elem_length_signed;
28488 duk_uint_t byte_length;
28489 duk_small_uint_t copy_mode;
28490
28491 /* XXX: The same copy helpers could be shared with at least some
28492 * buffer functions.
28493 */
28494
28496
28497 /* We could fit built-in index into magic but that'd make the magic
28498 * number dependent on built-in numbering (genbuiltins.py doesn't
28499 * handle that yet). So map both class and prototype from the
28500 * element type.
28501 */
28503 shift = magic & 0x03U; /* bits 0...1: shift */
28504 elem_type = (magic >> 2) & 0x0fU; /* bits 2...5: type */
28505 elem_size = 1U << shift;
28506 align_mask = elem_size - 1;
28507 DUK_ASSERT(elem_type < sizeof(duk__buffer_proto_from_elemtype) / sizeof(duk_uint8_t));
28508 proto_bidx = duk__buffer_proto_from_elemtype[elem_type];
28509 DUK_ASSERT(proto_bidx < DUK_NUM_BUILTINS);
28510 DUK_ASSERT(elem_type < sizeof(duk__buffer_class_from_elemtype) / sizeof(duk_uint8_t));
28511 class_num = duk__buffer_class_from_elemtype[elem_type];
28512
28513 DUK_DD(DUK_DDPRINT("typedarray constructor, magic=%d, shift=%d, elem_type=%d, "
28514 "elem_size=%d, proto_bidx=%d, class_num=%d",
28515 (int) magic,
28516 (int) shift,
28517 (int) elem_type,
28518 (int) elem_size,
28519 (int) proto_bidx,
28520 (int) class_num));
28521
28522 /* Argument variants. When the argument is an ArrayBuffer a view to
28523 * the same buffer is created; otherwise a new ArrayBuffer is always
28524 * created.
28525 */
28526
28527 /* XXX: initial iteration to treat a plain buffer like an ArrayBuffer:
28528 * coerce to an ArrayBuffer object and use that as .buffer. The underlying
28529 * buffer will be the same but result .buffer !== inputPlainBuffer.
28530 */
28532
28533 tv = duk_get_tval(thr, 0);
28534 DUK_ASSERT(tv != NULL); /* arg count */
28535 if (DUK_TVAL_IS_OBJECT(tv)) {
28536 h_obj = DUK_TVAL_GET_OBJECT(tv);
28537 DUK_ASSERT(h_obj != NULL);
28538
28540 /* ArrayBuffer: unlike any other argument variant, create
28541 * a view into the existing buffer.
28542 */
28543
28544 duk_int_t byte_offset_signed;
28545 duk_uint_t byte_offset;
28546
28547 h_bufarg = (duk_hbufobj *) h_obj;
28548
28549 byte_offset_signed = duk_to_int(thr, 1);
28550 if (byte_offset_signed < 0) {
28551 goto fail_arguments;
28552 }
28553 byte_offset = (duk_uint_t) byte_offset_signed;
28554 if (byte_offset > h_bufarg->length || (byte_offset & align_mask) != 0) {
28555 /* Must be >= 0 and multiple of element size. */
28556 goto fail_arguments;
28557 }
28558 if (duk_is_undefined(thr, 2)) {
28559 DUK_ASSERT(h_bufarg->length >= byte_offset);
28560 byte_length = h_bufarg->length - byte_offset;
28561 if ((byte_length & align_mask) != 0) {
28562 /* Must be element size multiple from
28563 * start offset to end of buffer.
28564 */
28565 goto fail_arguments;
28566 }
28567 elem_length = (byte_length >> shift);
28568 } else {
28569 elem_length_signed = duk_to_int(thr, 2);
28570 if (elem_length_signed < 0) {
28571 goto fail_arguments;
28572 }
28573 elem_length = (duk_uint_t) elem_length_signed;
28574 byte_length = elem_length << shift;
28575 if ((byte_length >> shift) != elem_length) {
28576 /* Byte length would overflow. */
28577 /* XXX: easier check with less code? */
28578 goto fail_arguments;
28579 }
28580 DUK_ASSERT(h_bufarg->length >= byte_offset);
28581 if (byte_length > h_bufarg->length - byte_offset) {
28582 /* Not enough data. */
28583 goto fail_arguments;
28584 }
28585 }
28586 DUK_UNREF(elem_length);
28587 DUK_ASSERT_DISABLE(byte_offset >= 0);
28588 DUK_ASSERT(byte_offset <= h_bufarg->length);
28589 DUK_ASSERT_DISABLE(byte_length >= 0);
28590 DUK_ASSERT(byte_offset + byte_length <= h_bufarg->length);
28591 DUK_ASSERT((elem_length << shift) == byte_length);
28592
28593 h_bufobj = duk_push_bufobj_raw(thr,
28595 DUK_HOBJECT_CLASS_AS_FLAGS(class_num),
28596 (duk_small_int_t) proto_bidx);
28597 h_val = h_bufarg->buf;
28598 if (h_val == NULL) {
28600 }
28601 h_bufobj->buf = h_val;
28602 DUK_HBUFFER_INCREF(thr, h_val);
28603 h_bufobj->offset = h_bufarg->offset + byte_offset;
28604 h_bufobj->length = byte_length;
28605 h_bufobj->shift = (duk_uint8_t) shift;
28606 h_bufobj->elem_type = (duk_uint8_t) elem_type;
28607 h_bufobj->is_typedarray = 1;
28608 DUK_HBUFOBJ_ASSERT_VALID(h_bufobj);
28609
28610 /* Set .buffer to the argument ArrayBuffer. */
28611 DUK_ASSERT(h_bufobj->buf_prop == NULL);
28612 h_bufobj->buf_prop = (duk_hobject *) h_bufarg;
28613 DUK_ASSERT(h_bufarg != NULL);
28614 DUK_HBUFOBJ_INCREF(thr, h_bufarg);
28615 return 1;
28616 } else if (DUK_HOBJECT_IS_BUFOBJ(h_obj)) {
28617 /* TypedArray (or other non-ArrayBuffer duk_hbufobj).
28618 * Conceptually same behavior as for an Array-like argument,
28619 * with a few fast paths.
28620 */
28621
28622 h_bufarg = (duk_hbufobj *) h_obj;
28623 DUK_HBUFOBJ_ASSERT_VALID(h_bufarg);
28624 elem_length_signed = (duk_int_t) (h_bufarg->length >> h_bufarg->shift);
28625 if (h_bufarg->buf == NULL) {
28627 }
28628
28629 /* Select copy mode. Must take into account element
28630 * compatibility and validity of the underlying source
28631 * buffer.
28632 */
28633
28634 DUK_DDD(DUK_DDDPRINT("selecting copy mode for bufobj arg, "
28635 "src byte_length=%ld, src shift=%d, "
28636 "src/dst elem_length=%ld; "
28637 "dst shift=%d -> dst byte_length=%ld",
28638 (long) h_bufarg->length,
28639 (int) h_bufarg->shift,
28640 (long) elem_length_signed,
28641 (int) shift,
28642 (long) (elem_length_signed << shift)));
28643
28644 copy_mode = 2; /* default is explicit index read/write copy */
28645#if !defined(DUK_USE_PREFER_SIZE)
28646 /* With a size optimized build copy_mode 2 is enough.
28647 * Modes 0 and 1 are faster but conceptually the same.
28648 */
28649 DUK_ASSERT(elem_type < sizeof(duk__buffer_elemtype_copy_compatible) / sizeof(duk_uint16_t));
28650 if (DUK_HBUFOBJ_VALID_SLICE(h_bufarg)) {
28651 if ((duk__buffer_elemtype_copy_compatible[elem_type] & (1 << h_bufarg->elem_type)) != 0) {
28652 DUK_DDD(DUK_DDDPRINT("source/target are copy compatible, memcpy"));
28653 DUK_ASSERT(shift == h_bufarg->shift); /* byte sizes will match */
28654 copy_mode = 0;
28655 } else {
28656 DUK_DDD(DUK_DDDPRINT("source/target not copy compatible but valid, fast copy"));
28657 copy_mode = 1;
28658 }
28659 }
28660#endif /* !DUK_USE_PREFER_SIZE */
28661 } else {
28662 /* Array or Array-like */
28663 elem_length_signed = (duk_int_t) duk_get_length(thr, 0);
28664 copy_mode = 2;
28665 }
28666 } else {
28667 /* Non-object argument is simply int coerced, matches
28668 * V8 behavior (except for "null", which we coerce to
28669 * 0 but V8 TypeErrors).
28670 */
28671 elem_length_signed = duk_to_int(thr, 0);
28672 copy_mode = 3;
28673 }
28674 if (elem_length_signed < 0) {
28675 goto fail_arguments;
28676 }
28677 elem_length = (duk_uint_t) elem_length_signed;
28678 byte_length = (duk_uint_t) (elem_length << shift);
28679 if ((byte_length >> shift) != elem_length) {
28680 /* Byte length would overflow. */
28681 /* XXX: easier check with less code? */
28682 goto fail_arguments;
28683 }
28684
28685 DUK_DDD(DUK_DDDPRINT("elem_length=%ld, byte_length=%ld", (long) elem_length, (long) byte_length));
28686
28687 /* ArrayBuffer argument is handled specially above; the rest of the
28688 * argument variants are handled by shared code below.
28689 *
28690 * ArrayBuffer in h_bufobj->buf_prop is intentionally left unset.
28691 * It will be automatically created by the .buffer accessor on
28692 * first access.
28693 */
28694
28695 /* Push the resulting view object on top of a plain fixed buffer. */
28696 (void) duk_push_fixed_buffer(thr, byte_length);
28697 h_val = duk_known_hbuffer(thr, -1);
28698 DUK_ASSERT(h_val != NULL);
28699
28700 h_bufobj =
28703 (duk_small_int_t) proto_bidx);
28704
28705 h_bufobj->buf = h_val;
28706 DUK_HBUFFER_INCREF(thr, h_val);
28707 DUK_ASSERT(h_bufobj->offset == 0);
28708 h_bufobj->length = byte_length;
28709 h_bufobj->shift = (duk_uint8_t) shift;
28710 h_bufobj->elem_type = (duk_uint8_t) elem_type;
28711 h_bufobj->is_typedarray = 1;
28712 DUK_HBUFOBJ_ASSERT_VALID(h_bufobj);
28713
28714 /* Copy values, the copy method depends on the arguments.
28715 *
28716 * Copy mode decision may depend on the validity of the underlying
28717 * buffer of the source argument; there must be no harmful side effects
28718 * from there to here for copy_mode to still be valid.
28719 */
28720 DUK_DDD(DUK_DDDPRINT("copy mode: %d", (int) copy_mode));
28721 switch (copy_mode) {
28722 /* Copy modes 0 and 1 can be omitted in size optimized build,
28723 * copy mode 2 handles them (but more slowly).
28724 */
28725#if !defined(DUK_USE_PREFER_SIZE)
28726 case 0: {
28727 /* Use byte copy. */
28728
28729 duk_uint8_t *p_src;
28730 duk_uint8_t *p_dst;
28731
28732 DUK_ASSERT(h_bufobj != NULL);
28733 DUK_ASSERT(h_bufobj->buf != NULL);
28735 DUK_ASSERT(h_bufarg != NULL);
28736 DUK_ASSERT(h_bufarg->buf != NULL);
28738
28739 p_dst = DUK_HBUFOBJ_GET_SLICE_BASE(thr->heap, h_bufobj);
28740 p_src = DUK_HBUFOBJ_GET_SLICE_BASE(thr->heap, h_bufarg);
28741
28742 DUK_DDD(DUK_DDDPRINT("using memcpy: p_src=%p, p_dst=%p, byte_length=%ld",
28743 (void *) p_src,
28744 (void *) p_dst,
28745 (long) byte_length));
28746
28747 duk_memcpy_unsafe((void *) p_dst, (const void *) p_src, (size_t) byte_length);
28748 break;
28749 }
28750 case 1: {
28751 /* Copy values through direct validated reads and writes. */
28752
28753 duk_small_uint_t src_elem_size;
28754 duk_small_uint_t dst_elem_size;
28755 duk_uint8_t *p_src;
28756 duk_uint8_t *p_src_end;
28757 duk_uint8_t *p_dst;
28758
28759 DUK_ASSERT(h_bufobj != NULL);
28760 DUK_ASSERT(h_bufobj->buf != NULL);
28762 DUK_ASSERT(h_bufarg != NULL);
28763 DUK_ASSERT(h_bufarg->buf != NULL);
28765
28766 src_elem_size = (duk_small_uint_t) (1U << h_bufarg->shift);
28767 dst_elem_size = elem_size;
28768
28769 p_src = DUK_HBUFOBJ_GET_SLICE_BASE(thr->heap, h_bufarg);
28770 p_dst = DUK_HBUFOBJ_GET_SLICE_BASE(thr->heap, h_bufobj);
28771 p_src_end = p_src + h_bufarg->length;
28772
28773 DUK_DDD(DUK_DDDPRINT("using fast copy: p_src=%p, p_src_end=%p, p_dst=%p, "
28774 "src_elem_size=%d, dst_elem_size=%d",
28775 (void *) p_src,
28776 (void *) p_src_end,
28777 (void *) p_dst,
28778 (int) src_elem_size,
28779 (int) dst_elem_size));
28780
28781 while (p_src != p_src_end) {
28782 DUK_DDD(DUK_DDDPRINT("fast path per element copy loop: "
28783 "p_src=%p, p_src_end=%p, p_dst=%p",
28784 (void *) p_src,
28785 (void *) p_src_end,
28786 (void *) p_dst));
28787 /* A validated read() is always a number, so it's write coercion
28788 * is always side effect free an won't invalidate pointers etc.
28789 */
28790 duk_hbufobj_push_validated_read(thr, h_bufarg, p_src, src_elem_size);
28791 duk_hbufobj_validated_write(thr, h_bufobj, p_dst, dst_elem_size);
28792 duk_pop(thr);
28793 p_src += src_elem_size;
28794 p_dst += dst_elem_size;
28795 }
28796 break;
28797 }
28798#endif /* !DUK_USE_PREFER_SIZE */
28799 case 2: {
28800 /* Copy values by index reads and writes. Let virtual
28801 * property handling take care of coercion.
28802 */
28803 duk_uint_t i;
28804
28805 DUK_DDD(DUK_DDDPRINT("using slow copy"));
28806
28807 for (i = 0; i < elem_length; i++) {
28808 duk_get_prop_index(thr, 0, (duk_uarridx_t) i);
28809 duk_put_prop_index(thr, -2, (duk_uarridx_t) i);
28810 }
28811 break;
28812 }
28813 default:
28814 case 3: {
28815 /* No copy, leave zero bytes in the buffer. There's no
28816 * ambiguity with Float32/Float64 because zero bytes also
28817 * represent 0.0.
28818 */
28819
28820 DUK_DDD(DUK_DDDPRINT("using no copy"));
28821 break;
28822 }
28823 }
28824
28825 return 1;
28826
28827fail_arguments:
28829}
28830#else /* DUK_USE_BUFFEROBJECT_SUPPORT */
28831/* When bufferobject support is disabled, new Uint8Array() could still be
28832 * supported to create a plain fixed buffer. Disabled for now.
28833 */
28834#if 0
28836 duk_int_t elem_length_signed;
28837 duk_uint_t byte_length;
28838
28839 /* XXX: The same copy helpers could be shared with at least some
28840 * buffer functions.
28841 */
28842
28844
28845 elem_length_signed = duk_require_int(thr, 0);
28846 if (elem_length_signed < 0) {
28847 goto fail_arguments;
28848 }
28849 byte_length = (duk_uint_t) elem_length_signed;
28850
28851 (void) duk_push_fixed_buffer_zero(thr, (duk_size_t) byte_length);
28852 return 1;
28853
28854 fail_arguments:
28856}
28857#endif /* 0 */
28858#endif /* DUK_USE_BUFFEROBJECT_SUPPORT */
28859
28860#if defined(DUK_USE_BUFFEROBJECT_SUPPORT)
28862 duk_hbufobj *h_bufarg;
28863 duk_hbufobj *h_bufobj;
28864 duk_hbuffer *h_val;
28865 duk_uint_t offset;
28866 duk_uint_t length;
28867
28869
28870 h_bufarg = duk__require_bufobj_value(thr, 0);
28871 DUK_ASSERT(h_bufarg != NULL);
28874 }
28875
28876 duk__resolve_offset_opt_length(thr, h_bufarg, 1, 2, &offset, &length, 1 /*throw_flag*/);
28877 DUK_ASSERT(offset <= h_bufarg->length);
28878 DUK_ASSERT(offset + length <= h_bufarg->length);
28879
28880 h_bufobj = duk_push_bufobj_raw(thr,
28884
28885 h_val = h_bufarg->buf;
28886 if (h_val == NULL) {
28888 }
28889 h_bufobj->buf = h_val;
28890 DUK_HBUFFER_INCREF(thr, h_val);
28891 h_bufobj->offset = h_bufarg->offset + offset;
28892 h_bufobj->length = length;
28893 DUK_ASSERT(h_bufobj->shift == 0);
28895 DUK_ASSERT(h_bufobj->is_typedarray == 0);
28896
28897 DUK_ASSERT(h_bufobj->buf_prop == NULL);
28898 h_bufobj->buf_prop = (duk_hobject *) h_bufarg;
28899 DUK_ASSERT(h_bufarg != NULL);
28900 DUK_HBUFOBJ_INCREF(thr, h_bufarg);
28901
28902 DUK_HBUFOBJ_ASSERT_VALID(h_bufobj);
28903 return 1;
28904}
28905#endif /* DUK_USE_BUFFEROBJECT_SUPPORT */
28906
28907/*
28908 * ArrayBuffer.isView()
28909 */
28910
28911#if defined(DUK_USE_BUFFEROBJECT_SUPPORT)
28913 duk_hobject *h_obj;
28914 duk_bool_t ret = 0;
28915
28916 if (duk_is_buffer(thr, 0)) {
28917 ret = 1;
28918 } else {
28919 h_obj = duk_get_hobject(thr, 0);
28920 if (h_obj != NULL && DUK_HOBJECT_IS_BUFOBJ(h_obj)) {
28921 /* DataView needs special casing: ArrayBuffer.isView() is
28922 * true, but ->is_typedarray is 0.
28923 */
28924 ret = ((duk_hbufobj *) h_obj)->is_typedarray ||
28927 }
28928 duk_push_boolean(thr, ret);
28929 return 1;
28930}
28931#endif /* DUK_USE_BUFFEROBJECT_SUPPORT */
28932
28933/*
28934 * Uint8Array.allocPlain()
28935 */
28936
28937#if defined(DUK_USE_BUFFEROBJECT_SUPPORT)
28940 return 1;
28941}
28942#endif /* DUK_USE_BUFFEROBJECT_SUPPORT */
28943
28944/*
28945 * Uint8Array.plainOf()
28946 */
28947
28948#if defined(DUK_USE_BUFFEROBJECT_SUPPORT)
28950 duk_hbufobj *h_bufobj;
28951
28952#if !defined(DUK_USE_PREFER_SIZE)
28953 /* Avoid churn if argument is already a plain buffer. */
28954 if (duk_is_buffer(thr, 0)) {
28955 return 1;
28956 }
28957#endif
28958
28959 /* Promotes plain buffers to ArrayBuffers, so for a plain buffer
28960 * argument we'll create a pointless temporary (but still work
28961 * correctly).
28962 */
28963 h_bufobj = duk__require_bufobj_value(thr, 0);
28964 if (h_bufobj->buf == NULL) {
28965 duk_push_undefined(thr);
28966 } else {
28967 duk_push_hbuffer(thr, h_bufobj->buf);
28968 }
28969 return 1;
28970}
28971#endif /* DUK_USE_BUFFEROBJECT_SUPPORT */
28972
28973/*
28974 * Node.js Buffer: toString([encoding], [start], [end])
28975 */
28976
28977#if defined(DUK_USE_BUFFEROBJECT_SUPPORT)
28979 duk_hbufobj *h_this;
28980 duk_int_t start_offset, end_offset;
28981 duk_uint8_t *buf_slice;
28982 duk_size_t slice_length;
28983
28984 h_this = duk__get_bufobj_this(thr);
28985 if (h_this == NULL) {
28986 /* XXX: happens e.g. when evaluating: String(Buffer.prototype). */
28987 duk_push_literal(thr, "[object Object]");
28988 return 1;
28989 }
28991
28992 /* Ignore encoding for now. */
28993
28995 (duk_int_t) h_this->length,
28996 1 /*idx_start*/,
28997 2 /*idx_end*/,
28998 &start_offset,
28999 &end_offset);
29000
29001 slice_length = (duk_size_t) (end_offset - start_offset);
29002 buf_slice = (duk_uint8_t *) duk_push_fixed_buffer_nozero(thr, slice_length); /* all bytes initialized below */
29003 DUK_ASSERT(buf_slice != NULL);
29004
29005 /* Neutered or uncovered, TypeError. */
29006 if (h_this->buf == NULL || !DUK_HBUFOBJ_VALID_BYTEOFFSET_EXCL(h_this, (duk_size_t) start_offset + slice_length)) {
29008 }
29009
29010 /* XXX: ideally we wouldn't make a copy but a view into the buffer for the
29011 * decoding process. Or the decoding helper could be changed to accept
29012 * the slice info (a buffer pointer is NOT a good approach because guaranteeing
29013 * its stability is difficult).
29014 */
29015
29016 DUK_ASSERT(DUK_HBUFOBJ_VALID_BYTEOFFSET_EXCL(h_this, (duk_size_t) start_offset + slice_length));
29017 duk_memcpy_unsafe((void *) buf_slice,
29018 (const void *) (DUK_HBUFOBJ_GET_SLICE_BASE(thr->heap, h_this) + start_offset),
29019 (size_t) slice_length);
29020
29021 /* Use the equivalent of: new TextEncoder().encode(this) to convert the
29022 * string. Result will be valid UTF-8; non-CESU-8 inputs are currently
29023 * interpreted loosely. Value stack convention is a bit odd for now.
29025 duk_replace(thr, 0);
29026 duk_set_top(thr, 1);
29028}
29029#endif /* DUK_USE_BUFFEROBJECT_SUPPORT */
29030
29031/*
29032 * Node.js Buffer.prototype: toJSON()
29033 */
29034
29035#if defined(DUK_USE_BUFFEROBJECT_SUPPORT)
29037 duk_hbufobj *h_this;
29038 duk_uint8_t *buf;
29039 duk_uint_t i, n;
29040 duk_tval *tv;
29041
29042 h_this = duk__require_bufobj_this(thr);
29043 DUK_ASSERT(h_this != NULL);
29044
29045 if (h_this->buf == NULL || !DUK_HBUFOBJ_VALID_SLICE(h_this)) {
29046 /* Serialize uncovered backing buffer as a null; doesn't
29047 * really matter as long we're memory safe.
29048 */
29049 duk_push_null(thr);
29050 return 1;
29051 }
29052
29053 duk_push_object(thr);
29056
29057 /* XXX: uninitialized would be OK */
29059 tv = duk_push_harray_with_size_outptr(thr, (duk_uint32_t) h_this->length); /* XXX: needs revision with >4G buffers */
29060 DUK_ASSERT(!duk_is_bare_object(thr, -1));
29061
29062 DUK_ASSERT(h_this->buf != NULL);
29063 buf = DUK_HBUFOBJ_GET_SLICE_BASE(thr->heap, h_this);
29064 for (i = 0, n = h_this->length; i < n; i++) {
29065 DUK_TVAL_SET_U32(tv + i, (duk_uint32_t) buf[i]); /* no need for decref or incref */
29066 }
29069 return 1;
29070}
29071#endif /* DUK_USE_BUFFEROBJECT_SUPPORT */
29072
29073/*
29074 * Node.js Buffer.prototype.equals()
29075 * Node.js Buffer.prototype.compare()
29076 * Node.js Buffer.compare()
29077 */
29078
29079#if defined(DUK_USE_BUFFEROBJECT_SUPPORT)
29081 duk_small_uint_t magic;
29082 duk_hbufobj *h_bufarg1;
29083 duk_hbufobj *h_bufarg2;
29084 duk_small_int_t comp_res;
29085
29086 /* XXX: keep support for plain buffers and non-Node.js buffers? */
29087
29089 if (magic & 0x02U) {
29090 /* Static call style. */
29091 h_bufarg1 = duk__require_bufobj_value(thr, 0);
29092 h_bufarg2 = duk__require_bufobj_value(thr, 1);
29093 } else {
29094 h_bufarg1 = duk__require_bufobj_this(thr);
29095 h_bufarg2 = duk__require_bufobj_value(thr, 0);
29096 }
29097 DUK_ASSERT(h_bufarg1 != NULL);
29098 DUK_ASSERT(h_bufarg2 != NULL);
29099
29100 /* We want to compare the slice/view areas of the arguments.
29101 * If either slice/view is invalid (underlying buffer is shorter)
29102 * ensure equals() is false, but otherwise the only thing that
29103 * matters is to be memory safe.
29104 */
29105
29106 if (DUK_HBUFOBJ_VALID_SLICE(h_bufarg1) && DUK_HBUFOBJ_VALID_SLICE(h_bufarg2)) {
29107 comp_res = duk_js_data_compare(
29108 (const duk_uint8_t *) DUK_HBUFFER_GET_DATA_PTR(thr->heap, h_bufarg1->buf) + h_bufarg1->offset,
29109 (const duk_uint8_t *) DUK_HBUFFER_GET_DATA_PTR(thr->heap, h_bufarg2->buf) + h_bufarg2->offset,
29110 (duk_size_t) h_bufarg1->length,
29111 (duk_size_t) h_bufarg2->length);
29112 } else {
29113 comp_res = -1; /* either nonzero value is ok */
29114 }
29115
29116 if (magic & 0x01U) {
29117 /* compare: similar to string comparison but for buffer data. */
29118 duk_push_int(thr, comp_res);
29119 } else {
29120 /* equals */
29121 duk_push_boolean(thr, (comp_res == 0));
29122 }
29123
29124 return 1;
29125}
29126#endif /* DUK_USE_BUFFEROBJECT_SUPPORT */
29127
29128/*
29129 * Node.js Buffer.prototype.fill()
29130 */
29131
29132#if defined(DUK_USE_BUFFEROBJECT_SUPPORT)
29134 duk_hbufobj *h_this;
29135 const duk_uint8_t *fill_str_ptr;
29136 duk_size_t fill_str_len;
29137 duk_uint8_t fill_value;
29138 duk_int_t fill_offset;
29139 duk_int_t fill_end;
29140 duk_size_t fill_length;
29141 duk_uint8_t *p;
29142
29143 h_this = duk__require_bufobj_this(thr);
29144 DUK_ASSERT(h_this != NULL);
29145 if (h_this->buf == NULL) {
29147 }
29148
29149 /* [ value offset end ] */
29150
29151 if (duk_is_string_notsymbol(thr, 0)) {
29152 fill_str_ptr = (const duk_uint8_t *) duk_get_lstring(thr, 0, &fill_str_len);
29153 DUK_ASSERT(fill_str_ptr != NULL);
29154 } else {
29155 /* Symbols get ToNumber() coerced and cause TypeError. */
29156 fill_value = (duk_uint8_t) duk_to_uint32(thr, 0);
29157 fill_str_ptr = (const duk_uint8_t *) &fill_value;
29158 fill_str_len = 1;
29159 }
29160
29161 /* Fill offset handling is more lenient than in Node.js. */
29162
29164 (duk_int_t) h_this->length,
29165 1 /*idx_start*/,
29166 2 /*idx_end*/,
29167 &fill_offset,
29168 &fill_end);
29169
29170 DUK_DDD(DUK_DDDPRINT("fill: fill_value=%02x, fill_offset=%ld, fill_end=%ld, view length=%ld",
29171 (unsigned int) fill_value,
29172 (long) fill_offset,
29173 (long) fill_end,
29174 (long) h_this->length));
29175
29176 DUK_ASSERT(fill_end - fill_offset >= 0);
29177 DUK_ASSERT(h_this->buf != NULL);
29178
29179 p = (DUK_HBUFOBJ_GET_SLICE_BASE(thr->heap, h_this) + fill_offset);
29180 fill_length = (duk_size_t) (fill_end - fill_offset);
29181 if (fill_str_len == 1) {
29182 /* Handle single character fills as memset() even when
29183 * the fill data comes from a one-char argument.
29184 */
29185 duk_memset_unsafe((void *) p, (int) fill_str_ptr[0], (size_t) fill_length);
29186 } else if (fill_str_len > 1) {
29187 duk_size_t i, n, t;
29188
29189 for (i = 0, n = (duk_size_t) (fill_end - fill_offset), t = 0; i < n; i++) {
29190 p[i] = fill_str_ptr[t++];
29191 if (t >= fill_str_len) {
29192 t = 0;
29193 }
29194 }
29195 } else {
29196 DUK_DDD(DUK_DDDPRINT("zero size fill pattern, ignore silently"));
29197 }
29199 /* Return the Buffer to allow chaining: b.fill(0x11).fill(0x22, 3, 5).toString() */
29200 duk_push_this(thr);
29201 return 1;
29202}
29203#endif /* DUK_USE_BUFFEROBJECT_SUPPORT */
29204
29205/*
29206 * Node.js Buffer.prototype.write(string, [offset], [length], [encoding])
29207 */
29208
29209#if defined(DUK_USE_BUFFEROBJECT_SUPPORT)
29211 duk_hbufobj *h_this;
29212 duk_uint_t offset;
29213 duk_uint_t length;
29214 const duk_uint8_t *str_data;
29215 duk_size_t str_len;
29216
29217 /* XXX: very inefficient support for plain buffers */
29218 h_this = duk__require_bufobj_this(thr);
29219 DUK_ASSERT(h_this != NULL);
29220
29221 /* Argument must be a string, e.g. a buffer is not allowed. */
29222 str_data = (const duk_uint8_t *) duk_require_lstring_notsymbol(thr, 0, &str_len);
29223
29224 duk__resolve_offset_opt_length(thr, h_this, 1, 2, &offset, &length, 0 /*throw_flag*/);
29225 DUK_ASSERT(offset <= h_this->length);
29226 DUK_ASSERT(offset + length <= h_this->length);
29227
29228 /* XXX: encoding is ignored now. */
29229
29230 if (length > str_len) {
29231 length = (duk_uint_t) str_len;
29232 }
29233
29234 if (DUK_HBUFOBJ_VALID_SLICE(h_this)) {
29235 /* Cannot overlap. */
29236 duk_memcpy_unsafe((void *) (DUK_HBUFOBJ_GET_SLICE_BASE(thr->heap, h_this) + offset),
29237 (const void *) str_data,
29238 (size_t) length);
29239 } else {
29240 DUK_DDD(DUK_DDDPRINT("write() target buffer is not covered, silent ignore"));
29242
29243 duk_push_uint(thr, length);
29244 return 1;
29245}
29246#endif /* DUK_USE_BUFFEROBJECT_SUPPORT */
29247
29248/*
29249 * Node.js Buffer.prototype.copy()
29250 */
29251
29252#if defined(DUK_USE_BUFFEROBJECT_SUPPORT)
29254 duk_hbufobj *h_this;
29255 duk_hbufobj *h_bufarg;
29256 duk_int_t source_length;
29257 duk_int_t target_length;
29258 duk_int_t target_start, source_start, source_end;
29259 duk_uint_t target_ustart, source_ustart, source_uend;
29260 duk_uint_t copy_size = 0;
29261
29262 /* [ targetBuffer targetStart sourceStart sourceEnd ] */
29263
29264 h_this = duk__require_bufobj_this(thr);
29265 h_bufarg = duk__require_bufobj_value(thr, 0);
29266 DUK_ASSERT(h_this != NULL);
29267 DUK_ASSERT(h_bufarg != NULL);
29268 source_length = (duk_int_t) h_this->length;
29269 target_length = (duk_int_t) h_bufarg->length;
29270
29271 target_start = duk_to_int(thr, 1);
29272 source_start = duk_to_int(thr, 2);
29273 if (duk_is_undefined(thr, 3)) {
29274 source_end = source_length;
29275 } else {
29276 source_end = duk_to_int(thr, 3);
29277 }
29278
29279 DUK_DDD(DUK_DDDPRINT("checking copy args: target_start=%ld, target_length=%ld, "
29280 "source_start=%ld, source_end=%ld, source_length=%ld",
29281 (long) target_start,
29282 (long) h_bufarg->length,
29283 (long) source_start,
29284 (long) source_end,
29285 (long) source_length));
29286
29287 /* This behavior mostly mimics Node.js now. */
29288
29289 if (source_start < 0 || source_end < 0 || target_start < 0) {
29290 /* Negative offsets cause a RangeError. */
29291 goto fail_bounds;
29292 }
29293 source_ustart = (duk_uint_t) source_start;
29294 source_uend = (duk_uint_t) source_end;
29295 target_ustart = (duk_uint_t) target_start;
29296 if (source_ustart >= source_uend || /* crossed offsets or zero size */
29297 source_ustart >= (duk_uint_t) source_length || /* source out-of-bounds (but positive) */
29298 target_ustart >= (duk_uint_t) target_length) { /* target out-of-bounds (but positive) */
29299 goto silent_ignore;
29300 }
29301 if (source_uend >= (duk_uint_t) source_length) {
29302 /* Source end clamped silently to available length. */
29303 source_uend = (duk_uint_t) source_length;
29304 }
29305 copy_size = source_uend - source_ustart;
29306 if (target_ustart + copy_size > (duk_uint_t) target_length) {
29307 /* Clamp to target's end if too long.
29308 *
29309 * NOTE: there's no overflow possibility in the comparison;
29310 * both target_ustart and copy_size are >= 0 and based on
29311 * values in duk_int_t range. Adding them as duk_uint_t
29312 * values is then guaranteed not to overflow.
29313 */
29314 DUK_ASSERT(target_ustart + copy_size >= target_ustart); /* no overflow */
29315 DUK_ASSERT(target_ustart + copy_size >= copy_size); /* no overflow */
29316 copy_size = (duk_uint_t) target_length - target_ustart;
29317 }
29318
29319 DUK_DDD(DUK_DDDPRINT("making copy: target_ustart=%lu source_ustart=%lu copy_size=%lu",
29320 (unsigned long) target_ustart,
29321 (unsigned long) source_ustart,
29322 (unsigned long) copy_size));
29323
29324 DUK_ASSERT(copy_size >= 1);
29325 DUK_ASSERT(source_ustart <= (duk_uint_t) source_length);
29326 DUK_ASSERT(source_ustart + copy_size <= (duk_uint_t) source_length);
29327 DUK_ASSERT(target_ustart <= (duk_uint_t) target_length);
29328 DUK_ASSERT(target_ustart + copy_size <= (duk_uint_t) target_length);
29329
29330 /* Ensure copy is covered by underlying buffers. */
29331 DUK_ASSERT(h_bufarg->buf != NULL); /* length check */
29332 DUK_ASSERT(h_this->buf != NULL); /* length check */
29333 if (DUK_HBUFOBJ_VALID_BYTEOFFSET_EXCL(h_bufarg, target_ustart + copy_size) &&
29334 DUK_HBUFOBJ_VALID_BYTEOFFSET_EXCL(h_this, source_ustart + copy_size)) {
29335 /* Must use memmove() because copy area may overlap (source and target
29336 * buffer may be the same, or from different slices.
29337 */
29338 duk_memmove_unsafe((void *) (DUK_HBUFOBJ_GET_SLICE_BASE(thr->heap, h_bufarg) + target_ustart),
29339 (const void *) (DUK_HBUFOBJ_GET_SLICE_BASE(thr->heap, h_this) + source_ustart),
29340 (size_t) copy_size);
29341 } else {
29342 DUK_DDD(DUK_DDDPRINT("buffer copy not covered by underlying buffer(s), ignoring"));
29343 }
29344
29345silent_ignore:
29346 /* Return value is like write(), number of bytes written.
29347 * The return value matters because of code like:
29348 * "off += buf.copy(...)".
29349 */
29350 duk_push_uint(thr, copy_size);
29351 return 1;
29352
29353fail_bounds:
29355}
29356#endif /* DUK_USE_BUFFEROBJECT_SUPPORT */
29357
29358/*
29359 * TypedArray.prototype.set()
29360 *
29361 * TypedArray set() is pretty interesting to implement because:
29362 *
29363 * - The source argument may be a plain array or a typedarray. If the
29364 * source is a TypedArray, values are decoded and re-encoded into the
29365 * target (not as a plain byte copy). This may happen even when the
29366 * element byte size is the same, e.g. integer values may be re-encoded
29367 * into floats.
29368 *
29369 * - Source and target may refer to the same underlying buffer, so that
29370 * the set() operation may overlap. The specification requires that this
29371 * must work as if a copy was made before the operation. Note that this
29372 * is NOT a simple memmove() situation because the source and target
29373 * byte sizes may be different -- e.g. a 4-byte source (Int8Array) may
29374 * expand to a 16-byte target (Uint32Array) so that the target overlaps
29375 * the source both from beginning and the end (unlike in typical memmove).
29376 *
29377 * - Even if 'buf' pointers of the source and target differ, there's no
29378 * guarantee that their memory areas don't overlap. This may be the
29379 * case with external buffers.
29380 *
29381 * Even so, it is nice to optimize for the common case:
29382 *
29383 * - Source and target separate buffers or non-overlapping.
29384 *
29385 * - Source and target have a compatible type so that a plain byte copy
29386 * is possible. Note that while e.g. uint8 and int8 are compatible
29387 * (coercion one way or another doesn't change the byte representation),
29388 * e.g. int8 and uint8clamped are NOT compatible when writing int8
29389 * values into uint8clamped typedarray (-1 would clamp to 0 for instance).
29390 *
29391 * See test-bi-typedarray-proto-set.js.
29392 */
29393
29394#if defined(DUK_USE_BUFFEROBJECT_SUPPORT)
29396 duk_hbufobj *h_this;
29397 duk_hobject *h_obj;
29398 duk_uarridx_t i, n;
29399 duk_int_t offset_signed;
29400 duk_uint_t offset_elems;
29401 duk_uint_t offset_bytes;
29402
29403 h_this = duk__require_bufobj_this(thr);
29404 DUK_ASSERT(h_this != NULL);
29406
29407 if (h_this->buf == NULL) {
29408 DUK_DDD(DUK_DDDPRINT("source neutered, skip copy"));
29409 return 0;
29410 }
29411
29413 h_obj = duk_require_hobject(thr, 0);
29414
29415 /* XXX: V8 throws a TypeError for negative values. Would it
29416 * be more useful to interpret negative offsets here from the
29417 * end of the buffer too?
29418 */
29419 offset_signed = duk_to_int(thr, 1);
29420 if (offset_signed < 0) {
29421 /* For some reason this is a TypeError (at least in V8). */
29423 }
29424 offset_elems = (duk_uint_t) offset_signed;
29425 offset_bytes = offset_elems << h_this->shift;
29426 if ((offset_bytes >> h_this->shift) != offset_elems) {
29427 /* Byte length would overflow. */
29428 /* XXX: easier check with less code? */
29429 goto fail_args;
29430 }
29431 if (offset_bytes > h_this->length) {
29432 /* Equality may be OK but >length not. Checking
29433 * this explicitly avoids some overflow cases
29434 * below.
29435 */
29436 goto fail_args;
29437 }
29438 DUK_ASSERT(offset_bytes <= h_this->length);
29439
29440 /* Fast path: source is a TypedArray (or any bufobj). */
29441
29442 if (DUK_HOBJECT_IS_BUFOBJ(h_obj)) {
29443 duk_hbufobj *h_bufarg;
29444#if !defined(DUK_USE_PREFER_SIZE)
29445 duk_uint16_t comp_mask;
29446#endif
29447 duk_small_int_t no_overlap = 0;
29448 duk_uint_t src_length;
29449 duk_uint_t dst_length;
29450 duk_uint_t dst_length_elems;
29451 duk_uint8_t *p_src_base;
29452 duk_uint8_t *p_src_end;
29453 duk_uint8_t *p_src;
29454 duk_uint8_t *p_dst_base;
29455 duk_uint8_t *p_dst;
29456 duk_small_uint_t src_elem_size;
29457 duk_small_uint_t dst_elem_size;
29458
29459 h_bufarg = (duk_hbufobj *) h_obj;
29460 DUK_HBUFOBJ_ASSERT_VALID(h_bufarg);
29461
29462 if (h_bufarg->buf == NULL) {
29463 DUK_DDD(DUK_DDDPRINT("target neutered, skip copy"));
29464 return 0;
29465 }
29466
29467 /* Nominal size check. */
29468 src_length = h_bufarg->length; /* bytes in source */
29469 dst_length_elems = (src_length >> h_bufarg->shift); /* elems in source and dest */
29470 dst_length = dst_length_elems << h_this->shift; /* bytes in dest */
29471 if ((dst_length >> h_this->shift) != dst_length_elems) {
29472 /* Byte length would overflow. */
29473 /* XXX: easier check with less code? */
29474 goto fail_args;
29475 }
29476 DUK_DDD(DUK_DDDPRINT("nominal size check: src_length=%ld, dst_length=%ld", (long) src_length, (long) dst_length));
29477 DUK_ASSERT(offset_bytes <= h_this->length);
29478 if (dst_length > h_this->length - offset_bytes) {
29479 /* Overflow not an issue because subtraction is used on the right
29480 * side and guaranteed to be >= 0.
29481 */
29482 DUK_DDD(DUK_DDDPRINT("copy exceeds target buffer nominal length"));
29483 goto fail_args;
29484 }
29485 if (!DUK_HBUFOBJ_VALID_BYTEOFFSET_EXCL(h_this, offset_bytes + dst_length)) {
29486 DUK_DDD(DUK_DDDPRINT("copy not covered by underlying target buffer, ignore"));
29487 return 0;
29488 }
29489
29490 p_src_base = DUK_HBUFOBJ_GET_SLICE_BASE(thr->heap, h_bufarg);
29491 p_dst_base = DUK_HBUFOBJ_GET_SLICE_BASE(thr->heap, h_this) + offset_bytes;
29492
29493 /* Check actual underlying buffers for validity and that they
29494 * cover the copy. No side effects are allowed after the check
29495 * so that the validity status doesn't change.
29496 */
29497 if (!DUK_HBUFOBJ_VALID_SLICE(h_this) || !DUK_HBUFOBJ_VALID_SLICE(h_bufarg)) {
29498 /* The condition could be more narrow and check for the
29499 * copy area only, but there's no need for fine grained
29500 * behavior when the underlying buffer is misconfigured.
29501 */
29502 DUK_DDD(DUK_DDDPRINT("source and/or target not covered by underlying buffer, skip copy"));
29503 return 0;
29504 }
29505
29506 /* We want to do a straight memory copy if possible: this is
29507 * an important operation because .set() is the TypedArray
29508 * way to copy chunks of memory. However, because set()
29509 * conceptually works in terms of elements, not all views are
29510 * compatible with direct byte copying.
29511 *
29512 * If we do manage a direct copy, the "overlap issue" handled
29513 * below can just be solved using memmove() because the source
29514 * and destination element sizes are necessarily equal.
29515 */
29516
29517#if !defined(DUK_USE_PREFER_SIZE)
29518 DUK_ASSERT(h_this->elem_type < sizeof(duk__buffer_elemtype_copy_compatible) / sizeof(duk_uint16_t));
29520 if (comp_mask & (1 << h_bufarg->elem_type)) {
29521 DUK_ASSERT(src_length == dst_length);
29522
29523 DUK_DDD(DUK_DDDPRINT("fast path: able to use memmove() because views are compatible"));
29524 duk_memmove_unsafe((void *) p_dst_base, (const void *) p_src_base, (size_t) dst_length);
29525 return 0;
29526 }
29527 DUK_DDD(DUK_DDDPRINT("fast path: views are not compatible with a byte copy, copy by item"));
29528#endif /* !DUK_USE_PREFER_SIZE */
29529
29530 /* We want to avoid making a copy to process set() but that's
29531 * not always possible: the source and the target may overlap
29532 * and because element sizes are different, the overlap cannot
29533 * always be handled with a memmove() or choosing the copy
29534 * direction in a certain way. For example, if source type is
29535 * uint8 and target type is uint32, the target area may exceed
29536 * the source area from both ends!
29537 *
29538 * Note that because external buffers may point to the same
29539 * memory areas, we must ultimately make this check using
29540 * pointers.
29541 *
29542 * NOTE: careful with side effects: any side effect may cause
29543 * a buffer resize (or external buffer pointer/length update)!
29544 */
29545
29546 DUK_DDD(DUK_DDDPRINT("overlap check: p_src_base=%p, src_length=%ld, "
29547 "p_dst_base=%p, dst_length=%ld",
29548 (void *) p_src_base,
29549 (long) src_length,
29550 (void *) p_dst_base,
29551 (long) dst_length));
29552
29553 if (p_src_base >= p_dst_base + dst_length || /* source starts after dest ends */
29554 p_src_base + src_length <= p_dst_base) { /* source ends before dest starts */
29555 no_overlap = 1;
29556 }
29557
29558 if (!no_overlap) {
29559 /* There's overlap: the desired end result is that
29560 * conceptually a copy is made to avoid "trampling"
29561 * of source data by destination writes. We make
29562 * an actual temporary copy to handle this case.
29563 */
29564 duk_uint8_t *p_src_copy;
29565
29566 DUK_DDD(DUK_DDDPRINT("there is overlap, make a copy of the source"));
29567 p_src_copy = (duk_uint8_t *) duk_push_fixed_buffer_nozero(thr, src_length);
29568 DUK_ASSERT(p_src_copy != NULL);
29569 duk_memcpy_unsafe((void *) p_src_copy, (const void *) p_src_base, (size_t) src_length);
29570
29571 p_src_base = p_src_copy; /* use p_src_base from now on */
29572 }
29573 /* Value stack intentionally mixed size here. */
29574
29575 DUK_DDD(DUK_DDDPRINT("after overlap check: p_src_base=%p, src_length=%ld, "
29576 "p_dst_base=%p, dst_length=%ld, valstack top=%ld",
29577 (void *) p_src_base,
29578 (long) src_length,
29579 (void *) p_dst_base,
29580 (long) dst_length,
29581 (long) duk_get_top(thr)));
29582
29583 /* Ready to make the copy. We must proceed element by element
29584 * and must avoid any side effects that might cause the buffer
29585 * validity check above to become invalid.
29586 *
29587 * Although we work through the value stack here, only plain
29588 * numbers are handled which should be side effect safe.
29589 */
29590
29591 src_elem_size = (duk_small_uint_t) (1U << h_bufarg->shift);
29592 dst_elem_size = (duk_small_uint_t) (1U << h_this->shift);
29593 p_src = p_src_base;
29594 p_dst = p_dst_base;
29595 p_src_end = p_src_base + src_length;
29596
29597 while (p_src != p_src_end) {
29598 DUK_DDD(DUK_DDDPRINT("fast path per element copy loop: "
29599 "p_src=%p, p_src_end=%p, p_dst=%p",
29600 (void *) p_src,
29601 (void *) p_src_end,
29602 (void *) p_dst));
29603 /* A validated read() is always a number, so it's write coercion
29604 * is always side effect free an won't invalidate pointers etc.
29605 */
29606 duk_hbufobj_push_validated_read(thr, h_bufarg, p_src, src_elem_size);
29607 duk_hbufobj_validated_write(thr, h_this, p_dst, dst_elem_size);
29608 duk_pop(thr);
29609 p_src += src_elem_size;
29610 p_dst += dst_elem_size;
29611 }
29612
29613 return 0;
29614 } else {
29615 /* Slow path: quite slow, but we save space by using the property code
29616 * to write coerce target values. We don't need to worry about overlap
29617 * here because the source is not a TypedArray.
29618 *
29619 * We could use the bufobj write coercion helper but since the
29620 * property read may have arbitrary side effects, full validity checks
29621 * would be needed for every element anyway.
29622 */
29623
29624 n = (duk_uarridx_t) duk_get_length(thr, 0);
29625 DUK_ASSERT(offset_bytes <= h_this->length);
29626 if ((n << h_this->shift) > h_this->length - offset_bytes) {
29627 /* Overflow not an issue because subtraction is used on the right
29628 * side and guaranteed to be >= 0.
29629 */
29630 DUK_DDD(DUK_DDDPRINT("copy exceeds target buffer nominal length"));
29631 goto fail_args;
29632 }
29633
29634 /* There's no need to check for buffer validity status for the
29635 * target here: the property access code will do that for each
29636 * element. Moreover, if we did check the validity here, side
29637 * effects from reading the source argument might invalidate
29638 * the results anyway.
29639 */
29640
29641 DUK_ASSERT_TOP(thr, 2);
29642 duk_push_this(thr);
29643
29644 for (i = 0; i < n; i++) {
29645 duk_get_prop_index(thr, 0, i);
29646 duk_put_prop_index(thr, 2, offset_elems + i);
29647 }
29648 }
29649
29650 return 0;
29651
29652fail_args:
29654}
29655#endif /* DUK_USE_BUFFEROBJECT_SUPPORT */
29656
29657/*
29658 * Node.js Buffer.prototype.slice([start], [end])
29659 * ArrayBuffer.prototype.slice(begin, [end])
29660 * TypedArray.prototype.subarray(begin, [end])
29661 *
29662 * The API calls are almost identical; negative indices are counted from end
29663 * of buffer, and final indices are clamped (allowing crossed indices). Main
29664 * differences:
29665 *
29666 * - Copy/view behavior; Node.js .slice() and TypedArray .subarray() create
29667 * views, ArrayBuffer .slice() creates a copy
29668 *
29669 * - Resulting object has a different class and prototype depending on the
29670 * call (or 'this' argument)
29671 *
29672 * - TypedArray .subarray() arguments are element indices, not byte offsets
29673 *
29674 * - Plain buffer argument creates a plain buffer slice
29675 */
29676
29677#if defined(DUK_USE_BUFFEROBJECT_SUPPORT)
29679 duk_int_t start_offset, end_offset;
29680 duk_uint_t slice_length;
29681 duk_uint8_t *p_copy;
29682 duk_size_t copy_length;
29683
29686 0 /*buffer_shift*/,
29687 0 /*idx_start*/,
29688 1 /*idx_end*/,
29689 &start_offset,
29690 &end_offset);
29691 DUK_ASSERT(end_offset <= (duk_int_t) DUK_HBUFFER_GET_SIZE(h_val));
29692 DUK_ASSERT(start_offset >= 0);
29693 DUK_ASSERT(end_offset >= start_offset);
29694 slice_length = (duk_uint_t) (end_offset - start_offset);
29695
29696 p_copy = (duk_uint8_t *) duk_push_fixed_buffer_nozero(thr, (duk_size_t) slice_length);
29697 DUK_ASSERT(p_copy != NULL);
29698 copy_length = slice_length;
29699
29700 duk_memcpy_unsafe((void *) p_copy,
29701 (const void *) ((duk_uint8_t *) DUK_HBUFFER_GET_DATA_PTR(thr->heap, h_val) + start_offset),
29702 copy_length);
29703}
29704#endif /* DUK_USE_BUFFEROBJECT_SUPPORT */
29705
29706#if defined(DUK_USE_BUFFEROBJECT_SUPPORT)
29707/* Shared helper for slice/subarray operation.
29708 * Magic: 0x01=isView, 0x02=copy, 0x04=Node.js Buffer special handling.
29709 */
29711 duk_small_int_t magic;
29712 duk_small_uint_t res_class_num;
29713 duk_small_int_t res_proto_bidx;
29714 duk_hbufobj *h_this;
29715 duk_hbufobj *h_bufobj;
29716 duk_hbuffer *h_val;
29717 duk_int_t start_offset, end_offset;
29718 duk_uint_t slice_length;
29719 duk_tval *tv;
29720
29721 /* [ start end ] */
29722
29723 magic = duk_get_current_magic(thr);
29724
29726 DUK_ASSERT(tv != NULL);
29727
29728 if (DUK_TVAL_IS_BUFFER(tv)) {
29729 /* For plain buffers return a plain buffer slice. */
29730 h_val = DUK_TVAL_GET_BUFFER(tv);
29731 DUK_ASSERT(h_val != NULL);
29732
29733 if (magic & 0x02) {
29734 /* Make copy: ArrayBuffer.prototype.slice() uses this. */
29735 duk__arraybuffer_plain_slice(thr, h_val);
29736 return 1;
29737 } else {
29738 /* View into existing buffer: cannot be done if the
29739 * result is a plain buffer because there's no slice
29740 * info. So return an ArrayBuffer instance; coerce
29741 * the 'this' binding into an object and behave as if
29742 * the original call was for an Object-coerced plain
29743 * buffer (handled automatically by duk__require_bufobj_this()).
29744 */
29745
29746 DUK_DDD(DUK_DDDPRINT("slice() doesn't handle view into plain buffer, coerce 'this' to ArrayBuffer object"));
29747 /* fall through */
29748 }
29749 }
29750 tv = NULL; /* No longer valid nor needed. */
29751
29752 h_this = duk__require_bufobj_this(thr);
29753
29754 /* Slice offsets are element (not byte) offsets, which only matters
29755 * for TypedArray views, Node.js Buffer and ArrayBuffer have shift
29756 * zero so byte and element offsets are the same. Negative indices
29757 * are counted from end of slice, crossed indices are allowed (and
29758 * result in zero length result), and final values are clamped
29759 * against the current slice. There's intentionally no check
29760 * against the underlying buffer here.
29761 */
29762
29764 (duk_int_t) h_this->length,
29765 (duk_uint8_t) h_this->shift,
29766 0 /*idx_start*/,
29767 1 /*idx_end*/,
29768 &start_offset,
29769 &end_offset);
29770 DUK_ASSERT(end_offset >= start_offset);
29771 DUK_ASSERT(start_offset >= 0);
29772 DUK_ASSERT(end_offset >= 0);
29773 slice_length = (duk_uint_t) (end_offset - start_offset);
29774
29775 /* The resulting buffer object gets the same class and prototype as
29776 * the buffer in 'this', e.g. if the input is a Uint8Array the
29777 * result is a Uint8Array; if the input is a Float32Array, the
29778 * result is a Float32Array. The result internal prototype should
29779 * be the default prototype for the class (e.g. initial value of
29780 * Uint8Array.prototype), not copied from the argument (Duktape 1.x
29781 * did that).
29782 *
29783 * Node.js Buffers have special handling: they're Uint8Arrays as far
29784 * as the internal class is concerned, so the new Buffer should also
29785 * be an Uint8Array but inherit from Buffer.prototype.
29786 */
29787 res_class_num = DUK_HOBJECT_GET_CLASS_NUMBER((duk_hobject *) h_this);
29788 DUK_ASSERT(res_class_num >= DUK_HOBJECT_CLASS_BUFOBJ_MIN); /* type check guarantees */
29789 DUK_ASSERT(res_class_num <= DUK_HOBJECT_CLASS_BUFOBJ_MAX);
29790 res_proto_bidx = duk__buffer_proto_from_classnum[res_class_num - DUK_HOBJECT_CLASS_BUFOBJ_MIN];
29791 if (magic & 0x04) {
29792 res_proto_bidx = DUK_BIDX_NODEJS_BUFFER_PROTOTYPE;
29793 }
29794 h_bufobj =
29797 res_proto_bidx);
29798 DUK_ASSERT(h_bufobj != NULL);
29799
29800 DUK_ASSERT(h_bufobj->length == 0);
29801 h_bufobj->shift = h_this->shift; /* inherit */
29802 h_bufobj->elem_type = h_this->elem_type; /* inherit */
29803 h_bufobj->is_typedarray = magic & 0x01;
29804 DUK_ASSERT(h_bufobj->is_typedarray == 0 || h_bufobj->is_typedarray == 1);
29805
29806 h_val = h_this->buf;
29807 if (h_val == NULL) {
29809 }
29810
29811 if (magic & 0x02) {
29812 /* non-zero: make copy */
29813 duk_uint8_t *p_copy;
29814 duk_size_t copy_length;
29815
29816 p_copy = (duk_uint8_t *) duk_push_fixed_buffer_zero(
29817 thr,
29818 (duk_size_t) slice_length); /* must be zeroed, not all bytes always copied */
29819 DUK_ASSERT(p_copy != NULL);
29820
29821 /* Copy slice, respecting underlying buffer limits; remainder
29822 * is left as zero.
29823 */
29824 copy_length = DUK_HBUFOBJ_CLAMP_BYTELENGTH(h_this, slice_length);
29825 duk_memcpy_unsafe((void *) p_copy,
29826 (const void *) (DUK_HBUFOBJ_GET_SLICE_BASE(thr->heap, h_this) + start_offset),
29827 copy_length);
29828
29829 h_val = duk_known_hbuffer(thr, -1);
29830
29831 h_bufobj->buf = h_val;
29832 DUK_HBUFFER_INCREF(thr, h_val);
29833 h_bufobj->length = slice_length;
29834 DUK_ASSERT(h_bufobj->offset == 0);
29835
29836 duk_pop(thr); /* reachable so pop OK */
29837 } else {
29838 h_bufobj->buf = h_val;
29839 DUK_HBUFFER_INCREF(thr, h_val);
29840 h_bufobj->length = slice_length;
29841 h_bufobj->offset = h_this->offset + (duk_uint_t) start_offset;
29842
29843 /* Copy the .buffer property, needed for TypedArray.prototype.subarray().
29844 *
29845 * XXX: limit copy only for TypedArray classes specifically?
29846 */
29847
29848 DUK_ASSERT(h_bufobj->buf_prop == NULL);
29849 h_bufobj->buf_prop = h_this->buf_prop; /* may be NULL */
29851 }
29852 /* unbalanced stack on purpose */
29853
29854 DUK_HBUFOBJ_ASSERT_VALID(h_bufobj);
29855 return 1;
29856}
29857#endif /* DUK_USE_BUFFEROBJECT_SUPPORT */
29858
29859/*
29860 * Node.js Buffer.isEncoding()
29861 */
29862
29863#if defined(DUK_USE_BUFFEROBJECT_SUPPORT)
29865 const char *encoding;
29866
29867 /* only accept lowercase 'utf8' now. */
29868
29869 encoding = duk_to_string(thr, 0);
29870 DUK_ASSERT(duk_is_string(thr, 0)); /* guaranteed by duk_to_string() */
29871 duk_push_boolean(thr, DUK_STRCMP(encoding, "utf8") == 0);
29872 return 1;
29873}
29874#endif /* DUK_USE_BUFFEROBJECT_SUPPORT */
29875
29876/*
29877 * Node.js Buffer.isBuffer()
29878 */
29879
29880#if defined(DUK_USE_BUFFEROBJECT_SUPPORT)
29882 duk_hobject *h;
29883 duk_hobject *h_proto;
29884 duk_bool_t ret = 0;
29885
29886 DUK_ASSERT(duk_get_top(thr) >= 1); /* nargs */
29887 h = duk_get_hobject(thr, 0);
29888 if (h != NULL) {
29890 DUK_ASSERT(h_proto != NULL);
29891
29892 h = DUK_HOBJECT_GET_PROTOTYPE(thr->heap, h);
29893 if (h != NULL) {
29894 ret = duk_hobject_prototype_chain_contains(thr, h, h_proto, 0 /*ignore_loop*/);
29895 }
29897
29898 duk_push_boolean(thr, ret);
29899 return 1;
29900}
29901#endif /* DUK_USE_BUFFEROBJECT_SUPPORT */
29902
29903/*
29904 * Node.js Buffer.byteLength()
29905 */
29906
29907#if defined(DUK_USE_BUFFEROBJECT_SUPPORT)
29909 const char *str;
29910 duk_size_t len;
29911
29912 /* At the moment Buffer(<str>) will just use the string bytes as
29913 * is (ignoring encoding), so we return the string length here
29914 * unconditionally.
29915 */
29916
29917 /* XXX: to be revised; Old Node.js behavior just coerces any buffer
29918 * values to string:
29919 * $ node
29920 * > Buffer.byteLength(new Uint32Array(10))
29921 * 20
29922 * > Buffer.byteLength(new Uint32Array(100))
29923 * 20
29924 * (The 20 comes from '[object Uint32Array]'.length
29925 */
29926
29927 str = duk_to_lstring(thr, 0, &len);
29928 DUK_UNREF(str);
29929 duk_push_size_t(thr, len);
29930 return 1;
29931}
29932#endif /* DUK_USE_BUFFEROBJECT_SUPPORT */
29933
29934/*
29935 * Node.js Buffer.concat()
29936 */
29937
29938#if defined(DUK_USE_BUFFEROBJECT_SUPPORT)
29940 duk_hobject *h_arg;
29941 duk_uint_t total_length;
29942 duk_hbufobj *h_bufobj;
29943 duk_hbufobj *h_bufres;
29944 duk_hbuffer *h_val;
29945 duk_uint_t i, n;
29946 duk_uint8_t *p;
29947 duk_size_t space_left;
29948 duk_size_t copy_size;
29949
29950 /* Node.js accepts only actual Arrays. */
29951 h_arg = duk_require_hobject(thr, 0);
29954 }
29955
29956 /* Compute result length and validate argument buffers. */
29957 n = (duk_uint_t) duk_get_length(thr, 0);
29958 total_length = 0;
29959 for (i = 0; i < n; i++) {
29960 /* Neutered checks not necessary here: neutered buffers have
29961 * zero 'length' so we'll effectively skip them.
29962 */
29963 DUK_ASSERT_TOP(thr, 2); /* [ array totalLength ] */
29964 duk_get_prop_index(thr, 0, (duk_uarridx_t) i); /* -> [ array totalLength buf ] */
29965 h_bufobj = duk__require_bufobj_value(thr, 2);
29966 DUK_ASSERT(h_bufobj != NULL);
29967 total_length += h_bufobj->length;
29968 if (DUK_UNLIKELY(total_length < h_bufobj->length)) {
29969 DUK_DCERROR_RANGE_INVALID_ARGS(thr); /* Wrapped. */
29970 }
29971 duk_pop(thr);
29972 }
29973 /* In Node.js v0.12.1 a 1-element array is special and won't create a
29974 * copy, this was fixed later so an explicit check no longer needed.
29975 */
29976
29977 /* User totalLength overrides a computed length, but we'll check
29978 * every copy in the copy loop. Note that duk_to_int() can
29979 * technically have arbitrary side effects so we need to recheck
29980 * the buffers in the copy loop.
29981 */
29982 if (!duk_is_undefined(thr, 1) && n > 0) {
29983 /* For n == 0, Node.js ignores totalLength argument and
29984 * returns a zero length buffer.
29985 */
29986 duk_int_t total_length_signed;
29987 total_length_signed = duk_to_int(thr, 1);
29988 if (total_length_signed < 0) {
29990 }
29991 total_length = (duk_uint_t) total_length_signed;
29992 }
29993
29994 h_bufres = duk_push_bufobj_raw(thr,
29998 DUK_ASSERT(h_bufres != NULL);
29999
30000 p = (duk_uint8_t *) duk_push_fixed_buffer_zero(thr,
30001 total_length); /* must be zeroed, all bytes not necessarily written over */
30002 DUK_ASSERT(p != NULL);
30003 space_left = (duk_size_t) total_length;
30004
30005 for (i = 0; i < n; i++) {
30006 DUK_ASSERT_TOP(thr, 4); /* [ array totalLength bufres buf ] */
30007
30008 duk_get_prop_index(thr, 0, (duk_uarridx_t) i);
30009 h_bufobj = duk__require_bufobj_value(thr, 4);
30010 DUK_ASSERT(h_bufobj != NULL);
30011
30012 copy_size = h_bufobj->length;
30013 if (copy_size > space_left) {
30014 copy_size = space_left;
30015 }
30016
30017 if (h_bufobj->buf != NULL && DUK_HBUFOBJ_VALID_SLICE(h_bufobj)) {
30018 duk_memcpy_unsafe((void *) p, (const void *) DUK_HBUFOBJ_GET_SLICE_BASE(thr->heap, h_bufobj), copy_size);
30019 } else {
30020 /* Just skip, leaving zeroes in the result. */
30021 ;
30022 }
30023 p += copy_size;
30024 space_left -= copy_size;
30025
30026 duk_pop(thr);
30027 }
30028
30029 h_val = duk_known_hbuffer(thr, -1);
30030
30031 duk__set_bufobj_buffer(thr, h_bufres, h_val);
30032 h_bufres->is_typedarray = 1;
30033 DUK_HBUFOBJ_ASSERT_VALID(h_bufres);
30034
30035 duk_pop(thr); /* pop plain buffer, now reachable through h_bufres */
30036
30037 return 1; /* return h_bufres */
30038}
30039#endif /* DUK_USE_BUFFEROBJECT_SUPPORT */
30040
30041/*
30042 * Shared readfield and writefield methods
30044 * The readfield/writefield methods need support for endianness and field
30045 * types. All offsets are byte based so no offset shifting is needed.
30048#if defined(DUK_USE_BUFFEROBJECT_SUPPORT)
30049/* Format of magic, bits:
30050 * 0...1: field type; 0=uint8, 1=uint16, 2=uint32, 3=float, 4=double, 5=unused, 6=unused, 7=unused
30051 * 3: endianness: 0=little, 1=big
30052 * 4: signed: 1=yes, 0=no
30053 * 5: typedarray: 1=yes, 0=no
30055#define DUK__FLD_8BIT 0
30056#define DUK__FLD_16BIT 1
30057#define DUK__FLD_32BIT 2
30058#define DUK__FLD_FLOAT 3
30059#define DUK__FLD_DOUBLE 4
30060#define DUK__FLD_VARINT 5
30061#define DUK__FLD_BIGENDIAN (1 << 3)
30062#define DUK__FLD_SIGNED (1 << 4)
30063#define DUK__FLD_TYPEDARRAY (1 << 5)
30064
30065/* XXX: split into separate functions for each field type? */
30068 duk_small_uint_t magic_ftype;
30069 duk_small_uint_t magic_bigendian;
30070 duk_small_uint_t magic_signed;
30071 duk_small_uint_t magic_typedarray;
30072 duk_small_uint_t endswap;
30073 duk_hbufobj *h_this;
30074 duk_bool_t no_assert;
30075 duk_int_t offset_signed;
30076 duk_uint_t offset;
30077 duk_uint_t buffer_length;
30078 duk_uint_t check_length;
30079 duk_uint8_t *buf;
30081
30082 magic_ftype = magic & 0x0007U;
30083 magic_bigendian = magic & 0x0008U;
30084 magic_signed = magic & 0x0010U;
30085 magic_typedarray = magic & 0x0020U;
30086
30087 h_this = duk__require_bufobj_this(thr); /* XXX: very inefficient for plain buffers */
30088 DUK_ASSERT(h_this != NULL);
30089 buffer_length = h_this->length;
30090
30091 /* [ offset noAssert ], when ftype != DUK__FLD_VARINT */
30092 /* [ offset fieldByteLength noAssert ], when ftype == DUK__FLD_VARINT */
30093 /* [ offset littleEndian ], when DUK__FLD_TYPEDARRAY (regardless of ftype) */
30094
30095 /* Handle TypedArray vs. Node.js Buffer arg differences */
30096 if (magic_typedarray) {
30097 no_assert = 0;
30098#if defined(DUK_USE_INTEGER_LE)
30099 endswap = !duk_to_boolean(thr, 1); /* 1=little endian */
30100#else
30101 endswap = duk_to_boolean(thr, 1); /* 1=little endian */
30102#endif
30103 } else {
30104 no_assert = duk_to_boolean(thr, (magic_ftype == DUK__FLD_VARINT) ? 2 : 1);
30105#if defined(DUK_USE_INTEGER_LE)
30106 endswap = magic_bigendian;
30107#else
30108 endswap = !magic_bigendian;
30109#endif
30110 }
30111
30112 /* Offset is coerced first to signed integer range and then to unsigned.
30113 * This ensures we can add a small byte length (1-8) to the offset in
30114 * bound checks and not wrap.
30115 */
30116 offset_signed = duk_to_int(thr, 0);
30117 offset = (duk_uint_t) offset_signed;
30118 if (offset_signed < 0) {
30119 goto fail_bounds;
30120 }
30121
30122 DUK_DDD(DUK_DDDPRINT("readfield, buffer_length=%ld, offset=%ld, no_assert=%d, "
30123 "magic=%04x, magic_fieldtype=%d, magic_bigendian=%d, magic_signed=%d, "
30124 "endswap=%u",
30125 (long) buffer_length,
30126 (long) offset,
30127 (int) no_assert,
30128 (unsigned int) magic,
30129 (int) magic_ftype,
30130 (int) (magic_bigendian >> 3),
30131 (int) (magic_signed >> 4),
30132 (int) endswap));
30133
30134 /* Update 'buffer_length' to be the effective, safe limit which
30135 * takes into account the underlying buffer. This value will be
30136 * potentially invalidated by any side effect.
30137 */
30138 check_length = DUK_HBUFOBJ_CLAMP_BYTELENGTH(h_this, buffer_length);
30139 DUK_DDD(DUK_DDDPRINT("buffer_length=%ld, check_length=%ld", (long) buffer_length, (long) check_length));
30140
30141 if (h_this->buf) {
30142 buf = DUK_HBUFOBJ_GET_SLICE_BASE(thr->heap, h_this);
30143 } else {
30144 /* Neutered. We could go into the switch-case safely with
30145 * buf == NULL because check_length == 0. To avoid scanbuild
30146 * warnings, fail directly instead.
30147 */
30148 DUK_ASSERT(check_length == 0);
30149 goto fail_neutered;
30150 }
30151 DUK_ASSERT(buf != NULL);
30152
30153 switch (magic_ftype) {
30154 case DUK__FLD_8BIT: {
30155 duk_uint8_t tmp;
30156 if (offset + 1U > check_length) {
30157 goto fail_bounds;
30158 }
30159 tmp = buf[offset];
30160 if (magic_signed) {
30161 duk_push_int(thr, (duk_int_t) ((duk_int8_t) tmp));
30162 } else {
30163 duk_push_uint(thr, (duk_uint_t) tmp);
30164 }
30165 break;
30166 }
30167 case DUK__FLD_16BIT: {
30168 duk_uint16_t tmp;
30169 if (offset + 2U > check_length) {
30170 goto fail_bounds;
30171 }
30172 duk_memcpy((void *) du.uc, (const void *) (buf + offset), 2);
30173 tmp = du.us[0];
30174 if (endswap) {
30175 tmp = DUK_BSWAP16(tmp);
30176 }
30177 if (magic_signed) {
30178 duk_push_int(thr, (duk_int_t) ((duk_int16_t) tmp));
30179 } else {
30180 duk_push_uint(thr, (duk_uint_t) tmp);
30181 }
30182 break;
30183 }
30184 case DUK__FLD_32BIT: {
30185 duk_uint32_t tmp;
30186 if (offset + 4U > check_length) {
30187 goto fail_bounds;
30188 }
30189 duk_memcpy((void *) du.uc, (const void *) (buf + offset), 4);
30190 tmp = du.ui[0];
30191 if (endswap) {
30192 tmp = DUK_BSWAP32(tmp);
30193 }
30194 if (magic_signed) {
30195 duk_push_int(thr, (duk_int_t) ((duk_int32_t) tmp));
30196 } else {
30197 duk_push_uint(thr, (duk_uint_t) tmp);
30198 }
30199 break;
30200 }
30201 case DUK__FLD_FLOAT: {
30202 duk_uint32_t tmp;
30203 if (offset + 4U > check_length) {
30204 goto fail_bounds;
30205 }
30206 duk_memcpy((void *) du.uc, (const void *) (buf + offset), 4);
30207 if (endswap) {
30208 tmp = du.ui[0];
30209 tmp = DUK_BSWAP32(tmp);
30210 du.ui[0] = tmp;
30211 }
30212 duk_push_number(thr, (duk_double_t) du.f[0]);
30213 break;
30214 }
30215 case DUK__FLD_DOUBLE: {
30216 if (offset + 8U > check_length) {
30217 goto fail_bounds;
30218 }
30219 duk_memcpy((void *) du.uc, (const void *) (buf + offset), 8);
30220 if (endswap) {
30222 }
30223 duk_push_number(thr, (duk_double_t) du.d);
30224 break;
30225 }
30226 case DUK__FLD_VARINT: {
30227 /* Node.js Buffer variable width integer field. We don't really
30228 * care about speed here, so aim for shortest algorithm.
30229 */
30230 duk_int_t field_bytelen;
30231 duk_int_t i, i_step, i_end;
30232#if defined(DUK_USE_64BIT_OPS)
30233 duk_int64_t tmp;
30234 duk_small_uint_t shift_tmp;
30235#else
30236 duk_double_t tmp;
30237 duk_small_int_t highbyte;
30238#endif
30239 const duk_uint8_t *p;
30240
30241 field_bytelen = duk_get_int(thr, 1); /* avoid side effects! */
30242 if (field_bytelen < 1 || field_bytelen > 6) {
30243 goto fail_field_length;
30244 }
30245 if (offset + (duk_uint_t) field_bytelen > check_length) {
30246 goto fail_bounds;
30247 }
30248 p = (const duk_uint8_t *) (buf + offset);
30249
30250 /* Slow gathering of value using either 64-bit arithmetic
30251 * or IEEE doubles if 64-bit types not available. Handling
30252 * of negative numbers is a bit non-obvious in both cases.
30253 */
30254
30255 if (magic_bigendian) {
30256 /* Gather in big endian */
30257 i = 0;
30258 i_step = 1;
30259 i_end = field_bytelen; /* one i_step over */
30260 } else {
30261 /* Gather in little endian */
30262 i = field_bytelen - 1;
30263 i_step = -1;
30264 i_end = -1; /* one i_step over */
30265 }
30266
30267#if defined(DUK_USE_64BIT_OPS)
30268 tmp = 0;
30269 do {
30270 DUK_ASSERT(i >= 0 && i < field_bytelen);
30271 tmp = (tmp << 8) + (duk_int64_t) p[i];
30272 i += i_step;
30273 } while (i != i_end);
30274
30275 if (magic_signed) {
30276 /* Shift to sign extend. Left shift must be unsigned
30277 * to avoid undefined behavior; right shift must be
30278 * signed to sign extend properly.
30279 */
30280 shift_tmp = (duk_small_uint_t) (64U - (duk_small_uint_t) field_bytelen * 8U);
30281 tmp = (duk_int64_t) ((duk_uint64_t) tmp << shift_tmp) >> shift_tmp;
30282 }
30283
30284 duk_push_i64(thr, tmp);
30285#else
30286 highbyte = p[i];
30287 if (magic_signed && (highbyte & 0x80) != 0) {
30288 /* 0xff => 255 - 256 = -1; 0x80 => 128 - 256 = -128 */
30289 tmp = (duk_double_t) (highbyte - 256);
30290 } else {
30291 tmp = (duk_double_t) highbyte;
30292 }
30293 for (;;) {
30294 i += i_step;
30295 if (i == i_end) {
30296 break;
30297 }
30298 DUK_ASSERT(i >= 0 && i < field_bytelen);
30299 tmp = (tmp * 256.0) + (duk_double_t) p[i];
30300 }
30301
30302 duk_push_number(thr, tmp);
30303#endif
30304 break;
30305 }
30306 default: { /* should never happen but default here */
30307 goto fail_bounds;
30308 }
30309 }
30310
30311 return 1;
30312
30313fail_neutered:
30314fail_field_length:
30315fail_bounds:
30316 if (no_assert) {
30317 /* Node.js return value for noAssert out-of-bounds reads is
30318 * usually (but not always) NaN. Return NaN consistently.
30319 */
30320 duk_push_nan(thr);
30321 return 1;
30322 }
30324}
30325#endif /* DUK_USE_BUFFEROBJECT_SUPPORT */
30326
30327#if defined(DUK_USE_BUFFEROBJECT_SUPPORT)
30328/* XXX: split into separate functions for each field type? */
30331 duk_small_uint_t magic_ftype;
30332 duk_small_uint_t magic_bigendian;
30333 duk_small_uint_t magic_signed;
30334 duk_small_uint_t magic_typedarray;
30335 duk_small_uint_t endswap;
30336 duk_hbufobj *h_this;
30337 duk_bool_t no_assert;
30338 duk_int_t offset_signed;
30339 duk_uint_t offset;
30340 duk_uint_t buffer_length;
30341 duk_uint_t check_length;
30342 duk_uint8_t *buf;
30344 duk_int_t nbytes = 0;
30345
30346 magic_ftype = magic & 0x0007U;
30347 magic_bigendian = magic & 0x0008U;
30348 magic_signed = magic & 0x0010U;
30349 magic_typedarray = magic & 0x0020U;
30350 DUK_UNREF(magic_signed);
30351
30352 h_this = duk__require_bufobj_this(thr); /* XXX: very inefficient for plain buffers */
30353 DUK_ASSERT(h_this != NULL);
30354 buffer_length = h_this->length;
30355
30356 /* [ value offset noAssert ], when ftype != DUK__FLD_VARINT */
30357 /* [ value offset fieldByteLength noAssert ], when ftype == DUK__FLD_VARINT */
30358 /* [ offset value littleEndian ], when DUK__FLD_TYPEDARRAY (regardless of ftype) */
30359
30360 /* Handle TypedArray vs. Node.js Buffer arg differences */
30361 if (magic_typedarray) {
30362 no_assert = 0;
30363#if defined(DUK_USE_INTEGER_LE)
30364 endswap = !duk_to_boolean(thr, 2); /* 1=little endian */
30365#else
30366 endswap = duk_to_boolean(thr, 2); /* 1=little endian */
30367#endif
30368 duk_swap(thr, 0, 1); /* offset/value order different from Node.js */
30369 } else {
30370 no_assert = duk_to_boolean(thr, (magic_ftype == DUK__FLD_VARINT) ? 3 : 2);
30371#if defined(DUK_USE_INTEGER_LE)
30372 endswap = magic_bigendian;
30373#else
30374 endswap = !magic_bigendian;
30375#endif
30376 }
30377
30378 /* Offset is coerced first to signed integer range and then to unsigned.
30379 * This ensures we can add a small byte length (1-8) to the offset in
30380 * bound checks and not wrap.
30381 */
30382 offset_signed = duk_to_int(thr, 1);
30383 offset = (duk_uint_t) offset_signed;
30384
30385 /* We need 'nbytes' even for a failed offset; return value must be
30386 * (offset + nbytes) even when write fails due to invalid offset.
30387 */
30388 if (magic_ftype != DUK__FLD_VARINT) {
30389 DUK_ASSERT(magic_ftype < (duk_small_uint_t) (sizeof(duk__buffer_nbytes_from_fldtype) / sizeof(duk_uint8_t)));
30390 nbytes = duk__buffer_nbytes_from_fldtype[magic_ftype];
30391 } else {
30392 nbytes = duk_get_int(thr, 2);
30393 if (nbytes < 1 || nbytes > 6) {
30394 goto fail_field_length;
30395 }
30396 }
30397 DUK_ASSERT(nbytes >= 1 && nbytes <= 8);
30398
30399 /* Now we can check offset validity. */
30400 if (offset_signed < 0) {
30401 goto fail_bounds;
30402 }
30403
30404 DUK_DDD(DUK_DDDPRINT("writefield, value=%!T, buffer_length=%ld, offset=%ld, no_assert=%d, "
30405 "magic=%04x, magic_fieldtype=%d, magic_bigendian=%d, magic_signed=%d, "
30406 "endswap=%u",
30407 duk_get_tval(thr, 0),
30408 (long) buffer_length,
30409 (long) offset,
30410 (int) no_assert,
30411 (unsigned int) magic,
30412 (int) magic_ftype,
30413 (int) (magic_bigendian >> 3),
30414 (int) (magic_signed >> 4),
30415 (int) endswap));
30416
30417 /* Coerce value to a number before computing check_length, so that
30418 * the field type specific coercion below can't have side effects
30419 * that would invalidate check_length.
30420 */
30421 duk_to_number(thr, 0);
30422
30423 /* Update 'buffer_length' to be the effective, safe limit which
30424 * takes into account the underlying buffer. This value will be
30425 * potentially invalidated by any side effect.
30426 */
30427 check_length = DUK_HBUFOBJ_CLAMP_BYTELENGTH(h_this, buffer_length);
30428 DUK_DDD(DUK_DDDPRINT("buffer_length=%ld, check_length=%ld", (long) buffer_length, (long) check_length));
30429
30430 if (h_this->buf) {
30431 buf = DUK_HBUFOBJ_GET_SLICE_BASE(thr->heap, h_this);
30432 } else {
30433 /* Neutered. We could go into the switch-case safely with
30434 * buf == NULL because check_length == 0. To avoid scanbuild
30435 * warnings, fail directly instead.
30436 */
30437 DUK_ASSERT(check_length == 0);
30438 goto fail_neutered;
30439 }
30440 DUK_ASSERT(buf != NULL);
30441
30442 switch (magic_ftype) {
30443 case DUK__FLD_8BIT: {
30444 if (offset + 1U > check_length) {
30445 goto fail_bounds;
30446 }
30447 /* sign doesn't matter when writing */
30448 buf[offset] = (duk_uint8_t) duk_to_uint32(thr, 0);
30449 break;
30450 }
30451 case DUK__FLD_16BIT: {
30452 duk_uint16_t tmp;
30453 if (offset + 2U > check_length) {
30454 goto fail_bounds;
30455 }
30456 tmp = (duk_uint16_t) duk_to_uint32(thr, 0);
30457 if (endswap) {
30458 tmp = DUK_BSWAP16(tmp);
30459 }
30460 du.us[0] = tmp;
30461 /* sign doesn't matter when writing */
30462 duk_memcpy((void *) (buf + offset), (const void *) du.uc, 2);
30463 break;
30464 }
30465 case DUK__FLD_32BIT: {
30466 duk_uint32_t tmp;
30467 if (offset + 4U > check_length) {
30468 goto fail_bounds;
30469 }
30470 tmp = (duk_uint32_t) duk_to_uint32(thr, 0);
30471 if (endswap) {
30472 tmp = DUK_BSWAP32(tmp);
30473 }
30474 du.ui[0] = tmp;
30475 /* sign doesn't matter when writing */
30476 duk_memcpy((void *) (buf + offset), (const void *) du.uc, 4);
30477 break;
30478 }
30479 case DUK__FLD_FLOAT: {
30480 duk_uint32_t tmp;
30481 if (offset + 4U > check_length) {
30482 goto fail_bounds;
30483 }
30484 du.f[0] = (duk_float_t) duk_to_number(thr, 0);
30485 if (endswap) {
30486 tmp = du.ui[0];
30487 tmp = DUK_BSWAP32(tmp);
30488 du.ui[0] = tmp;
30489 }
30490 /* sign doesn't matter when writing */
30491 duk_memcpy((void *) (buf + offset), (const void *) du.uc, 4);
30492 break;
30493 }
30494 case DUK__FLD_DOUBLE: {
30495 if (offset + 8U > check_length) {
30496 goto fail_bounds;
30497 }
30498 du.d = (duk_double_t) duk_to_number(thr, 0);
30499 if (endswap) {
30501 }
30502 /* sign doesn't matter when writing */
30503 duk_memcpy((void *) (buf + offset), (const void *) du.uc, 8);
30504 break;
30505 }
30506 case DUK__FLD_VARINT: {
30507 /* Node.js Buffer variable width integer field. We don't really
30508 * care about speed here, so aim for shortest algorithm.
30509 */
30510 duk_int_t field_bytelen;
30511 duk_int_t i, i_step, i_end;
30512#if defined(DUK_USE_64BIT_OPS)
30513 duk_int64_t tmp;
30514#else
30515 duk_double_t tmp;
30516#endif
30517 duk_uint8_t *p;
30518
30519 field_bytelen = (duk_int_t) nbytes;
30520 if (offset + (duk_uint_t) field_bytelen > check_length) {
30521 goto fail_bounds;
30522 }
30523
30524 /* Slow writing of value using either 64-bit arithmetic
30525 * or IEEE doubles if 64-bit types not available. There's
30526 * no special sign handling when writing varints.
30527 */
30528
30529 if (magic_bigendian) {
30530 /* Write in big endian */
30531 i = field_bytelen; /* one i_step added at top of loop */
30532 i_step = -1;
30533 i_end = 0;
30534 } else {
30535 /* Write in little endian */
30536 i = -1; /* one i_step added at top of loop */
30537 i_step = 1;
30538 i_end = field_bytelen - 1;
30539 }
30540
30541 /* XXX: The duk_to_number() cast followed by integer coercion
30542 * is platform specific so NaN, +/- Infinity, and out-of-bounds
30543 * values result in platform specific output now.
30544 * See: test-bi-nodejs-buffer-proto-varint-special.js
30545 */
30546
30547#if defined(DUK_USE_64BIT_OPS)
30548 tmp = (duk_int64_t) duk_to_number(thr, 0);
30549 p = (duk_uint8_t *) (buf + offset);
30550 do {
30551 i += i_step;
30552 DUK_ASSERT(i >= 0 && i < field_bytelen);
30553 p[i] = (duk_uint8_t) (tmp & 0xff);
30554 tmp = tmp >> 8; /* unnecessary shift for last byte */
30555 } while (i != i_end);
30556#else
30557 tmp = duk_to_number(thr, 0);
30558 p = (duk_uint8_t *) (buf + offset);
30559 do {
30560 i += i_step;
30561 tmp = DUK_FLOOR(tmp);
30562 DUK_ASSERT(i >= 0 && i < field_bytelen);
30563 p[i] = (duk_uint8_t) (DUK_FMOD(tmp, 256.0));
30564 tmp = tmp / 256.0; /* unnecessary div for last byte */
30565 } while (i != i_end);
30566#endif
30567 break;
30568 }
30569 default: { /* should never happen but default here */
30570 goto fail_bounds;
30571 }
30572 }
30573
30574 /* Node.js Buffer: return offset + #bytes written (i.e. next
30575 * write offset).
30576 */
30577 if (magic_typedarray) {
30578 /* For TypedArrays 'undefined' return value is specified
30579 * by ES2015 (matches V8).
30580 */
30581 return 0;
30582 }
30583 duk_push_uint(thr, offset + (duk_uint_t) nbytes);
30584 return 1;
30585
30586fail_neutered:
30587fail_field_length:
30588fail_bounds:
30589 if (no_assert) {
30590 /* Node.js return value for failed writes is offset + #bytes
30591 * that would have been written.
30592 */
30593 /* XXX: for negative input offsets, 'offset' will be a large
30594 * positive value so the result here is confusing.
30595 */
30596 if (magic_typedarray) {
30597 return 0;
30598 }
30599 duk_push_uint(thr, offset + (duk_uint_t) nbytes);
30600 return 1;
30601 }
30603}
30604#endif /* DUK_USE_BUFFEROBJECT_SUPPORT */
30605
30606/*
30607 * Accessors for .buffer, .byteLength, .byteOffset
30608 */
30609
30610#if defined(DUK_USE_BUFFEROBJECT_SUPPORT)
30612 duk_hbufobj *h_res;
30613
30614 h_res = duk_push_bufobj_raw(thr,
30618 DUK_ASSERT(h_res != NULL);
30619 DUK_UNREF(h_res);
30620
30621 duk__set_bufobj_buffer(thr, h_res, h_buf);
30623 DUK_ASSERT(h_res->buf_prop == NULL);
30624 return h_res;
30625}
30626
30628 duk_hbufobj *h_bufobj;
30629
30630 h_bufobj = (duk_hbufobj *) duk__getrequire_bufobj_this(thr, DUK__BUFOBJ_FLAG_THROW /*flags*/);
30631 DUK_ASSERT(h_bufobj != NULL);
30632 if (DUK_HEAPHDR_IS_BUFFER((duk_heaphdr *) h_bufobj)) {
30633 DUK_DD(DUK_DDPRINT("autospawn ArrayBuffer for plain buffer"));
30634 (void) duk__autospawn_arraybuffer(thr, (duk_hbuffer *) h_bufobj);
30635 return 1;
30636 } else {
30637 if (h_bufobj->buf_prop == NULL &&
30639 h_bufobj->buf != NULL) {
30640 duk_hbufobj *h_arrbuf;
30641
30642 DUK_DD(DUK_DDPRINT("autospawn ArrayBuffer for typed array or DataView"));
30643 h_arrbuf = duk__autospawn_arraybuffer(thr, h_bufobj->buf);
30644
30645 if (h_bufobj->buf_prop == NULL) {
30646 /* Must recheck buf_prop, in case ArrayBuffer
30647 * alloc had a side effect which already filled
30648 * it!
30649 */
30650
30651 /* Set ArrayBuffer's .byteOffset and .byteLength based
30652 * on the view so that Arraybuffer[view.byteOffset]
30653 * matches view[0].
30654 */
30655 h_arrbuf->offset = 0;
30656 DUK_ASSERT(h_bufobj->offset + h_bufobj->length >= h_bufobj->offset); /* Wrap check on creation. */
30657 h_arrbuf->length = h_bufobj->offset + h_bufobj->length;
30658 DUK_ASSERT(h_arrbuf->buf_prop == NULL);
30659
30660 DUK_ASSERT(h_bufobj->buf_prop == NULL);
30661 h_bufobj->buf_prop = (duk_hobject *) h_arrbuf;
30662 DUK_HBUFOBJ_INCREF(thr, h_arrbuf); /* Now reachable and accounted for. */
30664
30665 /* Left on stack; pushed for the second time below (OK). */
30666 }
30667 if (h_bufobj->buf_prop) {
30668 duk_push_hobject(thr, h_bufobj->buf_prop);
30669 return 1;
30670 }
30671 }
30672 return 0;
30673}
30674
30676 duk_hbufobj *h_bufobj;
30677
30678 h_bufobj = (duk_hbufobj *) duk__getrequire_bufobj_this(thr, DUK__BUFOBJ_FLAG_THROW /*flags*/);
30679 DUK_ASSERT(h_bufobj != NULL);
30680 if (DUK_HEAPHDR_IS_BUFFER((duk_heaphdr *) h_bufobj)) {
30681 duk_push_uint(thr, 0);
30682 } else {
30683 /* If neutered must return 0; offset is zeroed during
30684 * neutering.
30685 */
30686 duk_push_uint(thr, h_bufobj->offset);
30687 }
30688 return 1;
30689}
30690
30692 duk_hbufobj *h_bufobj;
30693
30694 h_bufobj = (duk_hbufobj *) duk__getrequire_bufobj_this(thr, DUK__BUFOBJ_FLAG_THROW /*flags*/);
30695 DUK_ASSERT(h_bufobj != NULL);
30696 if (DUK_HEAPHDR_IS_BUFFER((duk_heaphdr *) h_bufobj)) {
30697 duk_hbuffer *h_buf;
30698
30699 h_buf = (duk_hbuffer *) h_bufobj;
30700 DUK_ASSERT(DUK_HBUFFER_GET_SIZE(h_buf) <= DUK_UINT_MAX); /* Buffer limits. */
30702 } else {
30703 /* If neutered must return 0; length is zeroed during
30704 * neutering.
30705 */
30706 duk_push_uint(thr, h_bufobj->length);
30707 }
30708 return 1;
30709}
30710#else /* DUK_USE_BUFFEROBJECT_SUPPORT */
30711/* No .buffer getter without ArrayBuffer support. */
30712#if 0
30714 return 0;
30715}
30716#endif
30717
30719 duk_push_uint(thr, 0);
30720 return 1;
30721}
30722
30724 duk_hbuffer *h_buf;
30725
30726 /* XXX: helper? */
30727 duk_push_this(thr);
30728 h_buf = duk_require_hbuffer(thr, -1);
30730 return 1;
30731}
30732#endif /* DUK_USE_BUFFEROBJECT_SUPPORT */
30733
30734/* automatic undefs */
30735#undef DUK__BUFOBJ_FLAG_PROMOTE
30736#undef DUK__BUFOBJ_FLAG_THROW
30737#undef DUK__FLD_16BIT
30738#undef DUK__FLD_32BIT
30739#undef DUK__FLD_8BIT
30740#undef DUK__FLD_BIGENDIAN
30741#undef DUK__FLD_DOUBLE
30742#undef DUK__FLD_FLOAT
30743#undef DUK__FLD_SIGNED
30744#undef DUK__FLD_TYPEDARRAY
30745#undef DUK__FLD_VARINT
30746/*
30747 * CBOR bindings.
30748 *
30749 * http://cbor.io/
30750 * https://tools.ietf.org/html/rfc7049
30751 */
30752
30753/* #include duk_internal.h -> already included */
30754
30755#if defined(DUK_USE_CBOR_SUPPORT)
30756
30757/* #define DUK_CBOR_STRESS */
30758
30759/* Default behavior for encoding strings: use CBOR text string if string
30760 * is UTF-8 compatible, otherwise use CBOR byte string. These defines
30761 * can be used to force either type for all strings. Using text strings
30762 * for non-UTF-8 data is technically invalid CBOR.
30764/* #define DUK_CBOR_TEXT_STRINGS */
30765/* #define DUK_CBOR_BYTE_STRINGS */
30767/* Misc. defines. */
30768/* #define DUK_CBOR_PREFER_SIZE */
30769/* #define DUK_CBOR_DOUBLE_AS_IS */
30770/* #define DUK_CBOR_DECODE_FASTPATH */
30772typedef struct {
30774 duk_uint8_t *ptr;
30775 duk_uint8_t *buf;
30776 duk_uint8_t *buf_end;
30778 duk_idx_t idx_buf;
30779 duk_uint_t recursion_depth;
30780 duk_uint_t recursion_limit;
30782
30783typedef struct {
30784 duk_hthread *thr;
30785 const duk_uint8_t *buf;
30786 duk_size_t off;
30788 duk_uint_t recursion_depth;
30789 duk_uint_t recursion_limit;
30791
30794
30795/*
30796 * Misc
30798
30799DUK_LOCAL duk_uint32_t duk__cbor_double_to_uint32(double d) {
30800 /* Out of range casts are undefined behavior, so caller must avoid. */
30801 DUK_ASSERT(d >= 0.0 && d <= 4294967295.0);
30802 return (duk_uint32_t) d;
30803}
30804
30806 * Encoding
30807 */
30808
30810 (void) duk_type_error(enc_ctx->thr, "cbor encode error");
30811}
30812
30814 duk_require_stack(enc_ctx->thr, 4);
30815}
30816
30818 duk_hthread *thr = enc_ctx->thr;
30819
30820 /* Native stack check in object/array recursion. */
30822
30823 /* When working with deeply recursive structures, this is important
30824 * to ensure there's no effective depth limit.
30825 */
30827
30828 DUK_ASSERT(enc_ctx->recursion_depth <= enc_ctx->recursion_limit);
30829 if (enc_ctx->recursion_depth >= enc_ctx->recursion_limit) {
30831 DUK_WO_NORETURN(return;);
30832 }
30833 enc_ctx->recursion_depth++;
30834}
30835
30837 DUK_ASSERT(enc_ctx->recursion_depth > 0);
30838 enc_ctx->recursion_depth--;
30839}
30840
30841/* Check that a size_t is in uint32 range to avoid out-of-range casts. */
30843 if (DUK_UNLIKELY(sizeof(duk_size_t) > sizeof(duk_uint32_t) && len > (duk_size_t) DUK_UINT32_MAX)) {
30844 duk__cbor_encode_error(enc_ctx);
30845 }
30846}
30847
30849 duk_size_t oldlen;
30850 duk_size_t minlen;
30851 duk_size_t newlen;
30852 duk_uint8_t *p_new;
30853 duk_size_t old_data_len;
30854
30855 DUK_ASSERT(enc_ctx->ptr >= enc_ctx->buf);
30856 DUK_ASSERT(enc_ctx->buf_end >= enc_ctx->ptr);
30857 DUK_ASSERT(enc_ctx->buf_end >= enc_ctx->buf);
30858
30859 /* Overflow check.
30860 *
30861 * Limit example: 0xffffffffUL / 2U = 0x7fffffffUL, we reject >= 0x80000000UL.
30862 */
30863 oldlen = enc_ctx->len;
30864 minlen = oldlen + len;
30865 if (DUK_UNLIKELY(oldlen > DUK_SIZE_MAX / 2U || minlen < oldlen)) {
30866 duk__cbor_encode_error(enc_ctx);
30867 }
30868
30869#if defined(DUK_CBOR_STRESS)
30870 newlen = oldlen + 1U;
30871#else
30872 newlen = oldlen * 2U;
30873#endif
30874 DUK_ASSERT(newlen >= oldlen);
30875
30876 if (minlen > newlen) {
30877 newlen = minlen;
30878 }
30879 DUK_ASSERT(newlen >= oldlen);
30880 DUK_ASSERT(newlen >= minlen);
30881 DUK_ASSERT(newlen > 0U);
30883 DUK_DD(DUK_DDPRINT("cbor encode buffer resized to %ld", (long) newlen));
30884
30885 p_new = (duk_uint8_t *) duk_resize_buffer(enc_ctx->thr, enc_ctx->idx_buf, newlen);
30886 DUK_ASSERT(p_new != NULL);
30887 old_data_len = (duk_size_t) (enc_ctx->ptr - enc_ctx->buf);
30888 enc_ctx->buf = p_new;
30889 enc_ctx->buf_end = p_new + newlen;
30890 enc_ctx->ptr = p_new + old_data_len;
30891 enc_ctx->len = newlen;
30892}
30893
30895 if (DUK_LIKELY((duk_size_t) (enc_ctx->buf_end - enc_ctx->ptr) >= len)) {
30896 return;
30897 }
30899}
30900
30902 DUK_ASSERT(enc_ctx->ptr >= enc_ctx->buf);
30903 DUK_ASSERT(enc_ctx->ptr <= enc_ctx->buf_end);
30904 return (duk_size_t) (enc_ctx->buf_end - enc_ctx->ptr);
30905}
30906
30907DUK_LOCAL void duk__cbor_encode_uint32(duk_cbor_encode_context *enc_ctx, duk_uint32_t u, duk_uint8_t base) {
30908 duk_uint8_t *p;
30909
30910 /* Caller must ensure space. */
30911 DUK_ASSERT(duk__cbor_get_reserve(enc_ctx) >= 1 + 4);
30912
30913 p = enc_ctx->ptr;
30914 if (DUK_LIKELY(u <= 23U)) {
30915 *p++ = (duk_uint8_t) (base + (duk_uint8_t) u);
30916 } else if (u <= 0xffUL) {
30917 *p++ = base + 0x18U;
30918 *p++ = (duk_uint8_t) u;
30919 } else if (u <= 0xffffUL) {
30920 *p++ = base + 0x19U;
30921 DUK_RAW_WRITEINC_U16_BE(p, (duk_uint16_t) u);
30922 } else {
30923 *p++ = base + 0x1aU;
30925 }
30926 enc_ctx->ptr = p;
30927}
30928
30929#if defined(DUK_CBOR_DOUBLE_AS_IS)
30931 duk_uint8_t *p;
30932
30933 /* Caller must ensure space. */
30934 DUK_ASSERT(duk__cbor_get_reserve(enc_ctx) >= 1 + 8);
30935
30936 p = enc_ctx->ptr;
30937 *p++ = 0xfbU;
30939 p += 8;
30940 enc_ctx->ptr = p;
30941}
30942#else /* DUK_CBOR_DOUBLE_AS_IS */
30945 duk_uint16_t u16;
30946 duk_int16_t expt;
30947 duk_uint8_t *p;
30948
30950
30951 /* Caller must ensure space. */
30952 DUK_ASSERT(duk__cbor_get_reserve(enc_ctx) >= 1 + 8);
30953
30954 /* Organize into little endian (no-op if platform is little endian). */
30955 u.d = d;
30957
30958 /* Check if 'd' can represented as a normal half-float.
30959 * Denormal half-floats could also be used, but that check
30960 * isn't done now (denormal half-floats are decoded of course).
30961 * So just check exponent range and that at most 10 significant
30962 * bits (excluding implicit leading 1) are used in 'd'.
30963 */
30964 u16 = (((duk_uint16_t) u.uc[7]) << 8) | ((duk_uint16_t) u.uc[6]);
30965 expt = (duk_int16_t) ((u16 & 0x7ff0U) >> 4) - 1023;
30966
30967 if (expt >= -14 && expt <= 15) {
30968 /* Half-float normal exponents (excl. denormals).
30969 *
30970 * 7 6 5 4 3 2 1 0 (LE index)
30971 * double: seeeeeee eeeemmmm mmmmmmmm mmmmmmmm mmmmmmmm mmmmmmmm mmmmmmmm mmmmmmmm
30972 * half: seeeee mmmm mmmmmm00 00000000 00000000 00000000 00000000 00000000
30973 */
30974 duk_bool_t use_half_float;
30975
30976 use_half_float =
30977 (u.uc[0] == 0 && u.uc[1] == 0 && u.uc[2] == 0 && u.uc[3] == 0 && u.uc[4] == 0 && (u.uc[5] & 0x03U) == 0);
30978
30979 if (use_half_float) {
30980 duk_uint32_t t;
30981
30982 expt += 15;
30983 t = (duk_uint32_t) (u.uc[7] & 0x80U) << 8;
30984 t += (duk_uint32_t) expt << 10;
30985 t += ((duk_uint32_t) u.uc[6] & 0x0fU) << 6;
30986 t += ((duk_uint32_t) u.uc[5]) >> 2;
30987
30988 /* seeeeemm mmmmmmmm */
30989 p = enc_ctx->ptr;
30990 *p++ = 0xf9U;
30991 DUK_RAW_WRITEINC_U16_BE(p, (duk_uint16_t) t);
30992 enc_ctx->ptr = p;
30993 return;
30994 }
30995 }
30996
30997 /* Same check for plain float. Also no denormal support here. */
30998 if (expt >= -126 && expt <= 127) {
30999 /* Float normal exponents (excl. denormals).
31000 *
31001 * double: seeeeeee eeeemmmm mmmmmmmm mmmmmmmm mmmmmmmm mmmmmmmm mmmmmmmm mmmmmmmm
31002 * float: seeee eeeemmmm mmmmmmmm mmmmmmmm mmm00000 00000000 00000000 00000000
31003 */
31004 duk_bool_t use_float;
31005 duk_float_t d_float;
31006
31007 /* We could do this explicit mantissa check, but doing
31008 * a double-float-double cast is fine because we've
31009 * already verified that the exponent is in range so
31010 * that the narrower cast is not undefined behavior.
31011 */
31012#if 0
31013 use_float =
31014 (u.uc[0] == 0 && u.uc[1] == 0 && u.uc[2] == 0 && (u.uc[3] & 0xe0U) == 0);
31015#endif
31016 d_float = (duk_float_t) d;
31017 use_float = duk_double_equals((duk_double_t) d_float, d);
31018 if (use_float) {
31019 p = enc_ctx->ptr;
31020 *p++ = 0xfaU;
31021 DUK_RAW_WRITEINC_FLOAT_BE(p, d_float);
31022 enc_ctx->ptr = p;
31023 return;
31024 }
31025 }
31026
31027 /* Special handling for NaN and Inf which we want to encode as
31028 * half-floats. They share the same (maximum) exponent.
31029 */
31030 if (expt == 1024) {
31031 DUK_ASSERT(DUK_ISNAN(d) || DUK_ISINF(d));
31032 p = enc_ctx->ptr;
31033 *p++ = 0xf9U;
31034 if (DUK_ISNAN(d)) {
31035 /* Shortest NaN encoding is using a half-float. Lose the
31036 * exact NaN bits in the process. IEEE double would be
31037 * 7ff8 0000 0000 0000, i.e. a quiet NaN in most architectures
31038 * (https://en.wikipedia.org/wiki/NaN#Encoding). The
31039 * equivalent half float is 7e00.
31040 */
31041 *p++ = 0x7eU;
31042 } else {
31043 /* Shortest +/- Infinity encoding is using a half-float. */
31044 if (DUK_SIGNBIT(d)) {
31045 *p++ = 0xfcU;
31046 } else {
31047 *p++ = 0x7cU;
31048 }
31049 }
31050 *p++ = 0x00U;
31051 enc_ctx->ptr = p;
31052 return;
31053 }
31054
31055 /* Cannot use half-float or float, encode as full IEEE double. */
31056 p = enc_ctx->ptr;
31057 *p++ = 0xfbU;
31059 enc_ctx->ptr = p;
31060}
31061
31063 duk_uint8_t *p;
31064 double d_floor;
31065
31066 /* Integers and floating point values of all types are conceptually
31067 * equivalent in CBOR. Try to always choose the shortest encoding
31068 * which is not always immediately obvious. For example, NaN and Inf
31069 * can be most compactly represented as a half-float (assuming NaN
31070 * bits are not preserved), and 0x1'0000'0000 as a single precision
31071 * float. Shortest forms in preference order (prefer integer over
31072 * float when equal length):
31073 *
31074 * uint 1 byte [0,23] (not -0)
31075 * sint 1 byte [-24,-1]
31076 * uint+1 2 bytes [24,255]
31077 * sint+1 2 bytes [-256,-25]
31078 * uint+2 3 bytes [256,65535]
31079 * sint+2 3 bytes [-65536,-257]
31080 * half-float 3 bytes -0, NaN, +/- Infinity, range [-65504,65504]
31081 * uint+4 5 bytes [65536,4294967295]
31082 * sint+4 5 bytes [-4294967296,-258]
31083 * float 5 bytes range [-(1 - 2^(-24)) * 2^128, (1 - 2^(-24)) * 2^128]
31084 * uint+8 9 bytes [4294967296,18446744073709551615]
31085 * sint+8 9 bytes [-18446744073709551616,-4294967297]
31086 * double 9 bytes
31087 *
31088 * For whole numbers (compatible with integers):
31089 * - 1-byte or 2-byte uint/sint representation is preferred for
31090 * [-256,255].
31091 * - 3-byte uint/sint is preferred for [-65536,65535]. Half floats
31092 * are never preferred because they have the same length.
31093 * - 5-byte uint/sint is preferred for [-4294967296,4294967295].
31094 * Single precision floats are never preferred, and half-floats
31095 * don't reach above the 3-byte uint/sint range so they're never
31096 * preferred.
31097 * - So, for all integers up to signed/unsigned 32-bit range the
31098 * preferred encoding is always an integer uint/sint.
31099 * - For integers above 32 bits the situation is more complicated.
31100 * Half-floats are never useful for them because of their limited
31101 * range, but IEEE single precision floats (5 bytes encoded) can
31102 * represent some integers between the 32-bit and 64-bit ranges
31103 * which require 9 bytes as a uint/sint.
31104 *
31105 * For floating point values not compatible with integers, the
31106 * preferred encoding is quite clear:
31107 * - For +Inf/-Inf use half-float.
31108 * - For NaN use a half-float, assuming NaN bits ("payload") is
31109 * not worth preserving. Duktape doesn't in general guarantee
31110 * preservation of the NaN payload so using a half-float seems
31111 * consistent with that.
31112 * - For remaining values, prefer the shortest form which doesn't
31113 * lose any precision. For normal half-floats and single precision
31114 * floats this is simple: just check exponent and mantissa bits
31115 * using a fixed mask. For denormal half-floats and single
31116 * precision floats the check is a bit more complicated: a normal
31117 * IEEE double can sometimes be represented as a denormal
31118 * half-float or single precision float.
31119 *
31120 * https://en.wikipedia.org/wiki/Half-precision_floating-point_format#IEEE_754_half-precision_binary_floating-point_format:_binary16
31121 */
31122
31123 /* Caller must ensure space. */
31124 DUK_ASSERT(duk__cbor_get_reserve(enc_ctx) >= 1 + 8);
31125
31126 /* Most important path is integers. The floor() test will be true
31127 * for Inf too (but not NaN).
31128 */
31129 d_floor = DUK_FLOOR(d); /* identity if d is +/- 0.0, NaN, or +/- Infinity */
31130 if (DUK_LIKELY(duk_double_equals(d_floor, d) != 0)) {
31131 DUK_ASSERT(!DUK_ISNAN(d)); /* NaN == NaN compares false. */
31132 if (DUK_SIGNBIT(d)) {
31133 if (d >= -4294967296.0) {
31134 d = -1.0 - d;
31135 if (d >= 0.0) {
31136 DUK_ASSERT(d >= 0.0);
31138 return;
31139 }
31140
31141 /* Input was negative zero, d == -1.0 < 0.0.
31142 * Shortest -0 is using half-float.
31143 */
31144 p = enc_ctx->ptr;
31145 *p++ = 0xf9U;
31146 *p++ = 0x80U;
31147 *p++ = 0x00U;
31148 enc_ctx->ptr = p;
31149 return;
31150 }
31151 } else {
31152 if (d <= 4294967295.0) {
31153 /* Positive zero needs no special handling. */
31154 DUK_ASSERT(d >= 0.0);
31156 return;
31157 }
31158 }
31159 }
31161 /* 64-bit integers are not supported at present. So
31162 * we also don't need to deal with choosing between a
31163 * 64-bit uint/sint representation vs. IEEE double or
31164 * float.
31165 */
31166
31168 duk__cbor_encode_double_fp(enc_ctx, d);
31169}
31170#endif /* DUK_CBOR_DOUBLE_AS_IS */
31171
31173 const duk_uint8_t *str;
31174 duk_size_t len;
31175 duk_uint8_t *p;
31176
31177 /* CBOR differentiates between UTF-8 text strings and byte strings.
31178 * Text strings MUST be valid UTF-8, so not all Duktape strings can
31179 * be encoded as valid CBOR text strings. Possible behaviors:
31180 *
31181 * 1. Use text string when input is valid UTF-8, otherwise use
31182 * byte string (maybe tagged to indicate it was an extended
31183 * UTF-8 string).
31184 * 2. Always use text strings, but sanitize input string so that
31185 * invalid UTF-8 is replaced with U+FFFD for example. Combine
31186 * surrogates whenever possible.
31187 * 3. Always use byte strings. This is simple and produces valid
31188 * CBOR, but isn't ideal for interoperability.
31189 * 4. Always use text strings, even for invalid UTF-8 such as
31190 * codepoints in the surrogate pair range. This is simple but
31191 * produces technically invalid CBOR for non-UTF-8 strings which
31192 * may affect interoperability.
31193 *
31194 * Current default is 1; can be changed with defines.
31195 */
31196
31197 /* Caller must ensure space. */
31198 DUK_ASSERT(duk__cbor_get_reserve(enc_ctx) >= 1 + 8);
31199
31200 str = (const duk_uint8_t *) duk_require_lstring(enc_ctx->thr, -1, &len);
31201 if (duk_is_symbol(enc_ctx->thr, -1)) {
31202 /* Symbols, encode as an empty table for now. This matches
31203 * the behavior of cbor-js.
31204 *
31205 * XXX: Maybe encode String() coercion with a tag?
31206 * XXX: Option to keep enough information to recover
31207 * Symbols when decoding (this is not always desirable).
31208 */
31209 p = enc_ctx->ptr;
31210 *p++ = 0xa0U;
31211 enc_ctx->ptr = p;
31212 return;
31213 }
31214
31216#if defined(DUK_CBOR_TEXT_STRINGS)
31217 duk__cbor_encode_uint32(enc_ctx, (duk_uint32_t) len, 0x60U);
31218#elif defined(DUK_CBOR_BYTE_STRINGS)
31219 duk__cbor_encode_uint32(enc_ctx, (duk_uint32_t) len, 0x40U);
31220#else
31222 (duk_uint32_t) len,
31223 (DUK_LIKELY(duk_unicode_is_utf8_compatible(str, len) != 0) ? 0x60U : 0x40U));
31224#endif
31225 duk__cbor_encode_ensure(enc_ctx, len);
31226 p = enc_ctx->ptr;
31227 duk_memcpy((void *) p, (const void *) str, len);
31228 p += len;
31229 enc_ctx->ptr = p;
31230}
31231
31233 duk_uint8_t *buf;
31234 duk_size_t len;
31235 duk_uint8_t *p;
31236 duk_size_t i;
31237 duk_size_t off_ib;
31238 duk_uint32_t count;
31239
31240 /* Caller must ensure space. */
31241 DUK_ASSERT(duk__cbor_get_reserve(enc_ctx) >= 1 + 8);
31242
31244
31245 /* XXX: Support for specific built-ins like Date and RegExp. */
31246 if (duk_is_array(enc_ctx->thr, -1)) {
31247 /* Shortest encoding for arrays >= 256 in length is actually
31248 * the indefinite length one (3 or more bytes vs. 2 bytes).
31249 * We still use the definite length version because it is
31250 * more decoding friendly.
31251 */
31252 len = duk_get_length(enc_ctx->thr, -1);
31254 duk__cbor_encode_uint32(enc_ctx, (duk_uint32_t) len, 0x80U);
31255 for (i = 0; i < len; i++) {
31256 duk_get_prop_index(enc_ctx->thr, -1, (duk_uarridx_t) i);
31257 duk__cbor_encode_value(enc_ctx);
31258 }
31259 } else if (duk_is_buffer_data(enc_ctx->thr, -1)) {
31260 /* XXX: Tag buffer data?
31261 * XXX: Encode typed arrays as integer arrays rather
31262 * than buffer data as is?
31263 */
31264 buf = (duk_uint8_t *) duk_require_buffer_data(enc_ctx->thr, -1, &len);
31266 duk__cbor_encode_uint32(enc_ctx, (duk_uint32_t) len, 0x40U);
31267 duk__cbor_encode_ensure(enc_ctx, len);
31268 p = enc_ctx->ptr;
31269 duk_memcpy_unsafe((void *) p, (const void *) buf, len);
31270 p += len;
31271 enc_ctx->ptr = p;
31272 } else {
31273 /* We don't know the number of properties in advance
31274 * but would still like to encode at least small
31275 * objects without indefinite length. Emit an
31276 * indefinite length byte initially, and if the final
31277 * property count is small enough to also fit in one
31278 * byte, backpatch it later. Otherwise keep the
31279 * indefinite length. This works well up to 23
31280 * properties which is practical and good enough.
31281 */
31282 off_ib = (duk_size_t) (enc_ctx->ptr - enc_ctx->buf); /* XXX: get_offset? */
31283 count = 0U;
31284 p = enc_ctx->ptr;
31285 *p++ = 0xa0U + 0x1fU; /* indefinite length */
31286 enc_ctx->ptr = p;
31288 while (duk_next(enc_ctx->thr, -1, 1 /*get_value*/)) {
31289 duk_insert(enc_ctx->thr, -2); /* [ ... key value ] -> [ ... value key ] */
31290 duk__cbor_encode_value(enc_ctx);
31291 duk__cbor_encode_value(enc_ctx);
31292 count++;
31293 if (count == 0U) {
31294 duk__cbor_encode_error(enc_ctx);
31295 }
31296 }
31297 duk_pop(enc_ctx->thr);
31298 if (count <= 0x17U) {
31299 DUK_ASSERT(off_ib < enc_ctx->len);
31300 enc_ctx->buf[off_ib] = 0xa0U + (duk_uint8_t) count;
31301 } else {
31302 duk__cbor_encode_ensure(enc_ctx, 1);
31303 p = enc_ctx->ptr;
31304 *p++ = 0xffU; /* break */
31305 enc_ctx->ptr = p;
31306 }
31307 }
31308
31310}
31311
31313 duk_uint8_t *buf;
31314 duk_size_t len;
31315 duk_uint8_t *p;
31316
31317 /* Caller must ensure space. */
31318 DUK_ASSERT(duk__cbor_get_reserve(enc_ctx) >= 1 + 8);
31320 /* Tag buffer data? */
31321 buf = (duk_uint8_t *) duk_require_buffer(enc_ctx->thr, -1, &len);
31323 duk__cbor_encode_uint32(enc_ctx, (duk_uint32_t) len, 0x40U);
31324 duk__cbor_encode_ensure(enc_ctx, len);
31325 p = enc_ctx->ptr;
31326 duk_memcpy_unsafe((void *) p, (const void *) buf, len);
31327 p += len;
31328 enc_ctx->ptr = p;
31329}
31330
31332 /* Pointers (void *) are challenging to encode. They can't
31333 * be relied to be even 64-bit integer compatible (there are
31334 * pointer models larger than that), nor can floats encode
31335 * them. They could be encoded as strings (%p format) but
31336 * that's not portable. They could be encoded as direct memory
31337 * representations. Recovering pointers is non-portable in any
31338 * case but it would be nice to be able to detect and recover
31339 * compatible pointers.
31340 *
31341 * For now, encode as "(%p)" string, matching JX. There doesn't
31342 * seem to be an appropriate tag, so pointers don't currently
31343 * survive a CBOR encode/decode roundtrip intact.
31344 */
31345 const char *ptr;
31346
31347 ptr = duk_to_string(enc_ctx->thr, -1);
31348 DUK_ASSERT(ptr != NULL);
31349 duk_push_sprintf(enc_ctx->thr, "(%s)", ptr);
31350 duk_remove(enc_ctx->thr, -2);
31352}
31353
31355 duk_uint8_t *p;
31356
31357 /* Caller must ensure space. */
31358 DUK_ASSERT(duk__cbor_get_reserve(enc_ctx) >= 1 + 8);
31359
31360 /* For now encode as an empty object. */
31361 p = enc_ctx->ptr;
31362 *p++ = 0xa0U;
31363 enc_ctx->ptr = p;
31364}
31365
31367 duk_uint8_t *p;
31368
31369 /* Encode/decode cycle currently loses some type information.
31370 * This can be improved by registering custom tags with IANA.
31371 */
31372
31373 /* Reserve space for up to 64-bit types (1 initial byte + 8
31374 * followup bytes). This allows encoding of integers, floats,
31375 * string/buffer length fields, etc without separate checks
31376 * in each code path.
31377 */
31378 duk__cbor_encode_ensure(enc_ctx, 1 + 8);
31379
31380 switch (duk_get_type(enc_ctx->thr, -1)) {
31381 case DUK_TYPE_UNDEFINED: {
31382 p = enc_ctx->ptr;
31383 *p++ = 0xf7;
31384 enc_ctx->ptr = p;
31385 break;
31386 }
31387 case DUK_TYPE_NULL: {
31388 p = enc_ctx->ptr;
31389 *p++ = 0xf6;
31390 enc_ctx->ptr = p;
31391 break;
31392 }
31393 case DUK_TYPE_BOOLEAN: {
31394 duk_uint8_t u8 = duk_get_boolean(enc_ctx->thr, -1) ? 0xf5U : 0xf4U;
31395 p = enc_ctx->ptr;
31396 *p++ = u8;
31397 enc_ctx->ptr = p;
31398 break;
31399 }
31400 case DUK_TYPE_NUMBER: {
31401 duk__cbor_encode_double(enc_ctx, duk_get_number(enc_ctx->thr, -1));
31402 break;
31403 }
31404 case DUK_TYPE_STRING: {
31406 break;
31407 }
31408 case DUK_TYPE_OBJECT: {
31409 duk__cbor_encode_object(enc_ctx);
31410 break;
31411 }
31412 case DUK_TYPE_BUFFER: {
31413 duk__cbor_encode_buffer(enc_ctx);
31414 break;
31415 }
31416 case DUK_TYPE_POINTER: {
31417 duk__cbor_encode_pointer(enc_ctx);
31418 break;
31419 }
31420 case DUK_TYPE_LIGHTFUNC: {
31422 break;
31423 }
31424 case DUK_TYPE_NONE:
31425 default:
31426 goto fail;
31427 }
31429 duk_pop(enc_ctx->thr);
31430 return;
31431
31432fail:
31433 duk__cbor_encode_error(enc_ctx);
31434}
31435
31437 * Decoding
31438 */
31439
31441 (void) duk_type_error(dec_ctx->thr, "cbor decode error");
31442}
31443
31445 duk_require_stack(dec_ctx->thr, 4);
31446}
31447
31449 duk_hthread *thr = dec_ctx->thr;
31450
31451 /* Native stack check in object/array recursion. */
31453
31455
31456 DUK_ASSERT(dec_ctx->recursion_depth <= dec_ctx->recursion_limit);
31457 if (dec_ctx->recursion_depth >= dec_ctx->recursion_limit) {
31459 DUK_WO_NORETURN(return;);
31460 }
31461 dec_ctx->recursion_depth++;
31462}
31463
31466 dec_ctx->recursion_depth--;
31467}
31468
31470 DUK_ASSERT(dec_ctx->off <= dec_ctx->len);
31471 if (DUK_UNLIKELY(dec_ctx->len - dec_ctx->off < 1U)) {
31472 duk__cbor_decode_error(dec_ctx);
31473 }
31474 return dec_ctx->buf[dec_ctx->off++];
31475}
31476
31478 duk_uint16_t res;
31479
31480 DUK_ASSERT(dec_ctx->off <= dec_ctx->len);
31481 if (DUK_UNLIKELY(dec_ctx->len - dec_ctx->off < 2U)) {
31482 duk__cbor_decode_error(dec_ctx);
31483 }
31484 res = DUK_RAW_READ_U16_BE(dec_ctx->buf + dec_ctx->off);
31485 dec_ctx->off += 2;
31486 return res;
31487}
31488
31490 duk_uint32_t res;
31491
31492 DUK_ASSERT(dec_ctx->off <= dec_ctx->len);
31493 if (DUK_UNLIKELY(dec_ctx->len - dec_ctx->off < 4U)) {
31494 duk__cbor_decode_error(dec_ctx);
31495 }
31496 res = DUK_RAW_READ_U32_BE(dec_ctx->buf + dec_ctx->off);
31497 dec_ctx->off += 4;
31498 return res;
31499}
31500
31502 if (DUK_UNLIKELY(dec_ctx->off >= dec_ctx->len)) {
31503 duk__cbor_decode_error(dec_ctx);
31504 }
31505 return dec_ctx->buf[dec_ctx->off];
31506}
31507
31509 DUK_ASSERT(len <= dec_ctx->off); /* Caller must ensure. */
31510 dec_ctx->off -= len;
31511}
31512
31513#if 0
31514DUK_LOCAL void duk__cbor_decode_ensure(duk_cbor_decode_context *dec_ctx, duk_size_t len) {
31515 if (dec_ctx->off + len > dec_ctx->len) {
31516 duk__cbor_decode_error(dec_ctx);
31517 }
31518}
31519#endif
31520
31522 DUK_ASSERT(dec_ctx->off <= dec_ctx->len);
31523 if (DUK_LIKELY(dec_ctx->len - dec_ctx->off >= len)) {
31524 const duk_uint8_t *res = dec_ctx->buf + dec_ctx->off;
31525 dec_ctx->off += len;
31526 return res;
31527 }
31528
31529 duk__cbor_decode_error(dec_ctx); /* Not enough input. */
31530 return NULL;
31531}
31532
31534 if (duk__cbor_decode_peekbyte(dec_ctx) == 0xffU) {
31535 DUK_ASSERT(dec_ctx->off < dec_ctx->len);
31536 dec_ctx->off++;
31537#if 0
31538 (void) duk__cbor_decode_readbyte(dec_ctx);
31539#endif
31540 return 1;
31541 }
31542 return 0;
31543}
31544
31545DUK_LOCAL void duk__cbor_decode_push_aival_int(duk_cbor_decode_context *dec_ctx, duk_uint8_t ib, duk_bool_t negative) {
31546 duk_uint8_t ai;
31547 duk_uint32_t t, t1, t2;
31548#if 0
31549 duk_uint64_t t3;
31550#endif
31551 duk_double_t d1, d2;
31552 duk_double_t d;
31553
31554 ai = ib & 0x1fU;
31555 if (ai <= 0x17U) {
31556 t = ai;
31557 goto shared_exit;
31558 }
31559
31560 switch (ai) {
31561 case 0x18U: /* 1 byte */
31562 t = (duk_uint32_t) duk__cbor_decode_readbyte(dec_ctx);
31563 goto shared_exit;
31564 case 0x19U: /* 2 byte */
31565 t = (duk_uint32_t) duk__cbor_decode_read_u16(dec_ctx);
31566 goto shared_exit;
31567 case 0x1aU: /* 4 byte */
31568 t = (duk_uint32_t) duk__cbor_decode_read_u32(dec_ctx);
31569 goto shared_exit;
31570 case 0x1bU: /* 8 byte */
31571 /* For uint64 it's important to handle the -1.0 part before
31572 * casting to double: otherwise the adjustment might be lost
31573 * in the cast. Uses: -1.0 - d <=> -(d + 1.0).
31574 */
31575 t = (duk_uint32_t) duk__cbor_decode_read_u32(dec_ctx);
31576 t2 = t;
31577 t = (duk_uint32_t) duk__cbor_decode_read_u32(dec_ctx);
31578 t1 = t;
31579#if 0
31580 t3 = (duk_uint64_t) t2 * DUK_U64_CONSTANT(0x100000000) + (duk_uint64_t) t1;
31581 if (negative) {
31582 if (t3 == DUK_UINT64_MAX) {
31583 /* -(0xffff'ffff'ffff'ffffULL + 1) =
31584 * -0x1'0000'0000'0000'0000
31585 *
31586 * >>> -0x10000000000000000
31587 * -18446744073709551616L
31588 */
31589 return -18446744073709551616.0;
31590 } else {
31591 return -((duk_double_t) (t3 + DUK_U64_CONSTANT(1)));
31592 }
31593 } else {
31594 return (duk_double_t) t3; /* XXX: cast helper */
31595 }
31596#endif
31597#if 0
31598 t3 = (duk_uint64_t) t2 * DUK_U64_CONSTANT(0x100000000) + (duk_uint64_t) t1;
31599 if (negative) {
31600 /* Simpler version: take advantage of the fact that
31601 * 0xffff'ffff'ffff'ffff and 0x1'0000'0000'0000'0000
31602 * both round to 0x1'0000'0000'0000'0000:
31603 * > (0xffffffffffffffff).toString(16)
31604 * '10000000000000000'
31605 * > (0x10000000000000000).toString(16)
31606 * '10000000000000000'
31607 *
31608 * For the DUK_UINT64_MAX case we just skip the +1
31609 * increment to avoid wrapping; the result still
31610 * comes out right for an IEEE double cast.
31611 */
31612 if (t3 != DUK_UINT64_MAX) {
31613 t3++;
31614 }
31615 return -((duk_double_t) t3);
31616 } else {
31617 return (duk_double_t) t3; /* XXX: cast helper */
31618 }
31619#endif
31620#if 1
31621 /* Use two double parts, avoids dependency on 64-bit type.
31622 * Avoid precision loss carefully, especially when dealing
31623 * with the required +1 for negative values.
31624 *
31625 * No fastint check for this path at present.
31626 */
31627 d1 = (duk_double_t) t1; /* XXX: cast helpers */
31628 d2 = (duk_double_t) t2 * 4294967296.0;
31629 if (negative) {
31630 d1 += 1.0;
31631 }
31632 d = d2 + d1;
31633 if (negative) {
31634 d = -d;
31635 }
31636#endif
31637 /* XXX: a push and check for fastint API would be nice */
31638 duk_push_number(dec_ctx->thr, d);
31639 return;
31640 }
31641
31642 duk__cbor_decode_error(dec_ctx);
31643 return;
31644
31645shared_exit:
31646 if (negative) {
31647 /* XXX: a push and check for fastint API would be nice */
31648 if ((duk_uint_t) t <= (duk_uint_t) - (DUK_INT_MIN + 1)) {
31649 duk_push_int(dec_ctx->thr, -1 - ((duk_int_t) t));
31650 } else {
31651 duk_push_number(dec_ctx->thr, -1.0 - (duk_double_t) t);
31652 }
31653 } else {
31654 duk_push_uint(dec_ctx->thr, (duk_uint_t) t);
31655 }
31656}
31657
31659 const duk_int8_t skips[32] = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
31660 0, 0, 0, 0, 0, 0, 0, 0, 1, 2, 4, 8, -1, -1, -1, -1 };
31661 duk_uint8_t ai;
31662 duk_int8_t skip;
31663
31664 ai = ib & 0x1fU;
31665 skip = skips[ai];
31666 if (DUK_UNLIKELY(skip < 0)) {
31667 duk__cbor_decode_error(dec_ctx);
31668 }
31669 duk__cbor_decode_consume(dec_ctx, (duk_size_t) skip);
31670 return;
31671}
31672
31673DUK_LOCAL duk_uint32_t duk__cbor_decode_aival_uint32(duk_cbor_decode_context *dec_ctx, duk_uint8_t ib) {
31674 duk_uint8_t ai;
31675 duk_uint32_t t;
31676
31677 ai = ib & 0x1fU;
31678 if (ai <= 0x17U) {
31679 return (duk_uint32_t) ai;
31680 }
31681
31682 switch (ai) {
31683 case 0x18U: /* 1 byte */
31684 t = (duk_uint32_t) duk__cbor_decode_readbyte(dec_ctx);
31685 return t;
31686 case 0x19U: /* 2 byte */
31687 t = (duk_uint32_t) duk__cbor_decode_read_u16(dec_ctx);
31688 return t;
31689 case 0x1aU: /* 4 byte */
31690 t = (duk_uint32_t) duk__cbor_decode_read_u32(dec_ctx);
31691 return t;
31692 case 0x1bU: /* 8 byte */
31693 t = (duk_uint32_t) duk__cbor_decode_read_u32(dec_ctx);
31694 if (t != 0U) {
31695 break;
31696 }
31697 t = (duk_uint32_t) duk__cbor_decode_read_u32(dec_ctx);
31698 return t;
31699 }
31700
31701 duk__cbor_decode_error(dec_ctx);
31702 return 0U;
31703}
31704
31705DUK_LOCAL void duk__cbor_decode_buffer(duk_cbor_decode_context *dec_ctx, duk_uint8_t expected_base) {
31706 duk_uint32_t len;
31707 duk_uint8_t *buf;
31708 const duk_uint8_t *inp;
31709 duk_uint8_t ib;
31710
31712 if ((ib & 0xe0U) != expected_base) {
31713 duk__cbor_decode_error(dec_ctx);
31714 }
31715 /* Indefinite format is rejected by the following on purpose. */
31716 len = duk__cbor_decode_aival_uint32(dec_ctx, ib);
31717 inp = duk__cbor_decode_consume(dec_ctx, len);
31718 /* XXX: duk_push_fixed_buffer_with_data() would be a nice API addition. */
31719 buf = (duk_uint8_t *) duk_push_fixed_buffer(dec_ctx->thr, (duk_size_t) len);
31720 duk_memcpy((void *) buf, (const void *) inp, (size_t) len);
31721}
31722
31724 duk_size_t total_size = 0;
31725 duk_idx_t top = duk_get_top(dec_ctx->thr);
31726 duk_idx_t base = top - count; /* count is >= 1 */
31727 duk_idx_t idx;
31728 duk_uint8_t *p = NULL;
31729
31730 DUK_ASSERT(count >= 1);
31731 DUK_ASSERT(top >= count);
31732
31733 for (;;) {
31734 /* First round: compute total size.
31735 * Second round: copy into place.
31736 */
31737 for (idx = base; idx < top; idx++) {
31738 duk_uint8_t *buf_data;
31739 duk_size_t buf_size;
31740
31741 buf_data = (duk_uint8_t *) duk_require_buffer(dec_ctx->thr, idx, &buf_size);
31742 if (p != NULL) {
31743 duk_memcpy_unsafe((void *) p, (const void *) buf_data, buf_size);
31744 p += buf_size;
31745 } else {
31746 total_size += buf_size;
31747 if (DUK_UNLIKELY(total_size < buf_size)) { /* Wrap check. */
31748 duk__cbor_decode_error(dec_ctx);
31749 }
31750 }
31751 }
31752
31753 if (p != NULL) {
31754 break;
31755 } else {
31756 p = (duk_uint8_t *) duk_push_fixed_buffer(dec_ctx->thr, total_size);
31757 DUK_ASSERT(p != NULL);
31758 }
31759 }
31760
31761 duk_replace(dec_ctx->thr, base);
31762 duk_pop_n(dec_ctx->thr, count - 1);
31763}
31764
31765DUK_LOCAL void duk__cbor_decode_and_join_strbuf(duk_cbor_decode_context *dec_ctx, duk_uint8_t expected_base) {
31766 duk_idx_t count = 0;
31767 for (;;) {
31768 if (duk__cbor_decode_checkbreak(dec_ctx)) {
31769 break;
31770 }
31771 duk_require_stack(dec_ctx->thr, 1);
31772 duk__cbor_decode_buffer(dec_ctx, expected_base);
31774 if (DUK_UNLIKELY(count <= 0)) { /* Wrap check. */
31775 duk__cbor_decode_error(dec_ctx);
31776 }
31777 }
31778 if (count == 0) {
31779 (void) duk_push_fixed_buffer(dec_ctx->thr, 0);
31780 } else if (count > 1) {
31782 }
31783}
31784
31787 const duk_uint8_t *inp;
31788 duk_int_t expt;
31789 duk_uint_t u16;
31790 duk_uint_t tmp;
31791 duk_double_t res;
31792
31793 inp = duk__cbor_decode_consume(dec_ctx, 2);
31794 u16 = ((duk_uint_t) inp[0] << 8) + (duk_uint_t) inp[1];
31795 expt = (duk_int_t) ((u16 >> 10) & 0x1fU) - 15;
31796
31797 /* Reconstruct IEEE double into little endian order first, then convert
31798 * to host order.
31799 */
31800
31801 duk_memzero((void *) &u, sizeof(u));
31802
31803 if (expt == -15) {
31804 /* Zero or denormal; but note that half float
31805 * denormals become double normals.
31806 */
31807 if ((u16 & 0x03ffU) == 0) {
31808 u.uc[7] = inp[0] & 0x80U;
31809 } else {
31810 /* Create denormal by first creating a double that
31811 * contains the denormal bits and a leading implicit
31812 * 1-bit. Then subtract away the implicit 1-bit.
31813 *
31814 * 0.mmmmmmmmmm * 2^-14
31815 * 1.mmmmmmmmmm 0.... * 2^-14
31816 * -1.0000000000 0.... * 2^-14
31817 *
31818 * Double exponent: -14 + 1023 = 0x3f1
31819 */
31820 u.uc[7] = 0x3fU;
31821 u.uc[6] = 0x10U + (duk_uint8_t) ((u16 >> 6) & 0x0fU);
31822 u.uc[5] = (duk_uint8_t) ((u16 << 2) & 0xffU); /* Mask is really 0xfcU */
31823
31825 res = u.d - 0.00006103515625; /* 2^(-14) */
31826 if (u16 & 0x8000U) {
31827 res = -res;
31828 }
31829 return res;
31830 }
31831 } else if (expt == 16) {
31832 /* +/- Inf or NaN. */
31833 if ((u16 & 0x03ffU) == 0) {
31834 u.uc[7] = (inp[0] & 0x80U) + 0x7fU;
31835 u.uc[6] = 0xf0U;
31836 } else {
31837 /* Create a 'quiet NaN' with highest
31838 * bit set (there are some platforms
31839 * where the NaN payload convention is
31840 * the opposite). Keep sign.
31841 */
31842 u.uc[7] = (inp[0] & 0x80U) + 0x7fU;
31843 u.uc[6] = 0xf8U;
31844 }
31845 } else {
31846 /* Normal. */
31847 tmp = (inp[0] & 0x80U) ? 0x80000000UL : 0UL;
31848 tmp += (duk_uint_t) (expt + 1023) << 20;
31849 tmp += (duk_uint_t) (inp[0] & 0x03U) << 18;
31850 tmp += (duk_uint_t) (inp[1] & 0xffU) << 10;
31851 u.uc[7] = (tmp >> 24) & 0xffU;
31852 u.uc[6] = (tmp >> 16) & 0xffU;
31853 u.uc[5] = (tmp >> 8) & 0xffU;
31854 u.uc[4] = (tmp >> 0) & 0xffU;
31855 }
31856
31858 return u.d;
31859}
31860
31861DUK_LOCAL void duk__cbor_decode_string(duk_cbor_decode_context *dec_ctx, duk_uint8_t ib, duk_uint8_t ai) {
31862 /* If the CBOR string data is not valid UTF-8 it is technically
31863 * invalid CBOR. Possible behaviors at least:
31864 *
31865 * 1. Reject the input, i.e. throw TypeError.
31866 *
31867 * 2. Accept the input, but sanitize non-UTF-8 data into UTF-8
31868 * using U+FFFD replacements. Also it might make sense to
31869 * decode non-BMP codepoints into surrogates for better
31870 * ECMAScript compatibility.
31871 *
31872 * 3. Accept the input as a Duktape string (which are not always
31873 * valid UTF-8), but reject any input that would create a
31874 * Symbol representation.
31875 *
31876 * Current behavior is 3.
31877 */
31878
31879 if (ai == 0x1fU) {
31880 duk_uint8_t *buf_data;
31881 duk_size_t buf_size;
31882
31883 duk__cbor_decode_and_join_strbuf(dec_ctx, 0x60U);
31884 buf_data = (duk_uint8_t *) duk_require_buffer(dec_ctx->thr, -1, &buf_size);
31885 (void) duk_push_lstring(dec_ctx->thr, (const char *) buf_data, buf_size);
31886 duk_remove(dec_ctx->thr, -2);
31887 } else {
31888 duk_uint32_t len;
31889 const duk_uint8_t *inp;
31890
31891 len = duk__cbor_decode_aival_uint32(dec_ctx, ib);
31892 inp = duk__cbor_decode_consume(dec_ctx, len);
31893 (void) duk_push_lstring(dec_ctx->thr, (const char *) inp, (duk_size_t) len);
31894 }
31895 if (duk_is_symbol(dec_ctx->thr, -1)) {
31896 /* Refuse to create Symbols when decoding. */
31897 duk__cbor_decode_error(dec_ctx);
31898 }
31899
31900 /* XXX: Here a Duktape API call to convert input -> utf-8 with
31901 * replacements would be nice.
31902 */
31903}
31904
31905DUK_LOCAL duk_bool_t duk__cbor_decode_array(duk_cbor_decode_context *dec_ctx, duk_uint8_t ib, duk_uint8_t ai) {
31906 duk_uint32_t idx, len;
31907
31909
31910 /* Support arrays up to 0xfffffffeU in length. 0xffffffff is
31911 * used as an indefinite length marker.
31912 */
31913 if (ai == 0x1fU) {
31914 len = 0xffffffffUL;
31915 } else {
31916 len = duk__cbor_decode_aival_uint32(dec_ctx, ib);
31917 if (len == 0xffffffffUL) {
31918 goto failure;
31919 }
31920 }
31921
31922 /* XXX: use bare array? */
31923 duk_push_array(dec_ctx->thr);
31924 for (idx = 0U;;) {
31925 if (len == 0xffffffffUL && duk__cbor_decode_checkbreak(dec_ctx)) {
31926 break;
31927 }
31928 if (idx == len) {
31929 if (ai == 0x1fU) {
31930 goto failure;
31931 }
31932 break;
31933 }
31934 duk__cbor_decode_value(dec_ctx);
31935 duk_put_prop_index(dec_ctx->thr, -2, (duk_uarridx_t) idx);
31936 idx++;
31937 if (idx == 0U) {
31938 goto failure; /* wrapped */
31939 }
31940 }
31942#if 0
31943 success:
31944#endif
31946 return 1;
31947
31948failure:
31949 /* No need to unwind recursion checks, caller will throw. */
31950 return 0;
31951}
31952
31953DUK_LOCAL duk_bool_t duk__cbor_decode_map(duk_cbor_decode_context *dec_ctx, duk_uint8_t ib, duk_uint8_t ai) {
31954 duk_uint32_t count;
31955
31957
31958 if (ai == 0x1fU) {
31959 count = 0xffffffffUL;
31960 } else {
31961 count = duk__cbor_decode_aival_uint32(dec_ctx, ib);
31962 if (count == 0xffffffffUL) {
31963 goto failure;
31964 }
31965 }
31966
31967 /* XXX: use bare object? */
31968 duk_push_object(dec_ctx->thr);
31969 for (;;) {
31970 if (count == 0xffffffffUL) {
31971 if (duk__cbor_decode_checkbreak(dec_ctx)) {
31972 break;
31973 }
31974 } else {
31975 if (count == 0UL) {
31976 break;
31977 }
31978 count--;
31979 }
31980
31981 /* Non-string keys are coerced to strings,
31982 * possibly leading to overwriting previous
31983 * keys. Last key of a certain coerced name
31984 * wins. If key is an object, it will coerce
31985 * to '[object Object]' which is consistent
31986 * but potentially misleading. One alternative
31987 * would be to skip non-string keys.
31988 */
31989 duk__cbor_decode_value(dec_ctx);
31990 duk__cbor_decode_value(dec_ctx);
31991 duk_put_prop(dec_ctx->thr, -3);
31992 }
31994#if 0
31995 success:
31996#endif
31998 return 1;
31999
32000failure:
32001 /* No need to unwind recursion checks, caller will throw. */
32002 return 0;
32003}
32004
32007 const duk_uint8_t *inp;
32008 inp = duk__cbor_decode_consume(dec_ctx, 4);
32009 duk_memcpy((void *) u.uc, (const void *) inp, 4);
32011 return (duk_double_t) u.f;
32012}
32013
32016 const duk_uint8_t *inp;
32017 inp = duk__cbor_decode_consume(dec_ctx, 8);
32018 duk_memcpy((void *) u.uc, (const void *) inp, 8);
32020 return u.d;
32021}
32022
32023#if defined(DUK_CBOR_DECODE_FASTPATH)
32024#define DUK__CBOR_AI (ib & 0x1fU)
32025
32027 duk_uint8_t ib;
32028
32029 /* Any paths potentially recursing back to duk__cbor_decode_value()
32030 * must perform a Duktape value stack growth check. Avoid the check
32031 * here for simple paths like primitive values.
32032 */
32033
32034reread_initial_byte:
32035 DUK_DDD(DUK_DDDPRINT("cbor decode off=%ld len=%ld", (long) dec_ctx->off, (long) dec_ctx->len));
32036
32037 ib = duk__cbor_decode_readbyte(dec_ctx);
32038
32039 /* Full initial byte switch, footprint cost over baseline is ~+1kB. */
32040 /* XXX: Force full switch with no range check. */
32041
32042 switch (ib) {
32043 case 0x00U:
32044 case 0x01U:
32045 case 0x02U:
32046 case 0x03U:
32047 case 0x04U:
32048 case 0x05U:
32049 case 0x06U:
32050 case 0x07U:
32051 case 0x08U:
32052 case 0x09U:
32053 case 0x0aU:
32054 case 0x0bU:
32055 case 0x0cU:
32056 case 0x0dU:
32057 case 0x0eU:
32058 case 0x0fU:
32059 case 0x10U:
32060 case 0x11U:
32061 case 0x12U:
32062 case 0x13U:
32063 case 0x14U:
32064 case 0x15U:
32065 case 0x16U:
32066 case 0x17U:
32067 duk_push_uint(dec_ctx->thr, ib);
32068 break;
32069 case 0x18U:
32070 case 0x19U:
32071 case 0x1aU:
32072 case 0x1bU:
32073 duk__cbor_decode_push_aival_int(dec_ctx, ib, 0 /*negative*/);
32074 break;
32075 case 0x1cU:
32076 case 0x1dU:
32077 case 0x1eU:
32078 case 0x1fU:
32079 goto format_error;
32080 case 0x20U:
32081 case 0x21U:
32082 case 0x22U:
32083 case 0x23U:
32084 case 0x24U:
32085 case 0x25U:
32086 case 0x26U:
32087 case 0x27U:
32088 case 0x28U:
32089 case 0x29U:
32090 case 0x2aU:
32091 case 0x2bU:
32092 case 0x2cU:
32093 case 0x2dU:
32094 case 0x2eU:
32095 case 0x2fU:
32096 case 0x30U:
32097 case 0x31U:
32098 case 0x32U:
32099 case 0x33U:
32100 case 0x34U:
32101 case 0x35U:
32102 case 0x36U:
32103 case 0x37U:
32104 duk_push_int(dec_ctx->thr, -((duk_int_t) ((ib - 0x20U) + 1U)));
32105 break;
32106 case 0x38U:
32107 case 0x39U:
32108 case 0x3aU:
32109 case 0x3bU:
32110 duk__cbor_decode_push_aival_int(dec_ctx, ib, 1 /*negative*/);
32111 break;
32112 case 0x3cU:
32113 case 0x3dU:
32114 case 0x3eU:
32115 case 0x3fU:
32116 goto format_error;
32117 case 0x40U:
32118 case 0x41U:
32119 case 0x42U:
32120 case 0x43U:
32121 case 0x44U:
32122 case 0x45U:
32123 case 0x46U:
32124 case 0x47U:
32125 case 0x48U:
32126 case 0x49U:
32127 case 0x4aU:
32128 case 0x4bU:
32129 case 0x4cU:
32130 case 0x4dU:
32131 case 0x4eU:
32132 case 0x4fU:
32133 case 0x50U:
32134 case 0x51U:
32135 case 0x52U:
32136 case 0x53U:
32137 case 0x54U:
32138 case 0x55U:
32139 case 0x56U:
32140 case 0x57U:
32141 /* XXX: Avoid rewind, we know the length already. */
32142 DUK_ASSERT(dec_ctx->off > 0U);
32143 dec_ctx->off--;
32144 duk__cbor_decode_buffer(dec_ctx, 0x40U);
32145 break;
32146 case 0x58U:
32147 case 0x59U:
32148 case 0x5aU:
32149 case 0x5bU:
32150 /* XXX: Avoid rewind, decode length inline. */
32151 DUK_ASSERT(dec_ctx->off > 0U);
32152 dec_ctx->off--;
32153 duk__cbor_decode_buffer(dec_ctx, 0x40U);
32154 break;
32155 case 0x5cU:
32156 case 0x5dU:
32157 case 0x5eU:
32158 goto format_error;
32159 case 0x5fU:
32160 duk__cbor_decode_and_join_strbuf(dec_ctx, 0x40U);
32161 break;
32162 case 0x60U:
32163 case 0x61U:
32164 case 0x62U:
32165 case 0x63U:
32166 case 0x64U:
32167 case 0x65U:
32168 case 0x66U:
32169 case 0x67U:
32170 case 0x68U:
32171 case 0x69U:
32172 case 0x6aU:
32173 case 0x6bU:
32174 case 0x6cU:
32175 case 0x6dU:
32176 case 0x6eU:
32177 case 0x6fU:
32178 case 0x70U:
32179 case 0x71U:
32180 case 0x72U:
32181 case 0x73U:
32182 case 0x74U:
32183 case 0x75U:
32184 case 0x76U:
32185 case 0x77U:
32186 /* XXX: Avoid double decode of length. */
32187 duk__cbor_decode_string(dec_ctx, ib, DUK__CBOR_AI);
32188 break;
32189 case 0x78U:
32190 case 0x79U:
32191 case 0x7aU:
32192 case 0x7bU:
32193 /* XXX: Avoid double decode of length. */
32194 duk__cbor_decode_string(dec_ctx, ib, DUK__CBOR_AI);
32195 break;
32196 case 0x7cU:
32197 case 0x7dU:
32198 case 0x7eU:
32199 goto format_error;
32200 case 0x7fU:
32201 duk__cbor_decode_string(dec_ctx, ib, DUK__CBOR_AI);
32202 break;
32203 case 0x80U:
32204 case 0x81U:
32205 case 0x82U:
32206 case 0x83U:
32207 case 0x84U:
32208 case 0x85U:
32209 case 0x86U:
32210 case 0x87U:
32211 case 0x88U:
32212 case 0x89U:
32213 case 0x8aU:
32214 case 0x8bU:
32215 case 0x8cU:
32216 case 0x8dU:
32217 case 0x8eU:
32218 case 0x8fU:
32219 case 0x90U:
32220 case 0x91U:
32221 case 0x92U:
32222 case 0x93U:
32223 case 0x94U:
32224 case 0x95U:
32225 case 0x96U:
32226 case 0x97U:
32227 if (DUK_UNLIKELY(duk__cbor_decode_array(dec_ctx, ib, DUK__CBOR_AI) == 0)) {
32228 goto format_error;
32229 }
32230 break;
32231 case 0x98U:
32232 case 0x99U:
32233 case 0x9aU:
32234 case 0x9bU:
32235 if (DUK_UNLIKELY(duk__cbor_decode_array(dec_ctx, ib, DUK__CBOR_AI) == 0)) {
32236 goto format_error;
32237 }
32238 break;
32239 case 0x9cU:
32240 case 0x9dU:
32241 case 0x9eU:
32242 goto format_error;
32243 case 0x9fU:
32244 if (DUK_UNLIKELY(duk__cbor_decode_array(dec_ctx, ib, DUK__CBOR_AI) == 0)) {
32245 goto format_error;
32246 }
32247 break;
32248 case 0xa0U:
32249 case 0xa1U:
32250 case 0xa2U:
32251 case 0xa3U:
32252 case 0xa4U:
32253 case 0xa5U:
32254 case 0xa6U:
32255 case 0xa7U:
32256 case 0xa8U:
32257 case 0xa9U:
32258 case 0xaaU:
32259 case 0xabU:
32260 case 0xacU:
32261 case 0xadU:
32262 case 0xaeU:
32263 case 0xafU:
32264 case 0xb0U:
32265 case 0xb1U:
32266 case 0xb2U:
32267 case 0xb3U:
32268 case 0xb4U:
32269 case 0xb5U:
32270 case 0xb6U:
32271 case 0xb7U:
32272 if (DUK_UNLIKELY(duk__cbor_decode_map(dec_ctx, ib, DUK__CBOR_AI) == 0)) {
32273 goto format_error;
32274 }
32275 break;
32276 case 0xb8U:
32277 case 0xb9U:
32278 case 0xbaU:
32279 case 0xbbU:
32280 if (DUK_UNLIKELY(duk__cbor_decode_map(dec_ctx, ib, DUK__CBOR_AI) == 0)) {
32281 goto format_error;
32282 }
32283 break;
32284 case 0xbcU:
32285 case 0xbdU:
32286 case 0xbeU:
32287 goto format_error;
32288 case 0xbfU:
32289 if (DUK_UNLIKELY(duk__cbor_decode_map(dec_ctx, ib, DUK__CBOR_AI) == 0)) {
32290 goto format_error;
32291 }
32292 break;
32293 case 0xc0U:
32294 case 0xc1U:
32295 case 0xc2U:
32296 case 0xc3U:
32297 case 0xc4U:
32298 case 0xc5U:
32299 case 0xc6U:
32300 case 0xc7U:
32301 case 0xc8U:
32302 case 0xc9U:
32303 case 0xcaU:
32304 case 0xcbU:
32305 case 0xccU:
32306 case 0xcdU:
32307 case 0xceU:
32308 case 0xcfU:
32309 case 0xd0U:
32310 case 0xd1U:
32311 case 0xd2U:
32312 case 0xd3U:
32313 case 0xd4U:
32314 case 0xd5U:
32315 case 0xd6U:
32316 case 0xd7U:
32317 /* Tag 0-23: drop. */
32318 goto reread_initial_byte;
32319 case 0xd8U:
32320 case 0xd9U:
32321 case 0xdaU:
32322 case 0xdbU:
32324 goto reread_initial_byte;
32325 case 0xdcU:
32326 case 0xddU:
32327 case 0xdeU:
32328 case 0xdfU:
32329 goto format_error;
32330 case 0xe0U:
32331 goto format_error;
32332 case 0xe1U:
32333 goto format_error;
32334 case 0xe2U:
32335 goto format_error;
32336 case 0xe3U:
32337 goto format_error;
32338 case 0xe4U:
32339 goto format_error;
32340 case 0xe5U:
32341 goto format_error;
32342 case 0xe6U:
32343 goto format_error;
32344 case 0xe7U:
32345 goto format_error;
32346 case 0xe8U:
32347 goto format_error;
32348 case 0xe9U:
32349 goto format_error;
32350 case 0xeaU:
32351 goto format_error;
32352 case 0xebU:
32353 goto format_error;
32354 case 0xecU:
32355 goto format_error;
32356 case 0xedU:
32357 goto format_error;
32358 case 0xeeU:
32359 goto format_error;
32360 case 0xefU:
32361 goto format_error;
32362 case 0xf0U:
32363 goto format_error;
32364 case 0xf1U:
32365 goto format_error;
32366 case 0xf2U:
32367 goto format_error;
32368 case 0xf3U:
32369 goto format_error;
32370 case 0xf4U:
32371 duk_push_false(dec_ctx->thr);
32372 break;
32373 case 0xf5U:
32374 duk_push_true(dec_ctx->thr);
32375 break;
32376 case 0xf6U:
32377 duk_push_null(dec_ctx->thr);
32378 break;
32379 case 0xf7U:
32380 duk_push_undefined(dec_ctx->thr);
32381 break;
32382 case 0xf8U:
32383 /* Simple value 32-255, nothing defined yet, so reject. */
32384 goto format_error;
32385 case 0xf9U: {
32386 duk_double_t d;
32387 d = duk__cbor_decode_half_float(dec_ctx);
32388 duk_push_number(dec_ctx->thr, d);
32389 break;
32390 }
32391 case 0xfaU: {
32392 duk_double_t d;
32393 d = duk__cbor_decode_float(dec_ctx);
32394 duk_push_number(dec_ctx->thr, d);
32395 break;
32396 }
32397 case 0xfbU: {
32398 duk_double_t d;
32399 d = duk__cbor_decode_double(dec_ctx);
32400 duk_push_number(dec_ctx->thr, d);
32401 break;
32402 }
32403 case 0xfcU:
32404 case 0xfdU:
32405 case 0xfeU:
32406 case 0xffU:
32407 goto format_error;
32408 } /* end switch */
32409
32410 return;
32411
32412format_error:
32413 duk__cbor_decode_error(dec_ctx);
32414}
32415#else /* DUK_CBOR_DECODE_FASTPATH */
32417 duk_uint8_t ib, mt, ai;
32418
32419 /* Any paths potentially recursing back to duk__cbor_decode_value()
32420 * must perform a Duktape value stack growth check. Avoid the check
32421 * here for simple paths like primitive values.
32422 */
32423
32424reread_initial_byte:
32425 DUK_DDD(DUK_DDDPRINT("cbor decode off=%ld len=%ld", (long) dec_ctx->off, (long) dec_ctx->len));
32426
32427 ib = duk__cbor_decode_readbyte(dec_ctx);
32428 mt = ib >> 5U;
32429 ai = ib & 0x1fU;
32430
32431 /* Additional information in [24,27] = [0x18,0x1b] has relatively
32432 * uniform handling for all major types: read 1/2/4/8 additional
32433 * bytes. For major type 7 the 1-byte value is a 'simple type', and
32434 * 2/4/8-byte values are floats. For other major types the 1/2/4/8
32435 * byte values are integers. The lengths are uniform, but the typing
32436 * is not.
32437 */
32438
32439 switch (mt) {
32440 case 0U: { /* unsigned integer */
32441 duk__cbor_decode_push_aival_int(dec_ctx, ib, 0 /*negative*/);
32442 break;
32443 }
32444 case 1U: { /* negative integer */
32445 duk__cbor_decode_push_aival_int(dec_ctx, ib, 1 /*negative*/);
32446 break;
32447 }
32448 case 2U: { /* byte string */
32449 if (ai == 0x1fU) {
32450 duk__cbor_decode_and_join_strbuf(dec_ctx, 0x40U);
32451 } else {
32452 duk__cbor_decode_rewind(dec_ctx, 1U);
32453 duk__cbor_decode_buffer(dec_ctx, 0x40U);
32454 }
32455 break;
32456 }
32457 case 3U: { /* text string */
32458 duk__cbor_decode_string(dec_ctx, ib, ai);
32459 break;
32460 }
32461 case 4U: { /* array of data items */
32462 if (DUK_UNLIKELY(duk__cbor_decode_array(dec_ctx, ib, ai) == 0)) {
32463 goto format_error;
32464 }
32465 break;
32466 }
32467 case 5U: { /* map of pairs of data items */
32468 if (DUK_UNLIKELY(duk__cbor_decode_map(dec_ctx, ib, ai) == 0)) {
32469 goto format_error;
32470 }
32471 break;
32472 }
32473 case 6U: { /* semantic tagging */
32474 /* Tags are ignored now, re-read initial byte. A tagged
32475 * value may itself be tagged (an unlimited number of times)
32476 * so keep on peeling away tags.
32477 */
32479 goto reread_initial_byte;
32480 }
32481 case 7U: { /* floating point numbers, simple data types, break; other */
32482 switch (ai) {
32483 case 0x14U: {
32484 duk_push_false(dec_ctx->thr);
32485 break;
32486 }
32487 case 0x15U: {
32488 duk_push_true(dec_ctx->thr);
32489 break;
32490 }
32491 case 0x16U: {
32492 duk_push_null(dec_ctx->thr);
32493 break;
32494 }
32495 case 0x17U: {
32496 duk_push_undefined(dec_ctx->thr);
32497 break;
32498 }
32499 case 0x18U: { /* more simple values (1 byte) */
32500 /* Simple value encoded in additional byte (none
32501 * are defined so far). RFC 7049 states that the
32502 * follow-up byte must be 32-255 to minimize
32503 * confusion. So, a non-shortest encoding like
32504 * f815 (= true, shortest encoding f5) must be
32505 * rejected. cbor.me tester rejects f815, but
32506 * e.g. Python CBOR binding decodes it as true.
32507 */
32508 goto format_error;
32509 }
32510 case 0x19U: { /* half-float (2 bytes) */
32511 duk_double_t d;
32512 d = duk__cbor_decode_half_float(dec_ctx);
32513 duk_push_number(dec_ctx->thr, d);
32514 break;
32515 }
32516 case 0x1aU: { /* float (4 bytes) */
32517 duk_double_t d;
32518 d = duk__cbor_decode_float(dec_ctx);
32519 duk_push_number(dec_ctx->thr, d);
32520 break;
32521 }
32522 case 0x1bU: { /* double (8 bytes) */
32523 duk_double_t d;
32524 d = duk__cbor_decode_double(dec_ctx);
32525 duk_push_number(dec_ctx->thr, d);
32526 break;
32527 }
32528 case 0xffU: /* unexpected break */
32529 default: {
32530 goto format_error;
32531 }
32532 } /* end switch */
32533 break;
32534 }
32535 default: {
32536 goto format_error; /* will never actually occur */
32537 }
32538 } /* end switch */
32539
32540 return;
32541
32542format_error:
32543 duk__cbor_decode_error(dec_ctx);
32544}
32545#endif /* DUK_CBOR_DECODE_FASTPATH */
32546
32547DUK_LOCAL void duk__cbor_encode(duk_hthread *thr, duk_idx_t idx, duk_uint_t encode_flags) {
32549 duk_uint8_t *buf;
32550
32551 DUK_UNREF(encode_flags);
32552
32553 idx = duk_require_normalize_index(thr, idx);
32554
32555 enc_ctx.thr = thr;
32556 enc_ctx.idx_buf = duk_get_top(thr);
32557
32558 enc_ctx.len = 64;
32559 buf = (duk_uint8_t *) duk_push_dynamic_buffer(thr, enc_ctx.len);
32560 enc_ctx.ptr = buf;
32561 enc_ctx.buf = buf;
32562 enc_ctx.buf_end = buf + enc_ctx.len;
32564 enc_ctx.recursion_depth = 0;
32566
32567 duk_dup(thr, idx);
32569 duk__cbor_encode_value(&enc_ctx);
32570 DUK_ASSERT(enc_ctx.recursion_depth == 0);
32571 duk_resize_buffer(enc_ctx.thr, enc_ctx.idx_buf, (duk_size_t) (enc_ctx.ptr - enc_ctx.buf));
32572 duk_replace(thr, idx);
32573}
32574
32575DUK_LOCAL void duk__cbor_decode(duk_hthread *thr, duk_idx_t idx, duk_uint_t decode_flags) {
32577
32578 DUK_UNREF(decode_flags);
32579
32580 /* Suppress compile warnings for functions only needed with e.g.
32581 * asserts enabled.
32582 */
32584
32585 idx = duk_require_normalize_index(thr, idx);
32586
32587 dec_ctx.thr = thr;
32588 dec_ctx.buf = (const duk_uint8_t *) duk_require_buffer_data(thr, idx, &dec_ctx.len);
32589 dec_ctx.off = 0;
32590 /* dec_ctx.len: set above */
32591
32592 dec_ctx.recursion_depth = 0;
32594
32596 duk__cbor_decode_value(&dec_ctx);
32597 DUK_ASSERT(dec_ctx.recursion_depth == 0);
32598 if (dec_ctx.off != dec_ctx.len) {
32599 (void) duk_type_error(thr, "trailing garbage");
32600 }
32601
32602 duk_replace(thr, idx);
32603}
32604
32605#else /* DUK_USE_CBOR_SUPPORT */
32606
32607DUK_LOCAL void duk__cbor_encode(duk_hthread *thr, duk_idx_t idx, duk_uint_t encode_flags) {
32608 DUK_UNREF(idx);
32609 DUK_UNREF(encode_flags);
32611}
32612
32614 DUK_UNREF(idx);
32615 DUK_UNREF(decode_flags);
32618
32619#endif /* DUK_USE_CBOR_SUPPORT */
32620
32621/*
32622 * Public APIs
32623 */
32625DUK_EXTERNAL void duk_cbor_encode(duk_hthread *thr, duk_idx_t idx, duk_uint_t encode_flags) {
32627 duk__cbor_encode(thr, idx, encode_flags);
32628}
32629DUK_EXTERNAL void duk_cbor_decode(duk_hthread *thr, duk_idx_t idx, duk_uint_t decode_flags) {
32631 duk__cbor_decode(thr, idx, decode_flags);
32632}
32633
32634#if defined(DUK_USE_CBOR_BUILTIN)
32635#if defined(DUK_USE_CBOR_SUPPORT)
32638
32639 duk__cbor_encode(thr, -1, 0 /*flags*/);
32640
32641 /* Produce an ArrayBuffer by first decoding into a plain buffer which
32642 * mimics a Uint8Array and gettings its .buffer property.
32643 */
32644 /* XXX: shortcut */
32646 return 1;
32647}
32648
32650 DUK_ASSERT_TOP(thr, 1);
32651
32652 duk__cbor_decode(thr, -1, 0 /*flags*/);
32653 return 1;
32654}
32655#else /* DUK_USE_CBOR_SUPPORT */
32658 DUK_WO_NORETURN(return 0;);
32659}
32662 DUK_WO_NORETURN(return 0;);
32663}
32664#endif /* DUK_USE_CBOR_SUPPORT */
32665#endif /* DUK_USE_CBOR_BUILTIN */
32666
32667/* automatic undefs */
32668#undef DUK__CBOR_AI
32669/*
32670 * Date built-ins
32671 *
32672 * Unlike most built-ins, Date has some platform dependencies for getting
32673 * UTC time, converting between UTC and local time, and parsing and
32674 * formatting time values. These are all abstracted behind DUK_USE_xxx
32675 * config options. There are built-in platform specific providers for
32676 * POSIX and Windows, but external providers can also be used.
32677 *
32678 * See doc/datetime.rst.
32679 *
32680 */
32681
32682/* #include duk_internal.h -> already included */
32683
32684/* XXX: currently defines unnecessary symbols when DUK_USE_DATE_BUILTIN is disabled. */
32685
32686/*
32687 * Forward declarations
32689
32694
32695/*
32696 * Other file level defines
32697 */
32698
32699/* Debug macro to print all parts and dparts (used manually because of debug level). */
32700#define DUK__DPRINT_PARTS_AND_DPARTS(parts, dparts) \
32701 do { \
32702 DUK_D(DUK_DPRINT("parts: %ld %ld %ld %ld %ld %ld %ld %ld, dparts: %lf %lf %lf %lf %lf %lf %lf %lf", \
32703 (long) (parts)[0], \
32704 (long) (parts)[1], \
32705 (long) (parts)[2], \
32706 (long) (parts)[3], \
32707 (long) (parts)[4], \
32708 (long) (parts)[5], \
32709 (long) (parts)[6], \
32710 (long) (parts)[7], \
32711 (double) (dparts)[0], \
32712 (double) (dparts)[1], \
32713 (double) (dparts)[2], \
32714 (double) (dparts)[3], \
32715 (double) (dparts)[4], \
32716 (double) (dparts)[5], \
32717 (double) (dparts)[6], \
32718 (double) (dparts)[7])); \
32719 } while (0)
32720#define DUK__DPRINT_PARTS(parts) \
32721 do { \
32722 DUK_D(DUK_DPRINT("parts: %ld %ld %ld %ld %ld %ld %ld %ld", \
32723 (long) (parts)[0], \
32724 (long) (parts)[1], \
32725 (long) (parts)[2], \
32726 (long) (parts)[3], \
32727 (long) (parts)[4], \
32728 (long) (parts)[5], \
32729 (long) (parts)[6], \
32730 (long) (parts)[7])); \
32731 } while (0)
32732#define DUK__DPRINT_DPARTS(dparts) \
32733 do { \
32734 DUK_D(DUK_DPRINT("dparts: %lf %lf %lf %lf %lf %lf %lf %lf", \
32735 (double) (dparts)[0], \
32736 (double) (dparts)[1], \
32737 (double) (dparts)[2], \
32738 (double) (dparts)[3], \
32739 (double) (dparts)[4], \
32740 (double) (dparts)[5], \
32741 (double) (dparts)[6], \
32742 (double) (dparts)[7])); \
32743 } while (0)
32744
32745/* Equivalent year for DST calculations outside [1970,2038[ range, see
32746 * E5 Section 15.9.1.8. Equivalent year has the same leap-year-ness and
32747 * starts with the same weekday on Jan 1.
32748 * https://bugzilla.mozilla.org/show_bug.cgi?id=351066
32749 */
32750#define DUK__YEAR(x) ((duk_uint8_t) ((x) -1970))
32751DUK_LOCAL duk_uint8_t duk__date_equivyear[14] = {
32752#if 1
32753 /* This is based on V8 EquivalentYear() algorithm (see util/genequivyear.py):
32754 * http://code.google.com/p/v8/source/browse/trunk/src/date.h#146
32755 */
32756
32757 /* non-leap year: sunday, monday, ... */
32758 DUK__YEAR(2023),
32759 DUK__YEAR(2035),
32760 DUK__YEAR(2019),
32761 DUK__YEAR(2031),
32762 DUK__YEAR(2015),
32763 DUK__YEAR(2027),
32764 DUK__YEAR(2011),
32765
32766 /* leap year: sunday, monday, ... */
32767 DUK__YEAR(2012),
32768 DUK__YEAR(2024),
32769 DUK__YEAR(2008),
32770 DUK__YEAR(2020),
32771 DUK__YEAR(2032),
32772 DUK__YEAR(2016),
32773 DUK__YEAR(2028)
32774#endif
32775
32776#if 0
32777 /* This is based on Rhino EquivalentYear() algorithm:
32778 * https://github.com/mozilla/rhino/blob/f99cc11d616f0cdda2c42bde72b3484df6182947/src/org/mozilla/javascript/NativeDate.java
32779 */
32780
32781 /* non-leap year: sunday, monday, ... */
32782 DUK__YEAR(1978), DUK__YEAR(1973), DUK__YEAR(1985), DUK__YEAR(1986),
32783 DUK__YEAR(1981), DUK__YEAR(1971), DUK__YEAR(1977),
32785 /* leap year: sunday, monday, ... */
32786 DUK__YEAR(1984), DUK__YEAR(1996), DUK__YEAR(1980), DUK__YEAR(1992),
32787 DUK__YEAR(1976), DUK__YEAR(1988), DUK__YEAR(1972)
32788#endif
32792 * ISO 8601 subset parser.
32795/* Parser part count. */
32796#define DUK__NUM_ISO8601_PARSER_PARTS 9
32797
32798/* Parser part indices. */
32799#define DUK__PI_YEAR 0
32800#define DUK__PI_MONTH 1
32801#define DUK__PI_DAY 2
32802#define DUK__PI_HOUR 3
32803#define DUK__PI_MINUTE 4
32804#define DUK__PI_SECOND 5
32805#define DUK__PI_MILLISECOND 6
32806#define DUK__PI_TZHOUR 7
32807#define DUK__PI_TZMINUTE 8
32808
32809/* Parser part masks. */
32810#define DUK__PM_YEAR (1 << DUK__PI_YEAR)
32811#define DUK__PM_MONTH (1 << DUK__PI_MONTH)
32812#define DUK__PM_DAY (1 << DUK__PI_DAY)
32813#define DUK__PM_HOUR (1 << DUK__PI_HOUR)
32814#define DUK__PM_MINUTE (1 << DUK__PI_MINUTE)
32815#define DUK__PM_SECOND (1 << DUK__PI_SECOND)
32816#define DUK__PM_MILLISECOND (1 << DUK__PI_MILLISECOND)
32817#define DUK__PM_TZHOUR (1 << DUK__PI_TZHOUR)
32818#define DUK__PM_TZMINUTE (1 << DUK__PI_TZMINUTE)
32820/* Parser separator indices. */
32821#define DUK__SI_PLUS 0
32822#define DUK__SI_MINUS 1
32823#define DUK__SI_T 2
32824#define DUK__SI_SPACE 3
32825#define DUK__SI_COLON 4
32826#define DUK__SI_PERIOD 5
32827#define DUK__SI_Z 6
32828#define DUK__SI_NUL 7
32830/* Parser separator masks. */
32831#define DUK__SM_PLUS (1 << DUK__SI_PLUS)
32832#define DUK__SM_MINUS (1 << DUK__SI_MINUS)
32833#define DUK__SM_T (1 << DUK__SI_T)
32834#define DUK__SM_SPACE (1 << DUK__SI_SPACE)
32835#define DUK__SM_COLON (1 << DUK__SI_COLON)
32836#define DUK__SM_PERIOD (1 << DUK__SI_PERIOD)
32837#define DUK__SM_Z (1 << DUK__SI_Z)
32838#define DUK__SM_NUL (1 << DUK__SI_NUL)
32839
32840/* Rule control flags. */
32841#define DUK__CF_NEG (1 << 0) /* continue matching, set neg_tzoffset flag */
32842#define DUK__CF_ACCEPT (1 << 1) /* accept string */
32843#define DUK__CF_ACCEPT_NUL (1 << 2) /* accept string if next char is NUL (otherwise reject) */
32844
32845#define DUK__PACK_RULE(partmask, sepmask, nextpart, flags) \
32846 ((duk_uint32_t) (partmask) + (((duk_uint32_t) (sepmask)) << 9) + (((duk_uint32_t) (nextpart)) << 17) + \
32847 (((duk_uint32_t) (flags)) << 21))
32848
32849#define DUK__UNPACK_RULE(rule, var_nextidx, var_flags) \
32850 do { \
32851 (var_nextidx) = (duk_small_uint_t) (((rule) >> 17) & 0x0f); \
32852 (var_flags) = (duk_small_uint_t) ((rule) >> 21); \
32853 } while (0)
32854
32855#define DUK__RULE_MASK_PART_SEP 0x1ffffUL
32856
32857/* Matching separator index is used in the control table */
32858DUK_LOCAL const duk_uint8_t duk__parse_iso8601_seps[] = {
32859 DUK_ASC_PLUS /*0*/, DUK_ASC_MINUS /*1*/, DUK_ASC_UC_T /*2*/, DUK_ASC_SPACE /*3*/,
32860 DUK_ASC_COLON /*4*/, DUK_ASC_PERIOD /*5*/, DUK_ASC_UC_Z /*6*/, DUK_ASC_NUL /*7*/
32861};
32862
32863/* Rule table: first matching rule is used to determine what to do next. */
32864DUK_LOCAL const duk_uint32_t duk__parse_iso8601_control[] = {
32876 0),
32881 DUK__CF_NEG),
32884 DUK__SM_Z,
32885 0,
32890 0,
32892
32893 /* Note1: the specification doesn't require matching a time form with
32894 * just hours ("HH"), but we accept it here, e.g. "2012-01-02T12Z".
32895 *
32896 * Note2: the specification doesn't require matching a timezone offset
32897 * with just hours ("HH"), but accept it here, e.g. "2012-01-02T03:04:05+02"
32898 */
32899};
32900
32904 duk_double_t d;
32905 const duk_uint8_t *p;
32906 duk_small_uint_t part_idx = 0;
32907 duk_int_t accum = 0;
32908 duk_small_uint_t ndigits = 0;
32909 duk_bool_t neg_year = 0;
32910 duk_bool_t neg_tzoffset = 0;
32913
32914 /* During parsing, month and day are one-based; set defaults here. */
32915 duk_memzero(parts, sizeof(parts));
32916 DUK_ASSERT(parts[DUK_DATE_IDX_YEAR] == 0); /* don't care value, year is mandatory */
32917 parts[DUK_DATE_IDX_MONTH] = 1;
32918 parts[DUK_DATE_IDX_DAY] = 1;
32919
32920 /* Special handling for year sign. */
32921 p = (const duk_uint8_t *) str;
32922 ch = p[0];
32923 if (ch == DUK_ASC_PLUS) {
32924 p++;
32925 } else if (ch == DUK_ASC_MINUS) {
32926 neg_year = 1;
32927 p++;
32928 }
32929
32930 for (;;) {
32931 ch = *p++;
32932 DUK_DDD(DUK_DDDPRINT("parsing, part_idx=%ld, char=%ld ('%c')",
32933 (long) part_idx,
32934 (long) ch,
32935 (int) ((ch >= 0x20 && ch <= 0x7e) ? ch : DUK_ASC_QUESTION)));
32936
32937 if (ch >= DUK_ASC_0 && ch <= DUK_ASC_9) {
32938 if (ndigits >= 9) {
32939 DUK_DDD(DUK_DDDPRINT("too many digits -> reject"));
32940 goto reject;
32941 }
32942 if (part_idx == DUK__PI_MILLISECOND && ndigits >= 3) {
32943 /* ignore millisecond fractions after 3 */
32944 } else {
32945 accum = accum * 10 + ((duk_int_t) ch) - ((duk_int_t) DUK_ASC_0) + 0x00;
32946 ndigits++;
32947 }
32948 } else {
32949 duk_uint_fast32_t match_val;
32950 duk_small_uint_t sep_idx;
32951
32952 if (ndigits <= 0) {
32953 goto reject;
32954 }
32955 if (part_idx == DUK__PI_MILLISECOND) {
32956 /* complete the millisecond field */
32957 while (ndigits < 3) {
32958 accum *= 10;
32959 ndigits++;
32960 }
32961 }
32962 parts[part_idx] = accum;
32963 DUK_DDD(DUK_DDDPRINT("wrote part %ld -> value %ld", (long) part_idx, (long) accum));
32964
32965 accum = 0;
32966 ndigits = 0;
32967
32968 for (i = 0; i < (duk_small_uint_t) (sizeof(duk__parse_iso8601_seps) / sizeof(duk_uint8_t)); i++) {
32969 if (duk__parse_iso8601_seps[i] == ch) {
32970 break;
32971 }
32972 }
32973 if (i == (duk_small_uint_t) (sizeof(duk__parse_iso8601_seps) / sizeof(duk_uint8_t))) {
32974 DUK_DDD(DUK_DDDPRINT("separator character doesn't match -> reject"));
32975 goto reject;
32976 }
32977
32978 sep_idx = i;
32979 match_val = (1UL << part_idx) + (1UL << (sep_idx + 9)); /* match against rule part/sep bits */
32980
32981 for (i = 0; i < (duk_small_uint_t) (sizeof(duk__parse_iso8601_control) / sizeof(duk_uint32_t)); i++) {
32983 duk_small_uint_t nextpart;
32984 duk_small_uint_t cflags;
32985
32986 DUK_DDD(DUK_DDDPRINT("part_idx=%ld, sep_idx=%ld, match_val=0x%08lx, considering rule=0x%08lx",
32987 (long) part_idx,
32988 (long) sep_idx,
32989 (unsigned long) match_val,
32990 (unsigned long) rule));
32991
32992 if ((rule & match_val) != match_val) {
32993 continue;
32994 }
32995
32996 DUK__UNPACK_RULE(rule, nextpart, cflags);
32997
32998 DUK_DDD(DUK_DDDPRINT("rule match -> part_idx=%ld, sep_idx=%ld, match_val=0x%08lx, "
32999 "rule=0x%08lx -> nextpart=%ld, cflags=0x%02lx",
33000 (long) part_idx,
33001 (long) sep_idx,
33002 (unsigned long) match_val,
33003 (unsigned long) rule,
33004 (long) nextpart,
33005 (unsigned long) cflags));
33006
33007 if (cflags & DUK__CF_NEG) {
33008 neg_tzoffset = 1;
33009 }
33010
33011 if (cflags & DUK__CF_ACCEPT) {
33012 goto accept;
33013 }
33014
33015 if (cflags & DUK__CF_ACCEPT_NUL) {
33016 DUK_ASSERT(*(p - 1) != (char) 0);
33017 if (*p == DUK_ASC_NUL) {
33018 goto accept;
33019 }
33020 goto reject;
33021 }
33022
33023 part_idx = nextpart;
33024 break;
33025 } /* rule match */
33026
33027 if (i == (duk_small_uint_t) (sizeof(duk__parse_iso8601_control) / sizeof(duk_uint32_t))) {
33028 DUK_DDD(DUK_DDDPRINT("no rule matches -> reject"));
33029 goto reject;
33030 }
33031
33032 if (ch == 0) {
33033 /* This shouldn't be necessary, but check just in case
33034 * to avoid any chance of overruns.
33035 */
33036 DUK_DDD(DUK_DDDPRINT("NUL after rule matching (should not happen) -> reject"));
33037 goto reject;
33038 }
33039 } /* if-digit-else-ctrl */
33040 } /* char loop */
33041
33042 /* We should never exit the loop above. */
33044
33045reject:
33046 DUK_DDD(DUK_DDDPRINT("reject"));
33047 return 0;
33048
33049accept:
33050 DUK_DDD(DUK_DDDPRINT("accept"));
33051
33052 /* Apply timezone offset to get the main parts in UTC */
33053 if (neg_year) {
33054 parts[DUK__PI_YEAR] = -parts[DUK__PI_YEAR];
33055 }
33056 if (neg_tzoffset) {
33057 parts[DUK__PI_HOUR] += parts[DUK__PI_TZHOUR];
33058 parts[DUK__PI_MINUTE] += parts[DUK__PI_TZMINUTE];
33059 } else {
33060 parts[DUK__PI_HOUR] -= parts[DUK__PI_TZHOUR];
33061 parts[DUK__PI_MINUTE] -= parts[DUK__PI_TZMINUTE];
33062 }
33063 parts[DUK__PI_MONTH] -= 1; /* zero-based month */
33064 parts[DUK__PI_DAY] -= 1; /* zero-based day */
33065
33066 /* Use double parts, they tolerate unnormalized time.
33067 *
33068 * Note: DUK_DATE_IDX_WEEKDAY is initialized with a bogus value (DUK__PI_TZHOUR)
33069 * on purpose. It won't be actually used by duk_bi_date_get_timeval_from_dparts(),
33070 * but will make the value initialized just in case, and avoid any
33071 * potential for Valgrind issues.
33072 */
33073 for (i = 0; i < DUK_DATE_IDX_NUM_PARTS; i++) {
33074 DUK_DDD(DUK_DDDPRINT("part[%ld] = %ld", (long) i, (long) parts[i]));
33075 dparts[i] = parts[i];
33076 }
33077
33078 d = duk_bi_date_get_timeval_from_dparts(dparts, 0 /*flags*/);
33079 duk_push_number(thr, d);
33080 return 1;
33081}
33082
33083/*
33084 * Date/time parsing helper.
33085 *
33086 * Parse a datetime string into a time value. We must first try to parse
33087 * the input according to the standard format in E5.1 Section 15.9.1.15.
33088 * If that fails, we can try to parse using custom parsing, which can
33089 * either be platform neutral (custom code) or platform specific (using
33090 * existing platform API calls).
33091 *
33092 * Note in particular that we must parse whatever toString(), toUTCString(),
33093 * and toISOString() can produce; see E5.1 Section 15.9.4.2.
33094 *
33095 * Returns 1 to allow tail calling.
33096 *
33097 * There is much room for improvement here with respect to supporting
33098 * alternative datetime formats. For instance, V8 parses '2012-01-01' as
33099 * UTC and '2012/01/01' as local time.
33100 */
33101
33102DUK_LOCAL duk_ret_t duk__parse_string(duk_hthread *thr, const char *str) {
33103 /* XXX: there is a small risk here: because the ISO 8601 parser is
33104 * very loose, it may end up parsing some datetime values which
33105 * would be better parsed with a platform specific parser.
33106 */
33107
33108 DUK_ASSERT(str != NULL);
33109 DUK_DDD(DUK_DDDPRINT("parse datetime from string '%s'", (const char *) str));
33110
33111 if (duk__parse_string_iso8601_subset(thr, str) != 0) {
33112 return 1;
33113 }
33114
33115#if defined(DUK_USE_DATE_PARSE_STRING)
33116 /* Contract, either:
33117 * - Push value on stack and return 1
33118 * - Don't push anything on stack and return 0
33119 */
33120
33121 if (DUK_USE_DATE_PARSE_STRING(thr, str) != 0) {
33122 return 1;
33123 }
33124#else
33125 /* No platform-specific parsing, this is not an error. */
33126#endif
33127
33128 duk_push_nan(thr);
33129 return 1;
33130}
33131
33132/*
33133 * Calendar helpers
33134 *
33135 * Some helpers are used for getters and can operate on normalized values
33136 * which can be represented with 32-bit signed integers. Other helpers are
33137 * needed by setters and operate on un-normalized double values, must watch
33138 * out for non-finite numbers etc.
33139 */
33140
33141DUK_LOCAL duk_uint8_t duk__days_in_month[12] = { (duk_uint8_t) 31, (duk_uint8_t) 28, (duk_uint8_t) 31, (duk_uint8_t) 30,
33142 (duk_uint8_t) 31, (duk_uint8_t) 30, (duk_uint8_t) 31, (duk_uint8_t) 31,
33143 (duk_uint8_t) 30, (duk_uint8_t) 31, (duk_uint8_t) 30, (duk_uint8_t) 31 };
33145/* Maximum iteration count for computing UTC-to-local time offset when
33146 * creating an ECMAScript time value from local parts.
33147 */
33148#define DUK__LOCAL_TZOFFSET_MAXITER 4
33149
33150/* Because 'day since epoch' can be negative and is used to compute weekday
33151 * using a modulo operation, add this multiple of 7 to avoid negative values
33152 * when year is below 1970 epoch. ECMAScript time values are restricted to
33153 * +/- 100 million days from epoch, so this adder fits nicely into 32 bits.
33154 * Round to a multiple of 7 (= floor(100000000 / 7) * 7) and add margin.
33155 */
33156#define DUK__WEEKDAY_MOD_ADDER (20000000 * 7) /* 0x08583b00 */
33157
33159 if ((year % 4) != 0) {
33160 return 0;
33161 }
33162 if ((year % 100) != 0) {
33163 return 1;
33164 }
33165 if ((year % 400) != 0) {
33166 return 0;
33168 return 1;
33169}
33170
33172 return (x >= -DUK_DATE_MSEC_100M_DAYS && x <= DUK_DATE_MSEC_100M_DAYS);
33173}
33174
33177}
33178
33180 return (x >= DUK_DATE_MIN_ECMA_YEAR && x <= DUK_DATE_MAX_ECMA_YEAR);
33181}
33182
33184 if (!DUK_ISFINITE(x)) {
33185 return DUK_DOUBLE_NAN;
33186 }
33189 return DUK_DOUBLE_NAN;
33190 }
33191
33193
33194 /* Here we'd have the option to normalize -0 to +0. */
33195 return x;
33196}
33197
33198/* Integer division which floors also negative values correctly. */
33200 DUK_ASSERT(b > 0);
33201 if (a >= 0) {
33202 return a / b;
33203 } else {
33204 /* e.g. a = -4, b = 5 --> -4 - 5 + 1 / 5 --> -8 / 5 --> -1
33205 * a = -5, b = 5 --> -5 - 5 + 1 / 5 --> -9 / 5 --> -1
33206 * a = -6, b = 5 --> -6 - 5 + 1 / 5 --> -10 / 5 --> -2
33207 */
33208 return (a - b + 1) / b;
33209 }
33211
33212/* Compute day number of the first day of a given year. */
33214 /* Note: in integer arithmetic, (x / 4) is same as floor(x / 4) for non-negative
33215 * values, but is incorrect for negative ones.
33216 */
33217 return 365 * (year - 1970) + duk__div_floor(year - 1969, 4) - duk__div_floor(year - 1901, 100) +
33218 duk__div_floor(year - 1601, 400);
33219}
33220
33221/* Given a day number, determine year and day-within-year. */
33223 duk_int_t year;
33224 duk_int_t diff_days;
33225
33226 /* estimate year upwards (towards positive infinity), then back down;
33227 * two iterations should be enough
33228 */
33229
33230 if (day >= 0) {
33231 year = 1970 + day / 365;
33232 } else {
33233 year = 1970 + day / 366;
33234 }
33235
33236 for (;;) {
33237 diff_days = duk__day_from_year(year) - day;
33238 DUK_DDD(DUK_DDDPRINT("year=%ld day=%ld, diff_days=%ld", (long) year, (long) day, (long) diff_days));
33239 if (diff_days <= 0) {
33240 DUK_ASSERT(-diff_days < 366); /* fits into duk_small_int_t */
33241 *out_day_within_year = -diff_days;
33242 DUK_DDD(DUK_DDDPRINT("--> year=%ld, day-within-year=%ld", (long) year, (long) *out_day_within_year));
33243 DUK_ASSERT(*out_day_within_year >= 0);
33244 DUK_ASSERT(*out_day_within_year < (duk_bi_date_is_leap_year(year) ? 366 : 365));
33245 return year;
33247
33248 /* Note: this is very tricky; we must never 'overshoot' the
33249 * correction downwards.
33250 */
33251 year -= 1 + (diff_days - 1) / 366; /* conservative */
33252 }
33253}
33254
33255/* Given a (year, month, day-within-month) triple, compute day number.
33256 * The input triple is un-normalized and may contain non-finite values.
33257 */
33259 duk_int_t day_num;
33260 duk_bool_t is_leap;
33261 duk_small_int_t i, n;
33262
33263 /* Assume that year, month, day are all coerced to whole numbers.
33264 * They may also be NaN or infinity, in which case this function
33265 * must return NaN or infinity to ensure time value becomes NaN.
33266 * If 'day' is NaN, the final return will end up returning a NaN,
33267 * so it doesn't need to be checked here.
33268 */
33269
33270 if (!DUK_ISFINITE(year) || !DUK_ISFINITE(month)) {
33271 return DUK_DOUBLE_NAN;
33272 }
33273
33274 year += DUK_FLOOR(month / 12.0);
33275
33276 month = DUK_FMOD(month, 12.0);
33277 if (month < 0.0) {
33278 /* handle negative values */
33279 month += 12.0;
33280 }
33281
33282 /* The algorithm in E5.1 Section 15.9.1.12 normalizes month, but
33283 * does not normalize the day-of-month (nor check whether or not
33284 * it is finite) because it's not necessary for finding the day
33285 * number which matches the (year,month) pair.
33286 *
33287 * We assume that duk__day_from_year() is exact here.
33288 *
33289 * Without an explicit infinity / NaN check in the beginning,
33290 * day_num would be a bogus integer here.
33291 *
33292 * It's possible for 'year' to be out of integer range here.
33293 * If so, we need to return NaN without integer overflow.
33294 * This fixes test-bug-setyear-overflow.js.
33295 */
33296
33298 DUK_DD(DUK_DDPRINT("year not in ecmascript valid range, avoid integer overflow: %lf", (double) year));
33299 return DUK_DOUBLE_NAN;
33300 }
33301 day_num = duk__day_from_year((duk_int_t) year);
33302 is_leap = duk_bi_date_is_leap_year((duk_int_t) year);
33303
33304 n = (duk_small_int_t) month;
33305 for (i = 0; i < n; i++) {
33306 day_num += duk__days_in_month[i];
33307 if (i == 1 && is_leap) {
33308 day_num++;
33309 }
33310 }
33311
33312 /* If 'day' is NaN, returns NaN. */
33313 return (duk_double_t) day_num + day;
33314}
33315
33316/* Split time value into parts. The time value may contain fractions (it may
33317 * come from duk_time_to_components() API call) which are truncated. Possible
33318 * local time adjustment has already been applied when reading the time value.
33319 */
33321 duk_double_t d1, d2;
33322 duk_int_t t1, t2;
33323 duk_int_t day_since_epoch;
33324 duk_int_t year; /* does not fit into 16 bits */
33325 duk_small_int_t day_in_year;
33326 duk_small_int_t month;
33327 duk_small_int_t day;
33328 duk_small_int_t dim;
33329 duk_int_t jan1_since_epoch;
33330 duk_small_int_t jan1_weekday;
33331 duk_int_t equiv_year;
33333 duk_bool_t is_leap;
33334 duk_small_int_t arridx;
33335
33336 DUK_ASSERT(DUK_ISFINITE(d)); /* caller checks */
33337 d = DUK_FLOOR(d); /* remove fractions if present */
33339
33340 /* The timevalue must be in valid ECMAScript range, but since a local
33341 * time offset can be applied, we need to allow a +/- 24h leeway to
33342 * the value. In other words, although the UTC time is within the
33343 * ECMAScript range, the local part values can be just outside of it.
33344 */
33347
33348 /* These computations are guaranteed to be exact for the valid
33349 * E5 time value range, assuming milliseconds without fractions.
33350 */
33351 d1 = (duk_double_t) DUK_FMOD(d, (double) DUK_DATE_MSEC_DAY);
33352 if (d1 < 0.0) {
33353 /* deal with negative values */
33355 }
33356 d2 = DUK_FLOOR((double) (d / (duk_double_t) DUK_DATE_MSEC_DAY));
33358 /* now expected to fit into a 32-bit integer */
33359 t1 = (duk_int_t) d1;
33360 t2 = (duk_int_t) d2;
33361 day_since_epoch = t2;
33364
33365 /* t1 = milliseconds within day (fits 32 bit)
33366 * t2 = day number from epoch (fits 32 bit, may be negative)
33367 */
33368
33369 parts[DUK_DATE_IDX_MILLISECOND] = t1 % 1000;
33370 t1 /= 1000;
33371 parts[DUK_DATE_IDX_SECOND] = t1 % 60;
33372 t1 /= 60;
33373 parts[DUK_DATE_IDX_MINUTE] = t1 % 60;
33374 t1 /= 60;
33375 parts[DUK_DATE_IDX_HOUR] = t1;
33376 DUK_ASSERT(parts[DUK_DATE_IDX_MILLISECOND] >= 0 && parts[DUK_DATE_IDX_MILLISECOND] <= 999);
33377 DUK_ASSERT(parts[DUK_DATE_IDX_SECOND] >= 0 && parts[DUK_DATE_IDX_SECOND] <= 59);
33378 DUK_ASSERT(parts[DUK_DATE_IDX_MINUTE] >= 0 && parts[DUK_DATE_IDX_MINUTE] <= 59);
33379 DUK_ASSERT(parts[DUK_DATE_IDX_HOUR] >= 0 && parts[DUK_DATE_IDX_HOUR] <= 23);
33380
33381 DUK_DDD(DUK_DDDPRINT("d=%lf, d1=%lf, d2=%lf, t1=%ld, t2=%ld, parts: hour=%ld min=%ld sec=%ld msec=%ld",
33382 (double) d,
33383 (double) d1,
33384 (double) d2,
33385 (long) t1,
33386 (long) t2,
33387 (long) parts[DUK_DATE_IDX_HOUR],
33388 (long) parts[DUK_DATE_IDX_MINUTE],
33389 (long) parts[DUK_DATE_IDX_SECOND],
33390 (long) parts[DUK_DATE_IDX_MILLISECOND]));
33391
33392 /* This assert depends on the input parts representing time inside
33393 * the ECMAScript range.
33394 */
33396 parts[DUK_DATE_IDX_WEEKDAY] = (t2 + 4 + DUK__WEEKDAY_MOD_ADDER) % 7; /* E5.1 Section 15.9.1.6 */
33397 DUK_ASSERT(parts[DUK_DATE_IDX_WEEKDAY] >= 0 && parts[DUK_DATE_IDX_WEEKDAY] <= 6);
33398
33399 year = duk__year_from_day(t2, &day_in_year);
33400 day = day_in_year;
33401 is_leap = duk_bi_date_is_leap_year(year);
33402 for (month = 0; month < 12; month++) {
33403 dim = duk__days_in_month[month];
33404 if (month == 1 && is_leap) {
33405 dim++;
33406 }
33407 DUK_DDD(DUK_DDDPRINT("month=%ld, dim=%ld, day=%ld", (long) month, (long) dim, (long) day));
33408 if (day < dim) {
33409 break;
33410 }
33411 day -= dim;
33412 }
33413 DUK_DDD(DUK_DDDPRINT("final month=%ld", (long) month));
33414 DUK_ASSERT(month >= 0 && month <= 11);
33415 DUK_ASSERT(day >= 0 && day <= 31);
33416
33417 /* Equivalent year mapping, used to avoid DST trouble when platform
33418 * may fail to provide reasonable DST answers for dates outside the
33419 * ordinary range (e.g. 1970-2038). An equivalent year has the same
33420 * leap-year-ness as the original year and begins on the same weekday
33421 * (Jan 1).
33422 *
33423 * The year 2038 is avoided because there seem to be problems with it
33424 * on some platforms. The year 1970 is also avoided as there were
33425 * practical problems with it; an equivalent year is used for it too,
33426 * which breaks some DST computations for 1970 right now, see e.g.
33427 * test-bi-date-tzoffset-brute-fi.js.
33428 */
33429 if ((flags & DUK_DATE_FLAG_EQUIVYEAR) && (year < 1971 || year > 2037)) {
33430 DUK_ASSERT(is_leap == 0 || is_leap == 1);
33431
33432 jan1_since_epoch = day_since_epoch - day_in_year; /* day number for Jan 1 since epoch */
33433 DUK_ASSERT(jan1_since_epoch + DUK__WEEKDAY_MOD_ADDER >= 0);
33434 jan1_weekday = (jan1_since_epoch + 4 + DUK__WEEKDAY_MOD_ADDER) % 7; /* E5.1 Section 15.9.1.6 */
33435 DUK_ASSERT(jan1_weekday >= 0 && jan1_weekday <= 6);
33436 arridx = jan1_weekday;
33437 if (is_leap) {
33438 arridx += 7;
33439 }
33440 DUK_ASSERT(arridx >= 0 && arridx < (duk_small_int_t) (sizeof(duk__date_equivyear) / sizeof(duk_uint8_t)));
33441
33442 equiv_year = (duk_int_t) duk__date_equivyear[arridx] + 1970;
33443 year = equiv_year;
33444 DUK_DDD(DUK_DDDPRINT("equiv year mapping, year=%ld, day_in_year=%ld, day_since_epoch=%ld, "
33445 "jan1_since_epoch=%ld, jan1_weekday=%ld -> equiv year %ld",
33446 (long) year,
33447 (long) day_in_year,
33448 (long) day_since_epoch,
33449 (long) jan1_since_epoch,
33450 (long) jan1_weekday,
33451 (long) equiv_year));
33452 }
33453
33454 parts[DUK_DATE_IDX_YEAR] = year;
33455 parts[DUK_DATE_IDX_MONTH] = month;
33456 parts[DUK_DATE_IDX_DAY] = day;
33457
33458 if (flags & DUK_DATE_FLAG_ONEBASED) {
33459 parts[DUK_DATE_IDX_MONTH]++; /* zero-based -> one-based */
33460 parts[DUK_DATE_IDX_DAY]++; /* -""- */
33461 }
33462
33463 if (dparts != NULL) {
33464 for (i = 0; i < DUK_DATE_IDX_NUM_PARTS; i++) {
33465 dparts[i] = (duk_double_t) parts[i];
33466 }
33467 }
33468}
33469
33470/* Compute time value from (double) parts. The parts can be either UTC
33471 * or local time; if local, they need to be (conceptually) converted into
33472 * UTC time. The parts may represent valid or invalid time, and may be
33473 * wildly out of range (but may cancel each other and still come out in
33474 * the valid Date range).
33475 */
33477#if defined(DUK_USE_PARANOID_DATE_COMPUTATION)
33478 /* See comments below on MakeTime why these are volatile. */
33479 volatile duk_double_t tmp_time;
33480 volatile duk_double_t tmp_day;
33481 volatile duk_double_t d;
33482#else
33483 duk_double_t tmp_time;
33484 duk_double_t tmp_day;
33485 duk_double_t d;
33486#endif
33488 duk_int_t tzoff, tzoffprev1, tzoffprev2;
33489
33490 /* Expects 'this' at top of stack on entry. */
33491
33492 /* Coerce all finite parts with ToInteger(). ToInteger() must not
33493 * be called for NaN/Infinity because it will convert e.g. NaN to
33494 * zero. If ToInteger() has already been called, this has no side
33495 * effects and is idempotent.
33496 *
33497 * Don't read dparts[DUK_DATE_IDX_WEEKDAY]; it will cause Valgrind
33498 * issues if the value is uninitialized.
33499 */
33500 for (i = 0; i <= DUK_DATE_IDX_MILLISECOND; i++) {
33501 /* SCANBUILD: scan-build complains here about assigned value
33502 * being garbage or undefined. This is correct but operating
33503 * on undefined values has no ill effect and is ignored by the
33504 * caller in the case where this happens.
33505 */
33506 d = dparts[i];
33507 if (DUK_ISFINITE(d)) {
33508 dparts[i] = duk_js_tointeger_number(d);
33509 }
33510 }
33511
33512 /* Use explicit steps in computation to try to ensure that
33513 * computation happens with intermediate results coerced to
33514 * double values (instead of using something more accurate).
33515 * E.g. E5.1 Section 15.9.1.11 requires use of IEEE 754
33516 * rules (= ECMAScript '+' and '*' operators).
33517 *
33518 * Without 'volatile' even this approach fails on some platform
33519 * and compiler combinations. For instance, gcc 4.8.1 on Ubuntu
33520 * 64-bit, with -m32 and without -std=c99, test-bi-date-canceling.js
33521 * would fail because of some optimizations when computing tmp_time
33522 * (MakeTime below). Adding 'volatile' to tmp_time solved this
33523 * particular problem (annoyingly, also adding debug prints or
33524 * running the executable under valgrind hides it).
33525 */
33526
33527 /* MakeTime */
33528 tmp_time = 0.0;
33529 tmp_time += dparts[DUK_DATE_IDX_HOUR] * ((duk_double_t) DUK_DATE_MSEC_HOUR);
33530 tmp_time += dparts[DUK_DATE_IDX_MINUTE] * ((duk_double_t) DUK_DATE_MSEC_MINUTE);
33531 tmp_time += dparts[DUK_DATE_IDX_SECOND] * ((duk_double_t) DUK_DATE_MSEC_SECOND);
33532 tmp_time += dparts[DUK_DATE_IDX_MILLISECOND];
33533
33534 /* MakeDay */
33535 tmp_day = duk__make_day(dparts[DUK_DATE_IDX_YEAR], dparts[DUK_DATE_IDX_MONTH], dparts[DUK_DATE_IDX_DAY]);
33536
33537 /* MakeDate */
33538 d = tmp_day * ((duk_double_t) DUK_DATE_MSEC_DAY) + tmp_time;
33539
33540 DUK_DDD(DUK_DDDPRINT("time=%lf day=%lf --> timeval=%lf", (double) tmp_time, (double) tmp_day, (double) d));
33541
33542 /* Optional UTC conversion. */
33543 if (flags & DUK_DATE_FLAG_LOCALTIME) {
33544 /* DUK_USE_DATE_GET_LOCAL_TZOFFSET() needs to be called with a
33545 * time value computed from UTC parts. At this point we only
33546 * have 'd' which is a time value computed from local parts, so
33547 * it is off by the UTC-to-local time offset which we don't know
33548 * yet. The current solution for computing the UTC-to-local
33549 * time offset is to iterate a few times and detect a fixed
33550 * point or a two-cycle loop (or a sanity iteration limit),
33551 * see test-bi-date-local-parts.js and test-bi-date-tzoffset-basic-fi.js.
33552 *
33553 * E5.1 Section 15.9.1.9:
33554 * UTC(t) = t - LocalTZA - DaylightSavingTA(t - LocalTZA)
33555 *
33556 * For NaN/inf, DUK_USE_DATE_GET_LOCAL_TZOFFSET() returns 0.
33557 */
33558
33559#if 0
33560 /* Old solution: don't iterate, incorrect */
33561 tzoff = DUK_USE_DATE_GET_LOCAL_TZOFFSET(d);
33562 DUK_DDD(DUK_DDDPRINT("tzoffset w/o iteration, tzoff=%ld", (long) tzoff));
33563 d -= tzoff * 1000L;
33564 DUK_UNREF(tzoffprev1);
33565 DUK_UNREF(tzoffprev2);
33566#endif
33567
33568 /* Iteration solution */
33569 tzoff = 0;
33570 tzoffprev1 = 999999999L; /* invalid value which never matches */
33571 for (i = 0; i < DUK__LOCAL_TZOFFSET_MAXITER; i++) {
33572 tzoffprev2 = tzoffprev1;
33573 tzoffprev1 = tzoff;
33574 tzoff = DUK_USE_DATE_GET_LOCAL_TZOFFSET(d - tzoff * 1000L);
33575 DUK_DDD(DUK_DDDPRINT("tzoffset iteration, i=%d, tzoff=%ld, tzoffprev1=%ld tzoffprev2=%ld",
33576 (int) i,
33577 (long) tzoff,
33578 (long) tzoffprev1,
33579 (long) tzoffprev2));
33580 if (tzoff == tzoffprev1) {
33581 DUK_DDD(DUK_DDDPRINT("tzoffset iteration finished, i=%d, tzoff=%ld, tzoffprev1=%ld, tzoffprev2=%ld",
33582 (int) i,
33583 (long) tzoff,
33584 (long) tzoffprev1,
33585 (long) tzoffprev2));
33586 break;
33587 } else if (tzoff == tzoffprev2) {
33588 /* Two value cycle, see e.g. test-bi-date-tzoffset-basic-fi.js.
33589 * In these cases, favor a higher tzoffset to get a consistent
33590 * result which is independent of iteration count. Not sure if
33591 * this is a generically correct solution.
33592 */
33594 "tzoffset iteration two-value cycle, i=%d, tzoff=%ld, tzoffprev1=%ld, tzoffprev2=%ld",
33595 (int) i,
33596 (long) tzoff,
33597 (long) tzoffprev1,
33598 (long) tzoffprev2));
33599 if (tzoffprev1 > tzoff) {
33600 tzoff = tzoffprev1;
33601 }
33602 break;
33603 }
33604 }
33605 DUK_DDD(DUK_DDDPRINT("tzoffset iteration, tzoff=%ld", (long) tzoff));
33606 d -= tzoff * 1000L;
33607 }
33608
33609 /* TimeClip(), which also handles Infinity -> NaN conversion */
33610 d = duk__timeclip(d);
33612 return d;
33613}
33614
33615/*
33616 * API oriented helpers
33617 */
33618
33619/* Push 'this' binding, check that it is a Date object; then push the
33620 * internal time value. At the end, stack is: [ ... this timeval ].
33621 * Returns the time value. Local time adjustment is done if requested.
33622 */
33624 duk_hobject *h;
33625 duk_double_t d;
33626 duk_int_t tzoffset = 0;
33627
33628 duk_push_this(thr);
33629 h = duk_get_hobject(thr, -1); /* XXX: getter with class check, useful in built-ins */
33631 DUK_ERROR_TYPE(thr, "expected Date");
33632 DUK_WO_NORETURN(return 0.0;);
33633 }
33634
33636 d = duk_to_number_m1(thr);
33637 duk_pop(thr);
33638
33639 if (DUK_ISNAN(d)) {
33640 if (flags & DUK_DATE_FLAG_NAN_TO_ZERO) {
33641 d = 0.0;
33642 }
33644 DUK_ERROR_RANGE(thr, "Invalid Date");
33645 DUK_WO_NORETURN(return 0.0;);
33646 }
33647 }
33648 /* if no NaN handling flag, may still be NaN here, but not Inf */
33649 DUK_ASSERT(!DUK_ISINF(d));
33650
33651 if (flags & DUK_DATE_FLAG_LOCALTIME) {
33652 /* Note: DST adjustment is determined using UTC time.
33653 * If 'd' is NaN, tzoffset will be 0.
33655 tzoffset = DUK_USE_DATE_GET_LOCAL_TZOFFSET(d); /* seconds */
33656 d += tzoffset * 1000L;
33657 }
33658 if (out_tzoffset) {
33659 *out_tzoffset = tzoffset;
33660 }
33661
33662 /* [ ... this ] */
33663 return d;
33664}
33665
33667 return duk__push_this_get_timeval_tzoffset(thr, flags, NULL);
33668}
33669
33670/* Set timeval to 'this' from dparts, push the new time value onto the
33671 * value stack and return 1 (caller can then tail call us). Expects
33672 * the value stack to contain 'this' on the stack top.
33673 */
33675 duk_double_t d;
33676
33677 /* [ ... this ] */
33678
33679 d = duk_bi_date_get_timeval_from_dparts(dparts, flags);
33680 duk_push_number(thr, d); /* -> [ ... this timeval_new ] */
33681 duk_dup_top(thr); /* -> [ ... this timeval_new timeval_new ] */
33682
33683 /* Must force write because e.g. .setYear() must work even when
33684 * the Date instance is frozen.
33685 */
33687
33688 /* Stack top: new time value, return 1 to allow tail calls. */
33689 return 1;
33690}
33691
33692/* 'out_buf' must be at least DUK_BI_DATE_ISO8601_BUFSIZE long. */
33693DUK_LOCAL void duk__format_parts_iso8601(duk_int_t *parts, duk_int_t tzoffset, duk_small_uint_t flags, duk_uint8_t *out_buf) {
33694 char yearstr[8]; /* "-123456\0" */
33695 char tzstr[8]; /* "+11:22\0" */
33696 char sep = (flags & DUK_DATE_FLAG_SEP_T) ? DUK_ASC_UC_T : DUK_ASC_SPACE;
33697
33698 DUK_ASSERT(parts[DUK_DATE_IDX_MONTH] >= 1 && parts[DUK_DATE_IDX_MONTH] <= 12);
33699 DUK_ASSERT(parts[DUK_DATE_IDX_DAY] >= 1 && parts[DUK_DATE_IDX_DAY] <= 31);
33700 DUK_ASSERT(parts[DUK_DATE_IDX_YEAR] >= -999999 && parts[DUK_DATE_IDX_YEAR] <= 999999);
33701
33702 /* Note: %06d for positive value, %07d for negative value to include
33703 * sign and 6 digits.
33704 */
33705 DUK_SNPRINTF(yearstr,
33706 sizeof(yearstr),
33707 (parts[DUK_DATE_IDX_YEAR] >= 0 && parts[DUK_DATE_IDX_YEAR] <= 9999) ?
33708 "%04ld" :
33709 ((parts[DUK_DATE_IDX_YEAR] >= 0) ? "+%06ld" : "%07ld"),
33710 (long) parts[DUK_DATE_IDX_YEAR]);
33711 yearstr[sizeof(yearstr) - 1] = (char) 0;
33712
33713 if (flags & DUK_DATE_FLAG_LOCALTIME) {
33714 /* tzoffset seconds are dropped; 16 bits suffice for
33715 * time offset in minutes
33716 */
33717 const char *fmt;
33718 duk_small_int_t tmp, arg_hours, arg_minutes;
33719
33720 if (tzoffset >= 0) {
33721 tmp = tzoffset;
33722 fmt = "+%02d:%02d";
33723 } else {
33724 tmp = -tzoffset;
33725 fmt = "-%02d:%02d";
33726 }
33727 tmp = tmp / 60;
33728 arg_hours = tmp / 60;
33729 arg_minutes = tmp % 60;
33730 DUK_ASSERT(arg_hours <= 24); /* Even less is actually guaranteed for a valid tzoffset. */
33731 arg_hours = arg_hours & 0x3f; /* For [0,24] this is a no-op, but fixes GCC 7 warning, see
33732 https://github.com/svaarala/duktape/issues/1602. */
33733
33734 DUK_SNPRINTF(tzstr, sizeof(tzstr), fmt, (int) arg_hours, (int) arg_minutes);
33735 tzstr[sizeof(tzstr) - 1] = (char) 0;
33736 } else {
33737 tzstr[0] = DUK_ASC_UC_Z;
33738 tzstr[1] = (char) 0;
33739 }
33740
33741 /* Unlike year, the other parts fit into 16 bits so %d format
33742 * is portable.
33743 */
33744 if ((flags & DUK_DATE_FLAG_TOSTRING_DATE) && (flags & DUK_DATE_FLAG_TOSTRING_TIME)) {
33745 DUK_SPRINTF((char *) out_buf,
33746 "%s-%02d-%02d%c%02d:%02d:%02d.%03d%s",
33747 (const char *) yearstr,
33748 (int) parts[DUK_DATE_IDX_MONTH],
33749 (int) parts[DUK_DATE_IDX_DAY],
33750 (int) sep,
33751 (int) parts[DUK_DATE_IDX_HOUR],
33752 (int) parts[DUK_DATE_IDX_MINUTE],
33753 (int) parts[DUK_DATE_IDX_SECOND],
33754 (int) parts[DUK_DATE_IDX_MILLISECOND],
33755 (const char *) tzstr);
33756 } else if (flags & DUK_DATE_FLAG_TOSTRING_DATE) {
33757 DUK_SPRINTF((char *) out_buf,
33758 "%s-%02d-%02d",
33759 (const char *) yearstr,
33760 (int) parts[DUK_DATE_IDX_MONTH],
33761 (int) parts[DUK_DATE_IDX_DAY]);
33762 } else {
33764 DUK_SPRINTF((char *) out_buf,
33765 "%02d:%02d:%02d.%03d%s",
33766 (int) parts[DUK_DATE_IDX_HOUR],
33767 (int) parts[DUK_DATE_IDX_MINUTE],
33768 (int) parts[DUK_DATE_IDX_SECOND],
33769 (int) parts[DUK_DATE_IDX_MILLISECOND],
33770 (const char *) tzstr);
33771 }
33772}
33773
33774/* Helper for string conversion calls: check 'this' binding, get the
33775 * internal time value, and format date and/or time in a few formats.
33776 * Return value allows tail calls.
33777 */
33779 duk_double_t d;
33781 duk_int_t tzoffset; /* seconds, doesn't fit into 16 bits */
33782 duk_bool_t rc;
33783 duk_uint8_t buf[DUK_BI_DATE_ISO8601_BUFSIZE];
33784
33785 DUK_UNREF(rc); /* unreferenced with some options */
33786
33787 d = duk__push_this_get_timeval_tzoffset(thr, flags, &tzoffset);
33788 if (DUK_ISNAN(d)) {
33790 return 1;
33791 }
33793
33794 /* formatters always get one-based month/day-of-month */
33796 DUK_ASSERT(parts[DUK_DATE_IDX_MONTH] >= 1 && parts[DUK_DATE_IDX_MONTH] <= 12);
33797 DUK_ASSERT(parts[DUK_DATE_IDX_DAY] >= 1 && parts[DUK_DATE_IDX_DAY] <= 31);
33798
33799 if (flags & DUK_DATE_FLAG_TOSTRING_LOCALE) {
33800 /* try locale specific formatter; if it refuses to format the
33801 * string, fall back to an ISO 8601 formatted value in local
33802 * time.
33803 */
33804#if defined(DUK_USE_DATE_FORMAT_STRING)
33805 /* Contract, either:
33806 * - Push string to value stack and return 1
33807 * - Don't push anything and return 0
33808 */
33809
33810 rc = DUK_USE_DATE_FORMAT_STRING(thr, parts, tzoffset, flags);
33811 if (rc != 0) {
33812 return 1;
33813 }
33814#else
33815 /* No locale specific formatter; this is OK, we fall back
33816 * to ISO 8601.
33817 */
33818#endif
33819 }
33820
33821 /* Different calling convention than above used because the helper
33822 * is shared.
33823 */
33824 duk__format_parts_iso8601(parts, tzoffset, flags, buf);
33825 duk_push_string(thr, (const char *) buf);
33826 return 1;
33827}
33828
33829/* Helper for component getter calls: check 'this' binding, get the
33830 * internal time value, split it into parts (either as UTC time or
33831 * local time), push a specified component as a return value to the
33832 * value stack and return 1 (caller can then tail call us).
33833 */
33835 duk_double_t d;
33837 duk_small_uint_t idx_part = (duk_small_uint_t) (flags_and_idx >> DUK_DATE_FLAG_VALUE_SHIFT); /* unpack args */
33838
33839 DUK_ASSERT_DISABLE(idx_part >= 0); /* unsigned */
33841
33842 d = duk__push_this_get_timeval(thr, flags_and_idx);
33843 if (DUK_ISNAN(d)) {
33844 duk_push_nan(thr);
33845 return 1;
33846 }
33848
33849 duk_bi_date_timeval_to_parts(d, parts, NULL, flags_and_idx); /* no need to mask idx portion */
33850
33851 /* Setter APIs detect special year numbers (0...99) and apply a +1900
33852 * only in certain cases. The legacy getYear() getter applies -1900
33853 * unconditionally.
33855 duk_push_int(thr, (flags_and_idx & DUK_DATE_FLAG_SUB1900) ? parts[idx_part] - 1900 : parts[idx_part]);
33856 return 1;
33857}
33858
33859/* Helper for component setter calls: check 'this' binding, get the
33860 * internal time value, split it into parts (either as UTC time or
33861 * local time), modify one or more components as specified, recompute
33862 * the time value, set it as the internal value. Finally, push the
33863 * new time value as a return value to the value stack and return 1
33864 * (caller can then tail call us).
33865 */
33867 duk_double_t d;
33870 duk_idx_t nargs;
33871 duk_small_uint_t maxnargs = (duk_small_uint_t) (flags_and_maxnargs >> DUK_DATE_FLAG_VALUE_SHIFT); /* unpack args */
33872 duk_small_uint_t idx_first, idx;
33874
33875 nargs = duk_get_top(thr);
33876 d = duk__push_this_get_timeval(thr, flags_and_maxnargs);
33878
33879 if (DUK_ISFINITE(d)) {
33880 duk_bi_date_timeval_to_parts(d, parts, dparts, flags_and_maxnargs);
33881 } else {
33882 /* NaN timevalue: we need to coerce the arguments, but
33883 * the resulting internal timestamp needs to remain NaN.
33884 * This works but is not pretty: parts and dparts will
33885 * be partially uninitialized, but we only write to them.
33886 */
33887 }
33888
33889 /*
33890 * Determining which datetime components to overwrite based on
33891 * stack arguments is a bit complicated, but important to factor
33892 * out from setters themselves for compactness.
33893 *
33894 * If DUK_DATE_FLAG_TIMESETTER, maxnargs indicates setter type:
33895 *
33896 * 1 -> millisecond
33897 * 2 -> second, [millisecond]
33898 * 3 -> minute, [second], [millisecond]
33899 * 4 -> hour, [minute], [second], [millisecond]
33900 *
33901 * Else:
33902 *
33903 * 1 -> date
33904 * 2 -> month, [date]
33905 * 3 -> year, [month], [date]
33906 *
33907 * By comparing nargs and maxnargs (and flags) we know which
33908 * components to override. We rely on part index ordering.
33909 */
33910
33911 if (flags_and_maxnargs & DUK_DATE_FLAG_TIMESETTER) {
33912 DUK_ASSERT(maxnargs >= 1 && maxnargs <= 4);
33913 idx_first = DUK_DATE_IDX_MILLISECOND - (maxnargs - 1);
33914 } else {
33915 DUK_ASSERT(maxnargs >= 1 && maxnargs <= 3);
33916 idx_first = DUK_DATE_IDX_DAY - (maxnargs - 1);
33917 }
33918 DUK_ASSERT_DISABLE(idx_first >= 0); /* unsigned */
33920
33921 for (i = 0; i < maxnargs; i++) {
33922 if ((duk_idx_t) i >= nargs) {
33923 /* no argument given -> leave components untouched */
33924 break;
33925 }
33926 idx = idx_first + i;
33927 DUK_ASSERT_DISABLE(idx >= 0); /* unsigned */
33929
33930 if (idx == DUK_DATE_IDX_YEAR && (flags_and_maxnargs & DUK_DATE_FLAG_YEAR_FIXUP)) {
33932 }
33933
33934 dparts[idx] = duk_to_number(thr, (duk_idx_t) i);
33935
33936 if (idx == DUK_DATE_IDX_DAY) {
33937 /* Day-of-month is one-based in the API, but zero-based
33938 * internally, so fix here. Note that month is zero-based
33939 * both in the API and internally.
33940 */
33941 /* SCANBUILD: complains about use of uninitialized values.
33942 * The complaint is correct, but operating in undefined
33943 * values here is intentional in some cases and the caller
33944 * ignores the results.
33945 */
33946 dparts[idx] -= 1.0;
33947 }
33948 }
33949
33950 /* Leaves new timevalue on stack top and returns 1, which is correct
33951 * for part setters.
33952 */
33954 return duk__set_this_timeval_from_dparts(thr, dparts, flags_and_maxnargs);
33955 } else {
33956 /* Internal timevalue is already NaN, so don't touch it. */
33957 duk_push_nan(thr);
33958 return 1;
33959 }
33960}
33961
33962/* Apply ToNumber() to specified index; if ToInteger(val) in [0,99], add
33963 * 1900 and replace value at idx_val.
33964 */
33966 duk_double_t d;
33967
33968 /* XXX: idx_val would fit into 16 bits, but using duk_small_uint_t
33969 * might not generate better code due to casting.
33970 */
33971
33972 /* E5 Sections 15.9.3.1, B.2.4, B.2.5 */
33973 duk_to_number(thr, idx_val);
33974 if (duk_is_nan(thr, idx_val)) {
33975 return;
33976 }
33977 duk_dup(thr, idx_val);
33978 duk_to_int(thr, -1);
33979 d = duk_get_number(thr, -1); /* get as double to handle huge numbers correctly */
33980 if (d >= 0.0 && d <= 99.0) {
33981 d += 1900.0;
33982 duk_push_number(thr, d);
33983 duk_replace(thr, idx_val);
33984 }
33985 duk_pop(thr);
33986}
33987
33988/* Set datetime parts from stack arguments, defaulting any missing values.
33989 * Day-of-week is not set; it is not required when setting the time value.
33990 */
33992 duk_double_t d;
33994 duk_small_uint_t idx;
33995
33996 /* Causes a ToNumber() coercion, but doesn't break coercion order since
33997 * year is coerced first anyway.
33998 */
34000
34001 /* There are at most 7 args, but we use 8 here so that also
34002 * DUK_DATE_IDX_WEEKDAY gets initialized (to zero) to avoid the potential
34003 * for any Valgrind gripes later.
34004 */
34005 for (i = 0; i < 8; i++) {
34006 /* Note: rely on index ordering */
34007 idx = DUK_DATE_IDX_YEAR + i;
34008 if ((duk_idx_t) i < nargs) {
34009 d = duk_to_number(thr, (duk_idx_t) i);
34010 if (idx == DUK_DATE_IDX_DAY) {
34011 /* Convert day from one-based to zero-based (internal). This may
34012 * cause the day part to be negative, which is OK.
34013 */
34014 d -= 1.0;
34015 }
34016 } else {
34017 /* All components default to 0 except day-of-month which defaults
34018 * to 1. However, because our internal day-of-month is zero-based,
34019 * it also defaults to zero here.
34020 */
34021 d = 0.0;
34022 }
34023 dparts[idx] = d;
34024 }
34025
34026 DUK_DDD(DUK_DDDPRINT("parts from args -> %lf %lf %lf %lf %lf %lf %lf %lf",
34027 (double) dparts[0],
34028 (double) dparts[1],
34029 (double) dparts[2],
34030 (double) dparts[3],
34031 (double) dparts[4],
34032 (double) dparts[5],
34033 (double) dparts[6],
34034 (double) dparts[7]));
34035}
34037/*
34038 * Indirect magic value lookup for Date methods.
34039 *
34040 * Date methods don't put their control flags into the function magic value
34041 * because they wouldn't fit into a LIGHTFUNC's magic field. Instead, the
34042 * magic value is set to an index pointing to the array of control flags
34043 * below.
34044 *
34045 * This must be kept in strict sync with genbuiltins.py!
34046 */
34047
34048static duk_uint16_t duk__date_magics[] = {
34049 /* 0: toString */
34051
34052 /* 1: toDateString */
34054
34055 /* 2: toTimeString */
34057
34058 /* 3: toLocaleString */
34060
34061 /* 4: toLocaleDateString */
34063
34064 /* 5: toLocaleTimeString */
34066
34067 /* 6: toUTCString */
34069
34070 /* 7: toISOString */
34072
34073 /* 8: getFullYear */
34075
34076 /* 9: getUTCFullYear */
34078
34079 /* 10: getMonth */
34081
34082 /* 11: getUTCMonth */
34084
34085 /* 12: getDate */
34087
34088 /* 13: getUTCDate */
34090
34091 /* 14: getDay */
34093
34094 /* 15: getUTCDay */
34096
34097 /* 16: getHours */
34099
34100 /* 17: getUTCHours */
34102
34103 /* 18: getMinutes */
34105
34106 /* 19: getUTCMinutes */
34108
34109 /* 20: getSeconds */
34111
34112 /* 21: getUTCSeconds */
34114
34115 /* 22: getMilliseconds */
34117
34118 /* 23: getUTCMilliseconds */
34120
34121 /* 24: setMilliseconds */
34123
34124 /* 25: setUTCMilliseconds */
34126
34127 /* 26: setSeconds */
34129
34130 /* 27: setUTCSeconds */
34132
34133 /* 28: setMinutes */
34135
34136 /* 29: setUTCMinutes */
34138
34139 /* 30: setHours */
34141
34142 /* 31: setUTCHours */
34144
34145 /* 32: setDate */
34147
34148 /* 33: setUTCDate */
34149 0 + (1 << DUK_DATE_FLAG_VALUE_SHIFT),
34150
34151 /* 34: setMonth */
34153
34154 /* 35: setUTCMonth */
34155 0 + (2 << DUK_DATE_FLAG_VALUE_SHIFT),
34156
34157 /* 36: setFullYear */
34159
34160 /* 37: setUTCFullYear */
34162
34163 /* 38: getYear */
34165
34166 /* 39: setYear */
34168};
34172 DUK_ASSERT(magicidx < (duk_small_int_t) (sizeof(duk__date_magics) / sizeof(duk_uint16_t)));
34173 return (duk_small_uint_t) duk__date_magics[magicidx];
34174}
34175
34176#if defined(DUK_USE_DATE_BUILTIN)
34177/*
34178 * Constructor calls
34179 */
34180
34182 duk_idx_t nargs = duk_get_top(thr);
34183 duk_bool_t is_cons = duk_is_constructor_call(thr);
34185 duk_double_t d;
34186
34187 DUK_DDD(DUK_DDDPRINT("Date constructor, nargs=%ld, is_cons=%ld", (long) nargs, (long) is_cons));
34188
34189 (void) duk_push_object_helper(thr,
34193
34194 /* Unlike most built-ins, the internal [[PrimitiveValue]] of a Date
34195 * is mutable.
34196 */
34197
34198 if (nargs == 0 || !is_cons) {
34200 duk_push_number(thr, d);
34202 if (!is_cons) {
34203 /* called as a normal function: return new Date().toString() */
34204 duk_to_string(thr, -1);
34205 }
34206 return 1;
34207 } else if (nargs == 1) {
34208 const char *str;
34210 str = duk_get_string_notsymbol(thr, 0);
34211 if (str) {
34212 duk__parse_string(thr, str);
34213 duk_replace(thr, 0); /* may be NaN */
34214 }
34215 d = duk__timeclip(duk_to_number(thr, 0)); /* symbols fail here */
34216 duk_push_number(thr, d);
34218 return 1;
34219 }
34220
34221 duk__set_parts_from_args(thr, dparts, nargs);
34223 /* Parts are in local time, convert when setting. */
34224
34225 (void) duk__set_this_timeval_from_dparts(thr, dparts, DUK_DATE_FLAG_LOCALTIME /*flags*/); /* -> [ ... this timeval ] */
34226 duk_pop(thr); /* -> [ ... this ] */
34227 return 1;
34228}
34229
34231 return duk__parse_string(thr, duk_to_string(thr, 0));
34232}
34233
34235 duk_idx_t nargs = duk_get_top(thr);
34237 duk_double_t d;
34238
34239 /* Behavior for nargs < 2 is implementation dependent: currently we'll
34240 * set a NaN time value (matching V8 behavior) in this case.
34242
34243 if (nargs < 2) {
34244 duk_push_nan(thr);
34245 } else {
34246 duk__set_parts_from_args(thr, dparts, nargs);
34247 d = duk_bi_date_get_timeval_from_dparts(dparts, 0 /*flags*/);
34248 duk_push_number(thr, d);
34249 }
34250 return 1;
34251}
34252
34254 duk_double_t d;
34255
34257 DUK_ASSERT(duk_double_equals(duk__timeclip(d), d)); /* TimeClip() should never be necessary */
34258 duk_push_number(thr, d);
34259 return 1;
34260}
34261
34262/*
34263 * String/JSON conversions
34264 *
34265 * Human readable conversions are now basically ISO 8601 with a space
34266 * (instead of 'T') as the date/time separator. This is a good baseline
34267 * and is platform independent.
34268 *
34269 * A shared native helper to provide many conversions. Magic value contains
34270 * a set of flags. The helper provides:
34271 *
34272 * toString()
34273 * toDateString()
34274 * toTimeString()
34275 * toLocaleString()
34276 * toLocaleDateString()
34277 * toLocaleTimeString()
34278 * toUTCString()
34279 * toISOString()
34280 *
34281 * Notes:
34282 *
34283 * - Date.prototype.toGMTString() and Date.prototype.toUTCString() are
34284 * required to be the same ECMAScript function object (!), so it is
34285 * omitted from here.
34286 *
34287 * - Date.prototype.toUTCString(): E5.1 specification does not require a
34288 * specific format, but result should be human readable. The
34289 * specification suggests using ISO 8601 format with a space (instead
34290 * of 'T') separator if a more human readable format is not available.
34291 *
34292 * - Date.prototype.toISOString(): unlike other conversion functions,
34293 * toISOString() requires a RangeError for invalid date values.
34294 */
34295
34298 return duk__to_string_helper(thr, flags);
34299}
34302 /* This native function is also used for Date.prototype.getTime()
34303 * as their behavior is identical.
34304 */
34305
34306 duk_double_t d = duk__push_this_get_timeval(thr, 0 /*flags*/); /* -> [ this ] */
34308 duk_push_number(thr, d);
34309 return 1;
34310}
34311
34313 /* Note: toJSON() is a generic function which works even if 'this'
34314 * is not a Date. The sole argument is ignored.
34315 */
34316
34317 duk_push_this(thr);
34318 duk_to_object(thr, -1);
34319
34320 duk_dup_top(thr);
34322 if (duk_is_number(thr, -1)) {
34323 duk_double_t d = duk_get_number(thr, -1);
34324 if (!DUK_ISFINITE(d)) {
34325 duk_push_null(thr);
34326 return 1;
34327 }
34328 }
34329 duk_pop(thr);
34330
34332 duk_dup_m2(thr); /* -> [ O toIsoString O ] */
34333 duk_call_method(thr, 0);
34334 return 1;
34335}
34336
34337/*
34338 * Getters.
34339 *
34340 * Implementing getters is quite easy. The internal time value is either
34341 * NaN, or represents milliseconds (without fractions) from Jan 1, 1970.
34342 * The internal time value can be converted to integer parts, and each
34343 * part will be normalized and will fit into a 32-bit signed integer.
34344 *
34345 * A shared native helper to provide all getters. Magic value contains
34346 * a set of flags and also packs the date component index argument. The
34347 * helper provides:
34348 *
34349 * getFullYear()
34350 * getUTCFullYear()
34351 * getMonth()
34352 * getUTCMonth()
34353 * getDate()
34354 * getUTCDate()
34355 * getDay()
34356 * getUTCDay()
34357 * getHours()
34358 * getUTCHours()
34359 * getMinutes()
34360 * getUTCMinutes()
34361 * getSeconds()
34362 * getUTCSeconds()
34363 * getMilliseconds()
34364 * getUTCMilliseconds()
34365 * getYear()
34367 * Notes:
34368 *
34369 * - Date.prototype.getDate(): 'date' means day-of-month, and is
34370 * zero-based in internal calculations but public API expects it to
34371 * be one-based.
34372 *
34373 * - Date.prototype.getTime() and Date.prototype.valueOf() have identical
34374 * behavior. They have separate function objects, but share the same C
34375 * function (duk_bi_date_prototype_value_of).
34376 */
34377
34380 return duk__get_part_helper(thr, flags_and_idx);
34381}
34382
34384 /*
34385 * Return (t - LocalTime(t)) in minutes:
34386 *
34387 * t - LocalTime(t) = t - (t + LocalTZA + DaylightSavingTA(t))
34388 * = -(LocalTZA + DaylightSavingTA(t))
34389 *
34390 * where DaylightSavingTA() is checked for time 't'.
34391 *
34392 * Note that the sign of the result is opposite to common usage,
34393 * e.g. for EE(S)T which normally is +2h or +3h from UTC, this
34394 * function returns -120 or -180.
34395 *
34396 */
34397
34398 duk_double_t d;
34399 duk_int_t tzoffset;
34400
34401 /* Note: DST adjustment is determined using UTC time. */
34402 d = duk__push_this_get_timeval(thr, 0 /*flags*/);
34404 if (DUK_ISNAN(d)) {
34405 duk_push_nan(thr);
34406 } else {
34408 tzoffset = DUK_USE_DATE_GET_LOCAL_TZOFFSET(d);
34409 duk_push_int(thr, -tzoffset / 60);
34410 }
34411 return 1;
34412}
34413
34414/*
34415 * Setters.
34416 *
34417 * Setters are a bit more complicated than getters. Component setters
34418 * break down the current time value into its (normalized) component
34419 * parts, replace one or more components with -unnormalized- new values,
34420 * and the components are then converted back into a time value. As an
34421 * example of using unnormalized values:
34422 *
34423 * var d = new Date(1234567890);
34424 *
34425 * is equivalent to:
34426 *
34427 * var d = new Date(0);
34428 * d.setUTCMilliseconds(1234567890);
34429 *
34430 * A shared native helper to provide almost all setters. Magic value
34431 * contains a set of flags and also packs the "maxnargs" argument. The
34432 * helper provides:
34433 *
34434 * setMilliseconds()
34435 * setUTCMilliseconds()
34436 * setSeconds()
34437 * setUTCSeconds()
34438 * setMinutes()
34439 * setUTCMinutes()
34440 * setHours()
34441 * setUTCHours()
34442 * setDate()
34443 * setUTCDate()
34444 * setMonth()
34445 * setUTCMonth()
34446 * setFullYear()
34447 * setUTCFullYear()
34448 * setYear()
34449 *
34450 * Notes:
34452 * - Date.prototype.setYear() (Section B addition): special year check
34453 * is omitted. NaN / Infinity will just flow through and ultimately
34454 * result in a NaN internal time value.
34455 *
34456 * - Date.prototype.setYear() does not have optional arguments for
34457 * setting month and day-in-month (like setFullYear()), but we indicate
34458 * 'maxnargs' to be 3 to get the year written to the correct component
34459 * index in duk__set_part_helper(). The function has nargs == 1, so only
34460 * the year will be set regardless of actual argument count.
34461 */
34462
34464 duk_small_uint_t flags_and_maxnargs = duk__date_get_indirect_magic(thr);
34465 return duk__set_part_helper(thr, flags_and_maxnargs);
34466}
34467
34469 duk_double_t d;
34470
34471 (void) duk__push_this_get_timeval(thr, 0 /*flags*/); /* -> [ timeval this ] */
34472 d = duk__timeclip(duk_to_number(thr, 0));
34473 duk_push_number(thr, d);
34474 duk_dup_top(thr);
34475 /* Must force write because .setTime() must work even when
34476 * the Date instance is frozen.
34479 /* -> [ timeval this timeval ] */
34480
34481 return 1;
34482}
34483
34484/*
34485 * Misc.
34486 */
34487
34488#if defined(DUK_USE_SYMBOL_BUILTIN)
34490 duk_size_t hintlen;
34491 const char *hintstr;
34492 duk_int_t hint;
34493
34494 /* Invokes OrdinaryToPrimitive() with suitable hint. Note that the
34495 * method is generic, and works on non-Date arguments too.
34496 *
34497 * https://www.ecma-international.org/ecma-262/6.0/#sec-date.prototype-@@toprimitive
34498 */
34499
34500 duk_push_this(thr);
34501 duk_require_object(thr, -1);
34502 DUK_ASSERT_TOP(thr, 2);
34503
34504 hintstr = duk_require_lstring(thr, 0, &hintlen);
34505 if ((hintlen == 6 && DUK_STRCMP(hintstr, "string") == 0) || (hintlen == 7 && DUK_STRCMP(hintstr, "default") == 0)) {
34506 hint = DUK_HINT_STRING;
34507 } else if (hintlen == 6 && DUK_STRCMP(hintstr, "number") == 0) {
34508 hint = DUK_HINT_NUMBER;
34509 } else {
34511 }
34512
34513 duk_to_primitive_ordinary(thr, -1, hint);
34514 return 1;
34515}
34516#endif /* DUK_USE_SYMBOL_BUILTIN */
34517
34518#endif /* DUK_USE_DATE_BUILTIN */
34519
34520/* automatic undefs */
34521#undef DUK__CF_ACCEPT
34522#undef DUK__CF_ACCEPT_NUL
34523#undef DUK__CF_NEG
34524#undef DUK__DPRINT_DPARTS
34525#undef DUK__DPRINT_PARTS
34526#undef DUK__DPRINT_PARTS_AND_DPARTS
34527#undef DUK__LOCAL_TZOFFSET_MAXITER
34528#undef DUK__NUM_ISO8601_PARSER_PARTS
34529#undef DUK__PACK_RULE
34530#undef DUK__PI_DAY
34531#undef DUK__PI_HOUR
34532#undef DUK__PI_MILLISECOND
34533#undef DUK__PI_MINUTE
34534#undef DUK__PI_MONTH
34535#undef DUK__PI_SECOND
34536#undef DUK__PI_TZHOUR
34537#undef DUK__PI_TZMINUTE
34538#undef DUK__PI_YEAR
34539#undef DUK__PM_DAY
34540#undef DUK__PM_HOUR
34541#undef DUK__PM_MILLISECOND
34542#undef DUK__PM_MINUTE
34543#undef DUK__PM_MONTH
34544#undef DUK__PM_SECOND
34545#undef DUK__PM_TZHOUR
34546#undef DUK__PM_TZMINUTE
34547#undef DUK__PM_YEAR
34548#undef DUK__RULE_MASK_PART_SEP
34549#undef DUK__SI_COLON
34550#undef DUK__SI_MINUS
34551#undef DUK__SI_NUL
34552#undef DUK__SI_PERIOD
34553#undef DUK__SI_PLUS
34554#undef DUK__SI_SPACE
34555#undef DUK__SI_T
34556#undef DUK__SI_Z
34557#undef DUK__SM_COLON
34558#undef DUK__SM_MINUS
34559#undef DUK__SM_NUL
34560#undef DUK__SM_PERIOD
34561#undef DUK__SM_PLUS
34562#undef DUK__SM_SPACE
34563#undef DUK__SM_T
34564#undef DUK__SM_Z
34565#undef DUK__UNPACK_RULE
34566#undef DUK__WEEKDAY_MOD_ADDER
34567#undef DUK__YEAR
34568/*
34569 * Unix-like Date providers
34571 * Generally useful Unix / POSIX / ANSI Date providers.
34572 */
34573
34574/* #include duk_internal.h -> already included */
34575
34576/* The necessary #includes are in place in duk_config.h. */
34577
34578/* Buffer sizes for some UNIX calls. Larger than strictly necessary
34579 * to avoid Valgrind errors.
34580 */
34581#define DUK__STRPTIME_BUF_SIZE 64
34582#define DUK__STRFTIME_BUF_SIZE 64
34583
34584#if defined(DUK_USE_DATE_NOW_GETTIMEOFDAY)
34585/* Get current ECMAScript time (= UNIX/Posix time, but in milliseconds). */
34586DUK_INTERNAL duk_double_t duk_bi_date_get_now_gettimeofday(void) {
34587 struct timeval tv;
34588 duk_double_t d;
34589
34590 if (gettimeofday(&tv, NULL) != 0) {
34591 DUK_D(DUK_DPRINT("gettimeofday() failed"));
34592 return 0.0;
34593 }
34594
34595 /* As of Duktape 2.2.0 allow fractions. */
34596 d = ((duk_double_t) tv.tv_sec) * 1000.0 + ((duk_double_t) tv.tv_usec) / 1000.0;
34597
34598 return d;
34599}
34600#endif /* DUK_USE_DATE_NOW_GETTIMEOFDAY */
34601
34602#if defined(DUK_USE_DATE_NOW_TIME)
34603/* Not a very good provider: only full seconds are available. */
34605 time_t t;
34607 t = time(NULL);
34608 if (t == (time_t) -1) {
34609 DUK_D(DUK_DPRINT("time() failed"));
34610 return 0.0;
34611 }
34612 return ((duk_double_t) t) * 1000.0;
34613}
34614#endif /* DUK_USE_DATE_NOW_TIME */
34615
34616#if defined(DUK_USE_DATE_TZO_GMTIME) || defined(DUK_USE_DATE_TZO_GMTIME_R) || defined(DUK_USE_DATE_TZO_GMTIME_S)
34617/* Get local time offset (in seconds) for a certain (UTC) instant 'd'. */
34619 time_t t, t1, t2;
34622 struct tm tms[2];
34623#if defined(DUK_USE_DATE_TZO_GMTIME)
34624 struct tm *tm_ptr;
34625#endif
34626
34627 /* For NaN/inf, the return value doesn't matter. */
34628 if (!DUK_ISFINITE(d)) {
34629 return 0;
34630 }
34631
34632 /* If not within ECMAScript range, some integer time calculations
34633 * won't work correctly (and some asserts will fail), so bail out
34634 * if so. This fixes test-bug-date-insane-setyear.js. There is
34635 * a +/- 24h leeway in this range check to avoid a test262 corner
34636 * case documented in test-bug-date-timeval-edges.js.
34637 */
34639 DUK_DD(DUK_DDPRINT("timeval not within valid range, skip tzoffset computation to avoid integer overflows"));
34640 return 0;
34641 }
34642
34643 /*
34644 * This is a bit tricky to implement portably. The result depends
34645 * on the timestamp (specifically, DST depends on the timestamp).
34646 * If e.g. UNIX APIs are used, they'll have portability issues with
34647 * very small and very large years.
34648 *
34649 * Current approach:
34650 *
34651 * - Stay within portable UNIX limits by using equivalent year mapping.
34652 * Avoid year 1970 and 2038 as some conversions start to fail, at
34653 * least on some platforms. Avoiding 1970 means that there are
34654 * currently DST discrepancies for 1970.
34655 *
34656 * - Create a UTC and local time breakdowns from 't'. Then create
34657 * a time_t using gmtime() and localtime() and compute the time
34658 * difference between the two.
34659 *
34660 * Equivalent year mapping (E5 Section 15.9.1.8):
34661 *
34662 * If the host environment provides functionality for determining
34663 * daylight saving time, the implementation of ECMAScript is free
34664 * to map the year in question to an equivalent year (same
34665 * leap-year-ness and same starting week day for the year) for which
34666 * the host environment provides daylight saving time information.
34667 * The only restriction is that all equivalent years should produce
34668 * the same result.
34669 *
34670 * This approach is quite reasonable but not entirely correct, e.g.
34671 * the specification also states (E5 Section 15.9.1.8):
34672 *
34673 * The implementation of ECMAScript should not try to determine
34674 * whether the exact time was subject to daylight saving time, but
34675 * just whether daylight saving time would have been in effect if
34676 * the _current daylight saving time algorithm_ had been used at the
34677 * time. This avoids complications such as taking into account the
34678 * years that the locale observed daylight saving time year round.
34679 *
34680 * Since we rely on the platform APIs for conversions between local
34681 * time and UTC, we can't guarantee the above. Rather, if the platform
34682 * has historical DST rules they will be applied. This seems to be the
34683 * general preferred direction in ECMAScript standardization (or at least
34684 * implementations) anyway, and even the equivalent year mapping should
34685 * be disabled if the platform is known to handle DST properly for the
34686 * full ECMAScript range.
34687 *
34688 * The following has useful discussion and links:
34689 *
34690 * https://bugzilla.mozilla.org/show_bug.cgi?id=351066
34691 */
34692
34693 duk_bi_date_timeval_to_parts(d, parts, dparts, DUK_DATE_FLAG_EQUIVYEAR /*flags*/);
34694 DUK_ASSERT(parts[DUK_DATE_IDX_YEAR] >= 1970 && parts[DUK_DATE_IDX_YEAR] <= 2038);
34695
34696 d = duk_bi_date_get_timeval_from_dparts(dparts, 0 /*flags*/);
34697 DUK_ASSERT(d >= 0 && d < 2147483648.0 * 1000.0); /* unsigned 31-bit range */
34698 t = (time_t) (d / 1000.0);
34699 DUK_DDD(DUK_DDDPRINT("timeval: %lf -> time_t %ld", (double) d, (long) t));
34700
34701 duk_memzero((void *) tms, sizeof(struct tm) * 2);
34702
34703#if defined(DUK_USE_DATE_TZO_GMTIME_R)
34704 (void) gmtime_r(&t, &tms[0]);
34705 (void) localtime_r(&t, &tms[1]);
34706#elif defined(DUK_USE_DATE_TZO_GMTIME_S)
34707 (void) gmtime_s(&t, &tms[0]);
34708 (void) localtime_s(&t, &tms[1]);
34709#elif defined(DUK_USE_DATE_TZO_GMTIME)
34710 tm_ptr = gmtime(&t);
34711 duk_memcpy((void *) &tms[0], tm_ptr, sizeof(struct tm));
34712 tm_ptr = localtime(&t);
34713 duk_memcpy((void *) &tms[1], tm_ptr, sizeof(struct tm));
34714#else
34715#error internal error
34716#endif
34717 DUK_DDD(DUK_DDDPRINT("gmtime result: tm={sec:%ld,min:%ld,hour:%ld,mday:%ld,mon:%ld,year:%ld,"
34718 "wday:%ld,yday:%ld,isdst:%ld}",
34719 (long) tms[0].tm_sec,
34720 (long) tms[0].tm_min,
34721 (long) tms[0].tm_hour,
34722 (long) tms[0].tm_mday,
34723 (long) tms[0].tm_mon,
34724 (long) tms[0].tm_year,
34725 (long) tms[0].tm_wday,
34726 (long) tms[0].tm_yday,
34727 (long) tms[0].tm_isdst));
34728 DUK_DDD(DUK_DDDPRINT("localtime result: tm={sec:%ld,min:%ld,hour:%ld,mday:%ld,mon:%ld,year:%ld,"
34729 "wday:%ld,yday:%ld,isdst:%ld}",
34730 (long) tms[1].tm_sec,
34731 (long) tms[1].tm_min,
34732 (long) tms[1].tm_hour,
34733 (long) tms[1].tm_mday,
34734 (long) tms[1].tm_mon,
34735 (long) tms[1].tm_year,
34736 (long) tms[1].tm_wday,
34737 (long) tms[1].tm_yday,
34738 (long) tms[1].tm_isdst));
34739
34740 /* tm_isdst is both an input and an output to mktime(), use 0 to
34741 * avoid DST handling in mktime():
34742 * - https://github.com/svaarala/duktape/issues/406
34743 * - http://stackoverflow.com/questions/8558919/mktime-and-tm-isdst
34744 */
34745 tms[0].tm_isdst = 0;
34746 tms[1].tm_isdst = 0;
34747 t1 = mktime(&tms[0]); /* UTC */
34748 t2 = mktime(&tms[1]); /* local */
34749 if (t1 == (time_t) -1 || t2 == (time_t) -1) {
34750 /* This check used to be for (t < 0) but on some platforms
34751 * time_t is unsigned and apparently the proper way to detect
34752 * an mktime() error return is the cast above. See e.g.:
34753 * http://pubs.opengroup.org/onlinepubs/009695299/functions/mktime.html
34754 */
34755 goto mktime_error;
34756 }
34757 DUK_DDD(DUK_DDDPRINT("t1=%ld (utc), t2=%ld (local)", (long) t1, (long) t2));
34758
34759 /* Compute final offset in seconds, positive if local time ahead of
34760 * UTC (returned value is UTC-to-local offset).
34761 *
34762 * difftime() returns a double, so coercion to int generates quite
34763 * a lot of code. Direct subtraction is not portable, however.
34764 * XXX: allow direct subtraction on known platforms.
34765 */
34766#if 0
34767 return (duk_int_t) (t2 - t1);
34768#endif
34769 return (duk_int_t) difftime(t2, t1);
34770
34771mktime_error:
34772 /* XXX: return something more useful, so that caller can throw? */
34773 DUK_D(DUK_DPRINT("mktime() failed, d=%lf", (double) d));
34774 return 0;
34775}
34776#endif /* DUK_USE_DATE_TZO_GMTIME */
34777
34778#if defined(DUK_USE_DATE_PRS_STRPTIME)
34779DUK_INTERNAL duk_bool_t duk_bi_date_parse_string_strptime(duk_hthread *thr, const char *str) {
34780 struct tm tm;
34781 time_t t;
34782 char buf[DUK__STRPTIME_BUF_SIZE];
34783
34784 /* Copy to buffer with slack to avoid Valgrind gripes from strptime. */
34785 DUK_ASSERT(str != NULL);
34786 duk_memzero(buf, sizeof(buf)); /* valgrind whine without this */
34787 DUK_SNPRINTF(buf, sizeof(buf), "%s", (const char *) str);
34788 buf[sizeof(buf) - 1] = (char) 0;
34789
34790 DUK_DDD(DUK_DDDPRINT("parsing: '%s'", (const char *) buf));
34791
34792 duk_memzero(&tm, sizeof(tm));
34793 if (strptime((const char *) buf, "%c", &tm) != NULL) {
34794 DUK_DDD(DUK_DDDPRINT("before mktime: tm={sec:%ld,min:%ld,hour:%ld,mday:%ld,mon:%ld,year:%ld,"
34795 "wday:%ld,yday:%ld,isdst:%ld}",
34796 (long) tm.tm_sec,
34797 (long) tm.tm_min,
34798 (long) tm.tm_hour,
34799 (long) tm.tm_mday,
34800 (long) tm.tm_mon,
34801 (long) tm.tm_year,
34802 (long) tm.tm_wday,
34803 (long) tm.tm_yday,
34804 (long) tm.tm_isdst));
34805 tm.tm_isdst = -1; /* negative: dst info not available */
34806
34807 t = mktime(&tm);
34808 DUK_DDD(DUK_DDDPRINT("mktime() -> %ld", (long) t));
34809 if (t >= 0) {
34810 duk_push_number(thr, ((duk_double_t) t) * 1000.0);
34811 return 1;
34812 }
34813 }
34814
34815 return 0;
34816}
34817#endif /* DUK_USE_DATE_PRS_STRPTIME */
34818
34819#if defined(DUK_USE_DATE_PRS_GETDATE)
34820DUK_INTERNAL duk_bool_t duk_bi_date_parse_string_getdate(duk_hthread *thr, const char *str) {
34821 struct tm tm;
34822 duk_small_int_t rc;
34823 time_t t;
34824
34825 /* For this to work, DATEMSK must be set, so this is not very
34826 * convenient for an embeddable interpreter.
34827 */
34828
34829 duk_memzero(&tm, sizeof(struct tm));
34830 rc = (duk_small_int_t) getdate_r(str, &tm);
34831 DUK_DDD(DUK_DDDPRINT("getdate_r() -> %ld", (long) rc));
34832
34833 if (rc == 0) {
34834 t = mktime(&tm);
34835 DUK_DDD(DUK_DDDPRINT("mktime() -> %ld", (long) t));
34836 if (t >= 0) {
34837 duk_push_number(thr, (duk_double_t) t);
34838 return 1;
34839 }
34840 }
34841
34842 return 0;
34843}
34844#endif /* DUK_USE_DATE_PRS_GETDATE */
34845
34846#if defined(DUK_USE_DATE_FMT_STRFTIME)
34847DUK_INTERNAL duk_bool_t duk_bi_date_format_parts_strftime(duk_hthread *thr,
34848 duk_int_t *parts,
34849 duk_int_t tzoffset,
34850 duk_small_uint_t flags) {
34851 char buf[DUK__STRFTIME_BUF_SIZE];
34852 struct tm tm;
34853 const char *fmt;
34854
34855 DUK_UNREF(tzoffset);
34856
34857 /* If the platform doesn't support the entire ECMAScript range, we need
34858 * to return 0 so that the caller can fall back to the default formatter.
34859 *
34860 * For now, assume that if time_t is 8 bytes or more, the whole ECMAScript
34861 * range is supported. For smaller time_t values (4 bytes in practice),
34862 * assumes that the signed 32-bit range is supported.
34863 *
34864 * XXX: detect this more correctly per platform. The size of time_t is
34865 * probably not an accurate guarantee of strftime() supporting or not
34866 * supporting a large time range (the full ECMAScript range).
34867 */
34868 if (sizeof(time_t) < 8 && (parts[DUK_DATE_IDX_YEAR] < 1970 || parts[DUK_DATE_IDX_YEAR] > 2037)) {
34869 /* be paranoid for 32-bit time values (even avoiding negative ones) */
34870 return 0;
34871 }
34872
34873 duk_memzero(&tm, sizeof(tm));
34874 tm.tm_sec = parts[DUK_DATE_IDX_SECOND];
34875 tm.tm_min = parts[DUK_DATE_IDX_MINUTE];
34876 tm.tm_hour = parts[DUK_DATE_IDX_HOUR];
34877 tm.tm_mday = parts[DUK_DATE_IDX_DAY]; /* already one-based */
34878 tm.tm_mon = parts[DUK_DATE_IDX_MONTH] - 1; /* one-based -> zero-based */
34879 tm.tm_year = parts[DUK_DATE_IDX_YEAR] - 1900;
34880 tm.tm_wday = parts[DUK_DATE_IDX_WEEKDAY];
34881 tm.tm_isdst = 0;
34882
34883 duk_memzero(buf, sizeof(buf));
34884 if ((flags & DUK_DATE_FLAG_TOSTRING_DATE) && (flags & DUK_DATE_FLAG_TOSTRING_TIME)) {
34885 fmt = "%c";
34886 } else if (flags & DUK_DATE_FLAG_TOSTRING_DATE) {
34887 fmt = "%x";
34888 } else {
34890 fmt = "%X";
34891 }
34892 (void) strftime(buf, sizeof(buf) - 1, fmt, &tm);
34893 DUK_ASSERT(buf[sizeof(buf) - 1] == 0);
34894
34895 duk_push_string(thr, buf);
34896 return 1;
34897}
34898#endif /* DUK_USE_DATE_FMT_STRFTIME */
34899
34900#if defined(DUK_USE_GET_MONOTONIC_TIME_CLOCK_GETTIME)
34901DUK_INTERNAL duk_double_t duk_bi_date_get_monotonic_time_clock_gettime(void) {
34902 struct timespec ts;
34903
34904 if (clock_gettime(CLOCK_MONOTONIC, &ts) == 0) {
34905 return (duk_double_t) ts.tv_sec * 1000.0 + (duk_double_t) ts.tv_nsec / 1000000.0;
34906 } else {
34907 DUK_D(DUK_DPRINT("clock_gettime(CLOCK_MONOTONIC) failed"));
34908 return 0.0;
34909 }
34910}
34911#endif
34912
34913/* automatic undefs */
34914#undef DUK__STRFTIME_BUF_SIZE
34915#undef DUK__STRPTIME_BUF_SIZE
34916/*
34917 * Windows Date providers
34918 *
34919 * Platform specific links:
34920 *
34921 * - http://msdn.microsoft.com/en-us/library/windows/desktop/ms725473(v=vs.85).aspx
34922 */
34923
34924/* #include duk_internal.h -> already included */
34925
34926/* The necessary #includes are in place in duk_config.h. */
34927
34928#if defined(DUK_USE_DATE_NOW_WINDOWS) || defined(DUK_USE_DATE_TZO_WINDOWS)
34929/* Shared Windows helpers. */
34930DUK_LOCAL void duk__convert_systime_to_ularge(const SYSTEMTIME *st, ULARGE_INTEGER *res) {
34931 FILETIME ft;
34932 if (SystemTimeToFileTime(st, &ft) == 0) {
34933 DUK_D(DUK_DPRINT("SystemTimeToFileTime() failed, returning 0"));
34934 res->QuadPart = 0;
34935 } else {
34936 res->LowPart = ft.dwLowDateTime;
34937 res->HighPart = ft.dwHighDateTime;
34938 }
34939}
34940
34941#if defined(DUK_USE_DATE_NOW_WINDOWS_SUBMS)
34942DUK_LOCAL void duk__convert_filetime_to_ularge(const FILETIME *ft, ULARGE_INTEGER *res) {
34943 res->LowPart = ft->dwLowDateTime;
34944 res->HighPart = ft->dwHighDateTime;
34945}
34946#endif /* DUK_USE_DATE_NOW_WINDOWS_SUBMS */
34947
34948DUK_LOCAL void duk__set_systime_jan1970(SYSTEMTIME *st) {
34949 duk_memzero((void *) st, sizeof(*st));
34950 st->wYear = 1970;
34951 st->wMonth = 1;
34952 st->wDayOfWeek = 4; /* not sure whether or not needed; Thursday */
34953 st->wDay = 1;
34954 DUK_ASSERT(st->wHour == 0);
34955 DUK_ASSERT(st->wMinute == 0);
34956 DUK_ASSERT(st->wSecond == 0);
34957 DUK_ASSERT(st->wMilliseconds == 0);
34958}
34959#endif /* defined(DUK_USE_DATE_NOW_WINDOWS) || defined(DUK_USE_DATE_TZO_WINDOWS) */
34960
34961#if defined(DUK_USE_DATE_NOW_WINDOWS)
34962DUK_INTERNAL duk_double_t duk_bi_date_get_now_windows(void) {
34963 /* Suggested step-by-step method from documentation of RtlTimeToSecondsSince1970:
34964 * http://msdn.microsoft.com/en-us/library/windows/desktop/ms724928(v=vs.85).aspx
34965 */
34966 SYSTEMTIME st1, st2;
34967 ULARGE_INTEGER tmp1, tmp2;
34968
34969 GetSystemTime(&st1);
34970 duk__convert_systime_to_ularge((const SYSTEMTIME *) &st1, &tmp1);
34971
34972 duk__set_systime_jan1970(&st2);
34973 duk__convert_systime_to_ularge((const SYSTEMTIME *) &st2, &tmp2);
34974
34975 /* Difference is in 100ns units, convert to milliseconds, keeping
34976 * fractions since Duktape 2.2.0. This is only theoretical because
34977 * SYSTEMTIME is limited to milliseconds.
34978 */
34979 return (duk_double_t) ((LONGLONG) tmp1.QuadPart - (LONGLONG) tmp2.QuadPart) / 10000.0;
34980}
34981#endif /* DUK_USE_DATE_NOW_WINDOWS */
34982
34983#if defined(DUK_USE_DATE_NOW_WINDOWS_SUBMS)
34984DUK_INTERNAL duk_double_t duk_bi_date_get_now_windows_subms(void) {
34985 /* Variant of the basic algorithm using GetSystemTimePreciseAsFileTime()
34986 * for more accuracy.
34987 */
34988 FILETIME ft1;
34989 SYSTEMTIME st2;
34990 ULARGE_INTEGER tmp1, tmp2;
34991
34992 GetSystemTimePreciseAsFileTime(&ft1);
34993 duk__convert_filetime_to_ularge((const FILETIME *) &ft1, &tmp1);
34994
34995 duk__set_systime_jan1970(&st2);
34996 duk__convert_systime_to_ularge((const SYSTEMTIME *) &st2, &tmp2);
34997
34998 /* Difference is in 100ns units, convert to milliseconds, keeping
34999 * fractions since Duktape 2.2.0.
35000 */
35001 return (duk_double_t) ((LONGLONG) tmp1.QuadPart - (LONGLONG) tmp2.QuadPart) / 10000.0;
35002}
35003#endif /* DUK_USE_DATE_NOW_WINDOWS */
35004
35005#if defined(DUK_USE_DATE_TZO_WINDOWS)
35006DUK_INTERNAL duk_int_t duk_bi_date_get_local_tzoffset_windows(duk_double_t d) {
35007 SYSTEMTIME st1;
35008 SYSTEMTIME st2;
35009 SYSTEMTIME st3;
35010 ULARGE_INTEGER tmp1;
35011 ULARGE_INTEGER tmp2;
35012 ULARGE_INTEGER tmp3;
35013 FILETIME ft1;
35014
35015 /* XXX: handling of timestamps outside Windows supported range.
35016 * How does Windows deal with dates before 1600? Does windows
35017 * support all ECMAScript years (like -200000 and +200000)?
35018 * Should equivalent year mapping be used here too? If so, use
35019 * a shared helper (currently integrated into timeval-to-parts).
35020 */
35021
35022 /* Use the approach described in "Remarks" of FileTimeToLocalFileTime:
35023 * http://msdn.microsoft.com/en-us/library/windows/desktop/ms724277(v=vs.85).aspx
35024 */
35025
35026 duk__set_systime_jan1970(&st1);
35027 duk__convert_systime_to_ularge((const SYSTEMTIME *) &st1, &tmp1);
35028 tmp2.QuadPart = (ULONGLONG) (d * 10000.0); /* millisec -> 100ns units since jan 1, 1970 */
35029 tmp2.QuadPart += tmp1.QuadPart; /* input 'd' in Windows UTC, 100ns units */
35030
35031 ft1.dwLowDateTime = tmp2.LowPart;
35032 ft1.dwHighDateTime = tmp2.HighPart;
35033 if (FileTimeToSystemTime((const FILETIME *) &ft1, &st2) == 0) {
35034 DUK_D(DUK_DPRINT("FileTimeToSystemTime() failed, return tzoffset 0"));
35035 return 0;
35036 }
35037 if (SystemTimeToTzSpecificLocalTime((LPTIME_ZONE_INFORMATION) NULL, &st2, &st3) == 0) {
35038 DUK_D(DUK_DPRINT("SystemTimeToTzSpecificLocalTime() failed, return tzoffset 0"));
35039 return 0;
35040 }
35041 duk__convert_systime_to_ularge((const SYSTEMTIME *) &st3, &tmp3);
35042
35043 /* Positive if local time ahead of UTC. */
35044 return (duk_int_t) (((LONGLONG) tmp3.QuadPart - (LONGLONG) tmp2.QuadPart) / DUK_I64_CONSTANT(10000000)); /* seconds */
35045}
35046#endif /* DUK_USE_DATE_TZO_WINDOWS */
35047
35048#if defined(DUK_USE_DATE_TZO_WINDOWS_NO_DST)
35049DUK_INTERNAL duk_int_t duk_bi_date_get_local_tzoffset_windows_no_dst(duk_double_t d) {
35050 SYSTEMTIME st1;
35051 SYSTEMTIME st2;
35052 FILETIME ft1;
35053 FILETIME ft2;
35054 ULARGE_INTEGER tmp1;
35055 ULARGE_INTEGER tmp2;
35056
35057 /* Do a similar computation to duk_bi_date_get_local_tzoffset_windows
35058 * but without accounting for daylight savings time. Use this on
35059 * Windows platforms (like Durango) that don't support the
35060 * SystemTimeToTzSpecificLocalTime() call.
35061 */
35062
35063 /* current time not needed for this computation */
35064 DUK_UNREF(d);
35065
35066 duk__set_systime_jan1970(&st1);
35067 duk__convert_systime_to_ularge((const SYSTEMTIME *) &st1, &tmp1);
35068
35069 ft1.dwLowDateTime = tmp1.LowPart;
35070 ft1.dwHighDateTime = tmp1.HighPart;
35071 if (FileTimeToLocalFileTime((const FILETIME *) &ft1, &ft2) == 0) {
35072 DUK_D(DUK_DPRINT("FileTimeToLocalFileTime() failed, return tzoffset 0"));
35073 return 0;
35074 }
35075 if (FileTimeToSystemTime((const FILETIME *) &ft2, &st2) == 0) {
35076 DUK_D(DUK_DPRINT("FileTimeToSystemTime() failed, return tzoffset 0"));
35077 return 0;
35078 }
35079 duk__convert_systime_to_ularge((const SYSTEMTIME *) &st2, &tmp2);
35080
35081 return (duk_int_t) (((LONGLONG) tmp2.QuadPart - (LONGLONG) tmp1.QuadPart) / DUK_I64_CONSTANT(10000000)); /* seconds */
35082}
35083#endif /* DUK_USE_DATE_TZO_WINDOWS_NO_DST */
35084
35085#if defined(DUK_USE_GET_MONOTONIC_TIME_WINDOWS_QPC)
35086DUK_INTERNAL duk_double_t duk_bi_date_get_monotonic_time_windows_qpc(void) {
35087 LARGE_INTEGER count, freq;
35088
35089 /* There are legacy issues with QueryPerformanceCounter():
35090 * - Potential jumps:
35091 * https://support.microsoft.com/en-us/help/274323/performance-counter-value-may-unexpectedly-leap-forward
35092 * - Differences between cores (XP):
35093 * https://msdn.microsoft.com/en-us/library/windows/desktop/dn553408(v=vs.85).aspx#qpc_support_in_windows_versions
35094 *
35095 * We avoid these by enabling QPC by default only for Vista or later.
35096 */
35097
35098 if (QueryPerformanceCounter(&count) && QueryPerformanceFrequency(&freq)) {
35099 /* XXX: QueryPerformanceFrequency() can be cached */
35100 return (duk_double_t) count.QuadPart / (duk_double_t) freq.QuadPart * 1000.0;
35101 } else {
35102 /* MSDN: "On systems that run Windows XP or later, the function
35103 * will always succeed and will thus never return zero."
35104 * Provide minimal error path just in case user enables this
35105 * feature in pre-XP Windows.
35106 */
35107 return 0.0;
35108 }
35109}
35110#endif /* DUK_USE_GET_MONOTONIC_TIME_WINDOWS_QPC */
35111/*
35112 * Duktape built-ins
35113 *
35114 * Size optimization note: it might seem that vararg multipurpose functions
35115 * like fin(), enc(), and dec() are not very size optimal, but using a single
35116 * user-visible ECMAScript function saves a lot of run-time footprint; each
35117 * Function instance takes >100 bytes. Using a shared native helper and a
35118 * 'magic' value won't save much if there are multiple Function instances
35119 * anyway.
35120 */
35121
35122/* #include duk_internal.h -> already included */
35123
35124#if defined(DUK_USE_DUKTAPE_BUILTIN)
35125
35128 return 1;
35129}
35130
35132 duk_int_t level;
35133
35134 level = duk_to_int(thr, 0);
35135 duk_inspect_callstack_entry(thr, level);
35136 return 1;
35137}
35138
35140 duk_small_uint_t flags;
35142 flags = (duk_small_uint_t) duk_get_uint(thr, 0);
35143 duk_heap_mark_and_sweep(thr->heap, flags);
35144
35145 /* XXX: Not sure what the best return value would be in the API.
35146 * Return true for now.
35147 */
35148 duk_push_true(thr);
35149 return 1;
35150}
35151
35152#if defined(DUK_USE_FINALIZER_SUPPORT)
35154 (void) duk_require_hobject(thr, 0);
35155 if (duk_get_top(thr) >= 2) {
35156 /* Set: currently a finalizer is disabled by setting it to
35157 * undefined; this does not remove the property at the moment.
35158 * The value could be type checked to be either a function
35159 * or something else; if something else, the property could
35160 * be deleted. Must use duk_set_finalizer() to keep
35161 * DUK_HOBJECT_FLAG_HAVE_FINALIZER in sync.
35162 */
35164 duk_set_finalizer(thr, 0);
35165 return 0;
35166 } else {
35167 /* Get. */
35168 DUK_ASSERT(duk_get_top(thr) == 1);
35169 duk_get_finalizer(thr, 0);
35170 return 1;
35171 }
35172}
35173#endif /* DUK_USE_FINALIZER_SUPPORT */
35174
35176 duk_hstring *h_str;
35177
35178 /* Vararg function: must be careful to check/require arguments.
35179 * The JSON helpers accept invalid indices and treat them like
35180 * non-existent optional parameters.
35181 */
35182
35183 h_str = duk_require_hstring(thr, 0); /* Could reject symbols, but no point: won't match comparisons. */
35185
35186 if (h_str == DUK_HTHREAD_STRING_HEX(thr)) {
35187 duk_set_top(thr, 2);
35188 duk_hex_encode(thr, 1);
35189 DUK_ASSERT_TOP(thr, 2);
35190 } else if (h_str == DUK_HTHREAD_STRING_BASE64(thr)) {
35191 duk_set_top(thr, 2);
35192 duk_base64_encode(thr, 1);
35193 DUK_ASSERT_TOP(thr, 2);
35194#if defined(DUK_USE_JSON_SUPPORT) && defined(DUK_USE_JX)
35195 } else if (h_str == DUK_HTHREAD_STRING_JX(thr)) {
35197 1 /*idx_value*/,
35198 2 /*idx_replacer*/,
35199 3 /*idx_space*/,
35202#endif
35203#if defined(DUK_USE_JSON_SUPPORT) && defined(DUK_USE_JC)
35204 } else if (h_str == DUK_HTHREAD_STRING_JC(thr)) {
35206 1 /*idx_value*/,
35207 2 /*idx_replacer*/,
35208 3 /*idx_space*/,
35210#endif
35211 } else {
35213 }
35214 return 1;
35215}
35216
35218 duk_hstring *h_str;
35219
35220 /* Vararg function: must be careful to check/require arguments.
35221 * The JSON helpers accept invalid indices and treat them like
35222 * non-existent optional parameters.
35223 */
35224
35225 h_str = duk_require_hstring(thr, 0); /* Could reject symbols, but no point: won't match comparisons */
35227
35228 if (h_str == DUK_HTHREAD_STRING_HEX(thr)) {
35229 duk_set_top(thr, 2);
35230 duk_hex_decode(thr, 1);
35231 DUK_ASSERT_TOP(thr, 2);
35232 } else if (h_str == DUK_HTHREAD_STRING_BASE64(thr)) {
35233 duk_set_top(thr, 2);
35234 duk_base64_decode(thr, 1);
35235 DUK_ASSERT_TOP(thr, 2);
35236#if defined(DUK_USE_JSON_SUPPORT) && defined(DUK_USE_JX)
35237 } else if (h_str == DUK_HTHREAD_STRING_JX(thr)) {
35238 duk_bi_json_parse_helper(thr, 1 /*idx_value*/, 2 /*idx_replacer*/, DUK_JSON_FLAG_EXT_CUSTOM /*flags*/);
35239#endif
35240#if defined(DUK_USE_JSON_SUPPORT) && defined(DUK_USE_JC)
35241 } else if (h_str == DUK_HTHREAD_STRING_JC(thr)) {
35242 duk_bi_json_parse_helper(thr, 1 /*idx_value*/, 2 /*idx_replacer*/, DUK_JSON_FLAG_EXT_COMPATIBLE /*flags*/);
35243#endif
35244 } else {
35246 }
35247 return 1;
35248}
35249
35250/*
35251 * Compact an object
35252 */
35253
35255 DUK_ASSERT_TOP(thr, 1);
35256 duk_compact(thr, 0);
35257 return 1; /* return the argument object */
35258}
35259
35260#endif /* DUK_USE_DUKTAPE_BUILTIN */
35261/*
35262 * WHATWG Encoding API built-ins
35264 * API specification: https://encoding.spec.whatwg.org/#api
35265 * Web IDL: https://www.w3.org/TR/WebIDL/
35266 */
35268/* #include duk_internal.h -> already included */
35271 * Data structures for encoding/decoding
35274typedef struct {
35275 duk_uint8_t *out; /* where to write next byte(s) */
35276 duk_codepoint_t lead; /* lead surrogate */
35278
35279typedef struct {
35280 /* UTF-8 decoding state */
35281 duk_codepoint_t codepoint; /* built up incrementally */
35282 duk_uint8_t upper; /* max value of next byte (decode error otherwise) */
35283 duk_uint8_t lower; /* min value of next byte (ditto) */
35284 duk_uint8_t needed; /* how many more bytes we need */
35285 duk_uint8_t bom_handled; /* BOM seen or no longer expected */
35286
35287 /* Decoder configuration */
35288 duk_uint8_t fatal;
35289 duk_uint8_t ignore_bom;
35291
35292/* The signed duk_codepoint_t type is used to signal a decoded codepoint
35293 * (>= 0) or various other states using negative values.
35294 */
35295#define DUK__CP_CONTINUE (-1) /* continue to next byte, no completed codepoint */
35296#define DUK__CP_ERROR (-2) /* decoding error */
35297#define DUK__CP_RETRY (-3) /* decoding error; retry last byte */
35298
35300 * Raw helpers for encoding/decoding
35301 */
35302
35303/* Emit UTF-8 (= CESU-8) encoded U+FFFD (replacement char), i.e. ef bf bd. */
35304DUK_LOCAL duk_uint8_t *duk__utf8_emit_repl(duk_uint8_t *ptr) {
35305 *ptr++ = 0xef;
35306 *ptr++ = 0xbf;
35307 *ptr++ = 0xbd;
35308 return ptr;
35309}
35312 /* (Re)init the decoding state of 'dec_ctx' but leave decoder
35313 * configuration fields untouched.
35314 */
35315 dec_ctx->codepoint = 0x0000L;
35316 dec_ctx->upper = 0xbf;
35317 dec_ctx->lower = 0x80;
35318 dec_ctx->needed = 0;
35319 dec_ctx->bom_handled = 0;
35320}
35321
35323 /*
35324 * UTF-8 algorithm based on the Encoding specification:
35325 * https://encoding.spec.whatwg.org/#utf-8-decoder
35326 *
35327 * Two main states: decoding initial byte vs. decoding continuation
35328 * bytes. Shortest length encoding is validated by restricting the
35329 * allowed range of first continuation byte using 'lower' and 'upper'.
35330 */
35331
35332 if (dec_ctx->needed == 0) {
35333 /* process initial byte */
35334 if (x <= 0x7f) {
35335 /* U+0000-U+007F, 1 byte (ASCII) */
35336 return (duk_codepoint_t) x;
35337 } else if (x >= 0xc2 && x <= 0xdf) {
35338 /* U+0080-U+07FF, 2 bytes */
35339 dec_ctx->needed = 1;
35340 dec_ctx->codepoint = x & 0x1f;
35341 DUK_ASSERT(dec_ctx->lower == 0x80);
35342 DUK_ASSERT(dec_ctx->upper == 0xbf);
35343 return DUK__CP_CONTINUE;
35344 } else if (x >= 0xe0 && x <= 0xef) {
35345 /* U+0800-U+FFFF, 3 bytes */
35346 if (x == 0xe0) {
35347 dec_ctx->lower = 0xa0;
35348 DUK_ASSERT(dec_ctx->upper == 0xbf);
35349 } else if (x == 0xed) {
35350 DUK_ASSERT(dec_ctx->lower == 0x80);
35351 dec_ctx->upper = 0x9f;
35352 }
35353 dec_ctx->needed = 2;
35354 dec_ctx->codepoint = x & 0x0f;
35355 return DUK__CP_CONTINUE;
35356 } else if (x >= 0xf0 && x <= 0xf4) {
35357 /* U+010000-U+10FFFF, 4 bytes */
35358 if (x == 0xf0) {
35359 dec_ctx->lower = 0x90;
35360 DUK_ASSERT(dec_ctx->upper == 0xbf);
35361 } else if (x == 0xf4) {
35362 DUK_ASSERT(dec_ctx->lower == 0x80);
35363 dec_ctx->upper = 0x8f;
35364 }
35365 dec_ctx->needed = 3;
35366 dec_ctx->codepoint = x & 0x07;
35367 return DUK__CP_CONTINUE;
35368 } else {
35369 /* not a legal initial byte */
35370 return DUK__CP_ERROR;
35371 }
35372 } else {
35373 /* process continuation byte */
35374 if (x >= dec_ctx->lower && x <= dec_ctx->upper) {
35375 dec_ctx->lower = 0x80;
35376 dec_ctx->upper = 0xbf;
35377 dec_ctx->codepoint = (dec_ctx->codepoint << 6) | (x & 0x3f);
35378 if (--dec_ctx->needed > 0) {
35379 /* need more bytes */
35380 return DUK__CP_CONTINUE;
35381 } else {
35382 /* got a codepoint */
35383 duk_codepoint_t ret;
35384 DUK_ASSERT(dec_ctx->codepoint <= 0x10ffffL); /* Decoding rules guarantee. */
35385 ret = dec_ctx->codepoint;
35386 dec_ctx->codepoint = 0x0000L;
35387 dec_ctx->needed = 0;
35388 return ret;
35389 }
35390 } else {
35391 /* We just encountered an illegal UTF-8 continuation byte. This might
35392 * be the initial byte of the next character; if we return a plain
35393 * error status and the decoder is in replacement mode, the character
35394 * will be masked. We still need to alert the caller to the error
35395 * though.
35396 */
35397 dec_ctx->codepoint = 0x0000L;
35398 dec_ctx->needed = 0;
35399 dec_ctx->lower = 0x80;
35400 dec_ctx->upper = 0xbf;
35401 return DUK__CP_RETRY;
35402 }
35403 }
35404}
35405
35406#if defined(DUK_USE_ENCODING_BUILTINS)
35407DUK_LOCAL void duk__utf8_encode_char(void *udata, duk_codepoint_t codepoint) {
35408 duk__encode_context *enc_ctx;
35409
35410 DUK_ASSERT(codepoint >= 0);
35411 enc_ctx = (duk__encode_context *) udata;
35412 DUK_ASSERT(enc_ctx != NULL);
35413
35414#if !defined(DUK_USE_PREFER_SIZE)
35415 if (codepoint <= 0x7f && enc_ctx->lead == 0x0000L) {
35416 /* Fast path for ASCII. */
35417 *enc_ctx->out++ = (duk_uint8_t) codepoint;
35418 return;
35419 }
35420#endif
35421
35422 if (DUK_UNLIKELY(codepoint > 0x10ffffL)) {
35423 /* cannot legally encode in UTF-8 */
35425 } else if (codepoint >= 0xd800L && codepoint <= 0xdfffL) {
35426 if (codepoint <= 0xdbffL) {
35427 /* high surrogate */
35428 duk_codepoint_t prev_lead = enc_ctx->lead;
35429 enc_ctx->lead = codepoint;
35430 if (prev_lead == 0x0000L) {
35431 /* high surrogate, no output */
35432 return;
35433 } else {
35434 /* consecutive high surrogates, consider first one unpaired */
35436 }
35437 } else {
35438 /* low surrogate */
35439 if (enc_ctx->lead != 0x0000L) {
35440 codepoint =
35441 (duk_codepoint_t) (0x010000L + ((enc_ctx->lead - 0xd800L) << 10) + (codepoint - 0xdc00L));
35442 enc_ctx->lead = 0x0000L;
35443 } else {
35444 /* unpaired low surrogate */
35445 DUK_ASSERT(enc_ctx->lead == 0x0000L);
35447 }
35448 }
35449 } else {
35450 if (enc_ctx->lead != 0x0000L) {
35451 /* unpaired high surrogate: emit replacement character and the input codepoint */
35452 enc_ctx->lead = 0x0000L;
35453 enc_ctx->out = duk__utf8_emit_repl(enc_ctx->out);
35454 }
35456
35457 /* Codepoint may be original input, a decoded surrogate pair, or may
35458 * have been replaced with U+FFFD.
35459 */
35460 enc_ctx->out += duk_unicode_encode_xutf8((duk_ucodepoint_t) codepoint, enc_ctx->out);
35461}
35462#endif /* DUK_USE_ENCODING_BUILTINS */
35463
35464/* Shared helper for buffer-to-string using a TextDecoder() compatible UTF-8
35465 * decoder.
35466 */
35468 const duk_uint8_t *input;
35469 duk_size_t len = 0;
35470 duk_size_t len_tmp;
35471 duk_bool_t stream = 0;
35472 duk_codepoint_t codepoint;
35473 duk_uint8_t *output;
35474 const duk_uint8_t *in;
35475 duk_uint8_t *out;
35476
35477 DUK_ASSERT(dec_ctx != NULL);
35478
35479 /* Careful with input buffer pointer: any side effects involving
35480 * code execution (e.g. getters, coercion calls, and finalizers)
35481 * may cause a resize and invalidate a pointer we've read. This
35482 * is why the pointer is actually looked up at the last minute.
35483 * Argument validation must still happen first to match WHATWG
35484 * required side effect order.
35485 */
35486
35487 if (duk_is_undefined(thr, 0)) {
35489 duk_replace(thr, 0);
35490 }
35491 (void) duk_require_buffer_data(thr, 0, &len); /* Need 'len', avoid pointer. */
35492
35494 /* Use defaults, treat missing value like undefined. */
35495 } else {
35497 1,
35500 if (duk_get_prop_literal(thr, 1, "stream")) {
35501 stream = duk_to_boolean(thr, -1);
35502 }
35503 }
35504
35505 /* Allowance is 3*len in the general case because all bytes may potentially
35506 * become U+FFFD. If the first byte completes a non-BMP codepoint it will
35507 * decode to a CESU-8 surrogate pair (6 bytes) so we allow 3 extra bytes to
35508 * compensate: (1*3)+3 = 6. Non-BMP codepoints are safe otherwise because
35509 * the 4->6 expansion is well under the 3x allowance.
35510 *
35511 * XXX: As with TextEncoder, need a better buffer allocation strategy here.
35512 */
35513 if (len >= (DUK_HBUFFER_MAX_BYTELEN / 3) - 3) {
35515 DUK_WO_NORETURN(return 0;);
35516 }
35517 output =
35518 (duk_uint8_t *) duk_push_fixed_buffer_nozero(thr, 3 + (3 * len)); /* used parts will be always manually written over */
35519
35520 input = (const duk_uint8_t *) duk_get_buffer_data(thr, 0, &len_tmp);
35521 DUK_ASSERT(input != NULL || len == 0);
35522 if (DUK_UNLIKELY(len != len_tmp)) {
35523 /* Very unlikely but possible: source buffer was resized by
35524 * a side effect when fixed buffer was pushed. Output buffer
35525 * may not be large enough to hold output, so just fail if
35526 * length has changed.
35527 */
35528 DUK_D(DUK_DPRINT("input buffer resized by side effect, fail"));
35529 goto fail_type;
35530 }
35531
35532 /* From this point onwards it's critical that no side effect occur
35533 * which may disturb 'input': finalizer execution, property accesses,
35534 * active coercions, etc. Even an allocation related mark-and-sweep
35535 * may affect the pointer because it may trigger a pending finalizer.
35536 */
35537
35538 in = input;
35539 out = output;
35540 while (in < input + len) {
35541 codepoint = duk__utf8_decode_next(dec_ctx, *in++);
35542 if (codepoint < 0) {
35543 if (codepoint == DUK__CP_CONTINUE) {
35544 continue;
35545 }
35546
35547 /* Decoding error with or without retry. */
35548 DUK_ASSERT(codepoint == DUK__CP_ERROR || codepoint == DUK__CP_RETRY);
35549 if (codepoint == DUK__CP_RETRY) {
35550 --in; /* retry last byte */
35551 }
35552 /* replacement mode: replace with U+FFFD */
35554 if (dec_ctx->fatal) {
35555 /* fatal mode: throw a TypeError */
35556 goto fail_type;
35557 }
35558 /* Continue with 'codepoint', Unicode replacement. */
35559 }
35560 DUK_ASSERT(codepoint >= 0x0000L && codepoint <= 0x10ffffL);
35561
35562 if (!dec_ctx->bom_handled) {
35563 dec_ctx->bom_handled = 1;
35564 if (codepoint == 0xfeffL && !dec_ctx->ignore_bom) {
35565 continue;
35566 }
35567 }
35568
35569 out += duk_unicode_encode_cesu8((duk_ucodepoint_t) codepoint, out);
35570 DUK_ASSERT(out <= output + (3 + (3 * len)));
35571 }
35572
35573 if (!stream) {
35574 if (dec_ctx->needed != 0) {
35575 /* truncated sequence at end of buffer */
35576 if (dec_ctx->fatal) {
35577 goto fail_type;
35578 } else {
35580 DUK_ASSERT(out <= output + (3 + (3 * len)));
35581 }
35582 }
35583 duk__utf8_decode_init(dec_ctx); /* Initialize decoding state for potential reuse. */
35584 }
35585
35586 /* Output buffer is fixed and thus stable even if there had been
35587 * side effects (which there shouldn't be).
35588 */
35589 duk_push_lstring(thr, (const char *) output, (duk_size_t) (out - output));
35590 return 1;
35591
35592fail_type:
35594 DUK_WO_NORETURN(return 0;);
35595}
35596
35597/*
35598 * Built-in bindings
35600
35601#if defined(DUK_USE_ENCODING_BUILTINS)
35603 /* TextEncoder currently requires no persistent state, so the constructor
35604 * does nothing on purpose.
35605 */
35606
35608 return 0;
35609}
35610
35612 duk_push_literal(thr, "utf-8");
35613 return 1;
35614}
35615
35617 duk__encode_context enc_ctx;
35618 duk_size_t len;
35619 duk_size_t final_len;
35620 duk_uint8_t *output;
35621
35622 DUK_ASSERT_TOP(thr, 1);
35623 if (duk_is_undefined(thr, 0)) {
35624 len = 0;
35625 } else {
35626 duk_hstring *h_input;
35627
35628 h_input = duk_to_hstring(thr, 0);
35629 DUK_ASSERT(h_input != NULL);
35630
35631 len = (duk_size_t) DUK_HSTRING_GET_CHARLEN(h_input);
35632 if (len >= DUK_HBUFFER_MAX_BYTELEN / 3) {
35634 DUK_WO_NORETURN(return 0;);
35635 }
35636 }
35637
35638 /* Allowance is 3*len because all bytes can potentially be replaced with
35639 * U+FFFD -- which rather inconveniently encodes to 3 bytes in UTF-8.
35640 * Rely on dynamic buffer data pointer stability: no other code has
35641 * access to the data pointer.
35642 *
35643 * XXX: The buffer allocation strategy used here is rather inefficient.
35644 * Maybe switch to a chunk-based strategy, or preprocess the string to
35645 * figure out the space needed ahead of time?
35646 */
35647 DUK_ASSERT(3 * len >= len);
35648 output = (duk_uint8_t *) duk_push_dynamic_buffer(thr, 3 * len);
35649
35650 if (len > 0) {
35651 DUK_ASSERT(duk_is_string(thr, 0)); /* True if len > 0. */
35652
35653 /* XXX: duk_decode_string() is used to process the input
35654 * string. For standard ECMAScript strings, represented
35655 * internally as CESU-8, this is fine. However, behavior
35656 * beyond CESU-8 is not very strict: codepoints using an
35657 * extended form of UTF-8 are also accepted, and invalid
35658 * codepoint sequences (which are allowed in Duktape strings)
35659 * are not handled as well as they could (e.g. invalid
35660 * continuation bytes may mask following codepoints).
35661 * This is how ECMAScript code would also see such strings.
35662 * Maybe replace duk_decode_string() with an explicit strict
35663 * CESU-8 decoder here?
35664 */
35665 enc_ctx.lead = 0x0000L;
35666 enc_ctx.out = output;
35667 duk_decode_string(thr, 0, duk__utf8_encode_char, (void *) &enc_ctx);
35668 if (enc_ctx.lead != 0x0000L) {
35669 /* unpaired high surrogate at end of string */
35670 enc_ctx.out = duk__utf8_emit_repl(enc_ctx.out);
35671 DUK_ASSERT(enc_ctx.out <= output + (3 * len));
35672 }
35673
35674 /* The output buffer is usually very much oversized, so shrink it to
35675 * actually needed size. Pointer stability assumed up to this point.
35676 */
35677 DUK_ASSERT_TOP(thr, 2);
35678 DUK_ASSERT(output == (duk_uint8_t *) duk_get_buffer_data(thr, -1, NULL));
35679
35680 final_len = (duk_size_t) (enc_ctx.out - output);
35681 duk_resize_buffer(thr, -1, final_len);
35682 /* 'output' and 'enc_ctx.out' are potentially invalidated by the resize. */
35683 } else {
35684 final_len = 0;
35685 }
35686
35687 /* Standard WHATWG output is a Uint8Array. Here the Uint8Array will
35688 * be backed by a dynamic buffer which differs from e.g. Uint8Arrays
35689 * created as 'new Uint8Array(N)'. ECMAScript code won't see the
35690 * difference but C code will. When bufferobjects are not supported,
35691 * returns a plain dynamic buffer.
35692 */
35693#if defined(DUK_USE_BUFFEROBJECT_SUPPORT)
35694 duk_push_buffer_object(thr, -1, 0, final_len, DUK_BUFOBJ_UINT8ARRAY);
35695#endif
35696 return 1;
35697}
35698
35700 duk__decode_context *dec_ctx;
35701 duk_bool_t fatal = 0;
35702 duk_bool_t ignore_bom = 0;
35703
35704 DUK_ASSERT_TOP(thr, 2);
35706 if (!duk_is_undefined(thr, 0)) {
35707 /* XXX: For now ignore 'label' (encoding identifier). */
35708 duk_to_string(thr, 0);
35709 }
35710 if (!duk_is_null_or_undefined(thr, 1)) {
35711 if (duk_get_prop_literal(thr, 1, "fatal")) {
35712 fatal = duk_to_boolean(thr, -1);
35713 }
35714 if (duk_get_prop_literal(thr, 1, "ignoreBOM")) {
35715 ignore_bom = duk_to_boolean(thr, -1);
35716 }
35717 }
35718
35719 duk_push_this(thr);
35720
35721 /* The decode context is not assumed to be zeroed; all fields are
35722 * initialized explicitly.
35723 */
35725 dec_ctx->fatal = (duk_uint8_t) fatal;
35726 dec_ctx->ignore_bom = (duk_uint8_t) ignore_bom;
35727 duk__utf8_decode_init(dec_ctx); /* Initializes remaining fields. */
35728
35729 duk_put_prop_literal(thr, -2, DUK_INTERNAL_SYMBOL("Context"));
35730 return 0;
35732
35733/* Get TextDecoder context from 'this'; leaves garbage on stack. */
35735 duk__decode_context *dec_ctx;
35736 duk_push_this(thr);
35737 duk_get_prop_literal(thr, -1, DUK_INTERNAL_SYMBOL("Context"));
35738 dec_ctx = (duk__decode_context *) duk_require_buffer(thr, -1, NULL);
35739 DUK_ASSERT(dec_ctx != NULL);
35740 return dec_ctx;
35741}
35742
35744 duk__decode_context *dec_ctx;
35745 duk_int_t magic;
35746
35747 dec_ctx = duk__get_textdecoder_context(thr);
35748 magic = duk_get_current_magic(thr);
35749 switch (magic) {
35750 case 0:
35751 /* Encoding is now fixed, so _Context lookup is only needed to
35752 * validate the 'this' binding (TypeError if not TextDecoder-like).
35753 */
35754 duk_push_literal(thr, "utf-8");
35755 break;
35756 case 1:
35757 duk_push_boolean(thr, dec_ctx->fatal);
35758 break;
35759 default:
35760 duk_push_boolean(thr, dec_ctx->ignore_bom);
35761 break;
35762 }
35763
35764 return 1;
35765}
35766
35768 duk__decode_context *dec_ctx;
35769
35770 dec_ctx = duk__get_textdecoder_context(thr);
35771 return duk__decode_helper(thr, dec_ctx);
35773#endif /* DUK_USE_ENCODING_BUILTINS */
35774
35775/*
35776 * Internal helper for Node.js Buffer
35777 */
35778
35779/* Internal helper used for Node.js Buffer .toString(). Value stack convention
35780 * is currently odd: it mimics TextDecoder .decode() so that argument must be at
35781 * index 0, and decode options (not present for Buffer) at index 1. Return value
35782 * is a Duktape/C function return value.
35783 */
35785 duk__decode_context dec_ctx;
35786
35787 dec_ctx.fatal = 0; /* use replacement chars */
35788 dec_ctx.ignore_bom = 1; /* ignore BOMs (matches Node.js Buffer .toString()) */
35789 duk__utf8_decode_init(&dec_ctx);
35790
35791 return duk__decode_helper(thr, &dec_ctx);
35793
35794/* automatic undefs */
35795#undef DUK__CP_CONTINUE
35796#undef DUK__CP_ERROR
35797#undef DUK__CP_RETRY
35798/*
35799 * Error built-ins
35800 */
35801
35802/* #include duk_internal.h -> already included */
35803
35805 /* Behavior for constructor and non-constructor call is
35806 * the same except for augmenting the created error. When
35807 * called as a constructor, the caller (duk_new()) will handle
35808 * augmentation; when called as normal function, we need to do
35809 * it here.
35810 */
35811
35812 duk_small_int_t bidx_prototype = duk_get_current_magic(thr);
35813
35814 /* same for both error and each subclass like TypeError */
35815 duk_uint_t flags_and_class =
35817
35818 (void) duk_push_object_helper(thr, flags_and_class, bidx_prototype);
35819
35820 /* If message is undefined, the own property 'message' is not set at
35821 * all to save property space. An empty message is inherited anyway.
35822 */
35823 if (!duk_is_undefined(thr, 0)) {
35824 duk_to_string(thr, 0);
35825 duk_dup_0(thr); /* [ message error message ] */
35827 }
35828
35829 /* Augment the error if called as a normal function. __FILE__ and __LINE__
35830 * are not desirable in this case.
35831 */
35832
35833#if defined(DUK_USE_AUGMENT_ERROR_CREATE)
35834 if (!duk_is_constructor_call(thr)) {
35836 }
35837#endif
35838
35839 return 1;
35840}
35841
35843 /* XXX: optimize with more direct internal access */
35844
35845 duk_push_this(thr);
35847
35848 /* [ ... this ] */
35849
35851 if (duk_is_undefined(thr, -1)) {
35852 duk_pop(thr);
35853 duk_push_literal(thr, "Error");
35854 } else {
35855 duk_to_string(thr, -1);
35856 }
35857
35858 /* [ ... this name ] */
35859
35860 /* XXX: Are steps 6 and 7 in E5 Section 15.11.4.4 duplicated by
35861 * accident or are they actually needed? The first ToString()
35862 * could conceivably return 'undefined'.
35863 */
35865 if (duk_is_undefined(thr, -1)) {
35866 duk_pop(thr);
35868 } else {
35869 duk_to_string(thr, -1);
35870 }
35871
35872 /* [ ... this name message ] */
35873
35874 if (duk_get_length(thr, -2) == 0) {
35875 /* name is empty -> return message */
35876 return 1;
35877 }
35878 if (duk_get_length(thr, -1) == 0) {
35879 /* message is empty -> return name */
35880 duk_pop(thr);
35881 return 1;
35882 }
35883 duk_push_literal(thr, ": ");
35884 duk_insert(thr, -2); /* ... name ': ' message */
35885 duk_concat(thr, 3);
35886
35887 return 1;
35888}
35889
35890#if defined(DUK_USE_TRACEBACKS)
35891
35892/*
35893 * Traceback handling
35894 *
35895 * The unified helper decodes the traceback and produces various requested
35896 * outputs. It should be optimized for size, and may leave garbage on stack,
35897 * only the topmost return value matters. For instance, traceback separator
35898 * and decoded strings are pushed even when looking for filename only.
35900 * NOTE: although _Tracedata is an internal property, user code can currently
35901 * write to the array (or replace it with something other than an array).
35902 * The code below must tolerate arbitrary _Tracedata. It can throw errors
35903 * etc, but cannot cause a segfault or memory unsafe behavior.
35904 */
35905
35906/* constants arbitrary, chosen for small loads */
35907#define DUK__OUTPUT_TYPE_TRACEBACK (-1)
35908#define DUK__OUTPUT_TYPE_FILENAME 0
35909#define DUK__OUTPUT_TYPE_LINENUMBER 1
35910
35912 duk_idx_t idx_td;
35913 duk_small_int_t i; /* traceback depth fits into 16 bits */
35914 duk_small_int_t t; /* stack type fits into 16 bits */
35915 duk_small_int_t count_func = 0; /* traceback depth ensures fits into 16 bits */
35916 const char *str_tailcall = " tailcall";
35917 const char *str_strict = " strict";
35918 const char *str_construct = " construct";
35919 const char *str_prevyield = " preventsyield";
35920 const char *str_directeval = " directeval";
35921 const char *str_empty = "";
35922
35923 DUK_ASSERT_TOP(thr, 0); /* fixed arg count */
35924
35925 duk_push_this(thr);
35927 idx_td = duk_get_top_index(thr);
35928
35930 duk_push_this(thr);
35931
35932 /* [ ... this tracedata sep this ] */
35933
35934 /* XXX: skip null filename? */
35935
35936 if (duk_check_type(thr, idx_td, DUK_TYPE_OBJECT)) {
35937 /* Current tracedata contains 2 entries per callstack entry. */
35938 for (i = 0;; i += 2) {
35939 duk_int_t pc;
35941 duk_uint_t flags;
35942 duk_double_t d;
35943 const char *funcname;
35944 const char *filename;
35945 duk_hobject *h_func;
35946 duk_hstring *h_name;
35947
35948 duk_require_stack(thr, 5);
35949 duk_get_prop_index(thr, idx_td, (duk_uarridx_t) i);
35950 duk_get_prop_index(thr, idx_td, (duk_uarridx_t) (i + 1));
35951 d = duk_to_number_m1(thr);
35954 t = (duk_small_int_t) duk_get_type(thr, -2);
35955
35956 if (t == DUK_TYPE_OBJECT || t == DUK_TYPE_LIGHTFUNC) {
35957 /*
35958 * ECMAScript/native function call or lightfunc call
35959 */
35960
35961 count_func++;
35962
35963 /* [ ... v1(func) v2(pc+flags) ] */
35964
35965 /* These may be systematically omitted by Duktape
35966 * with certain config options, but allow user to
35967 * set them on a case-by-case basis.
35968 */
35971
35972#if defined(DUK_USE_PC2LINE)
35974#else
35975 line = 0;
35976#endif
35977
35978 /* [ ... v1 v2 name filename ] */
35979
35980 /* When looking for .fileName/.lineNumber, blame first
35981 * function which has a .fileName.
35982 */
35983 if (duk_is_string_notsymbol(thr, -1)) {
35984 if (output_type == DUK__OUTPUT_TYPE_FILENAME) {
35985 return 1;
35986 } else if (output_type == DUK__OUTPUT_TYPE_LINENUMBER) {
35987 duk_push_uint(thr, line);
35988 return 1;
35989 }
35990 }
35991
35992 /* XXX: Change 'anon' handling here too, to use empty string for anonymous functions? */
35993 /* XXX: Could be improved by coercing to a readable duk_tval (especially string escaping) */
35994 h_name = duk_get_hstring_notsymbol(thr, -2); /* may be NULL */
35995 funcname = (h_name == NULL || h_name == DUK_HTHREAD_STRING_EMPTY_STRING(thr)) ?
35996 "[anon]" :
35997 (const char *) DUK_HSTRING_GET_DATA(h_name);
35998 filename = duk_get_string_notsymbol(thr, -1);
35999 filename = filename ? filename : "";
36000 DUK_ASSERT(funcname != NULL);
36001 DUK_ASSERT(filename != NULL);
36002
36003 h_func = duk_get_hobject(thr, -4); /* NULL for lightfunc */
36004
36005 if (h_func == NULL) {
36007 thr,
36008 "at %s light%s%s%s%s%s",
36009 (const char *) funcname,
36010 (const char *) ((flags & DUK_ACT_FLAG_STRICT) ? str_strict : str_empty),
36011 (const char *) ((flags & DUK_ACT_FLAG_TAILCALLED) ? str_tailcall : str_empty),
36012 (const char *) ((flags & DUK_ACT_FLAG_CONSTRUCT) ? str_construct : str_empty),
36013 (const char *) ((flags & DUK_ACT_FLAG_DIRECT_EVAL) ? str_directeval : str_empty),
36014 (const char *) ((flags & DUK_ACT_FLAG_PREVENT_YIELD) ? str_prevyield : str_empty));
36015 } else if (DUK_HOBJECT_HAS_NATFUNC(h_func)) {
36017 thr,
36018 "at %s (%s) native%s%s%s%s%s",
36019 (const char *) funcname,
36020 (const char *) filename,
36021 (const char *) ((flags & DUK_ACT_FLAG_STRICT) ? str_strict : str_empty),
36022 (const char *) ((flags & DUK_ACT_FLAG_TAILCALLED) ? str_tailcall : str_empty),
36023 (const char *) ((flags & DUK_ACT_FLAG_CONSTRUCT) ? str_construct : str_empty),
36024 (const char *) ((flags & DUK_ACT_FLAG_DIRECT_EVAL) ? str_directeval : str_empty),
36025 (const char *) ((flags & DUK_ACT_FLAG_PREVENT_YIELD) ? str_prevyield : str_empty));
36026 } else {
36028 thr,
36029 "at %s (%s:%lu)%s%s%s%s%s",
36030 (const char *) funcname,
36031 (const char *) filename,
36032 (unsigned long) line,
36033 (const char *) ((flags & DUK_ACT_FLAG_STRICT) ? str_strict : str_empty),
36034 (const char *) ((flags & DUK_ACT_FLAG_TAILCALLED) ? str_tailcall : str_empty),
36035 (const char *) ((flags & DUK_ACT_FLAG_CONSTRUCT) ? str_construct : str_empty),
36036 (const char *) ((flags & DUK_ACT_FLAG_DIRECT_EVAL) ? str_directeval : str_empty),
36037 (const char *) ((flags & DUK_ACT_FLAG_PREVENT_YIELD) ? str_prevyield : str_empty));
36038 }
36039 duk_replace(thr, -5); /* [ ... v1 v2 name filename str ] -> [ ... str v2 name filename ] */
36040 duk_pop_3(thr); /* -> [ ... str ] */
36041 } else if (t == DUK_TYPE_STRING) {
36042 const char *str_file;
36043
36044 /*
36045 * __FILE__ / __LINE__ entry, here 'pc' is line number directly.
36046 * Sometimes __FILE__ / __LINE__ is reported as the source for
36047 * the error (fileName, lineNumber), sometimes not.
36048 */
36049
36050 /* [ ... v1(filename) v2(line+flags) ] */
36051
36052 /* When looking for .fileName/.lineNumber, blame compilation
36053 * or C call site unless flagged not to do so.
36054 */
36055 if (!(flags & DUK_TB_FLAG_NOBLAME_FILELINE)) {
36056 if (output_type == DUK__OUTPUT_TYPE_FILENAME) {
36057 duk_pop(thr);
36058 return 1;
36059 } else if (output_type == DUK__OUTPUT_TYPE_LINENUMBER) {
36060 duk_push_int(thr, pc);
36061 return 1;
36062 }
36063 }
36064
36065 /* Tracedata is trusted but avoid any risk of using a NULL
36066 * for %s format because it has undefined behavior. Symbols
36067 * don't need to be explicitly rejected as they pose no memory
36068 * safety issues.
36069 */
36070 str_file = (const char *) duk_get_string(thr, -2);
36071 duk_push_sprintf(thr,
36072 "at [anon] (%s:%ld) internal",
36073 (const char *) (str_file ? str_file : "null"),
36074 (long) pc);
36075 duk_replace(thr, -3); /* [ ... v1 v2 str ] -> [ ... str v2 ] */
36076 duk_pop(thr); /* -> [ ... str ] */
36077 } else {
36078 /* unknown, ignore */
36079 duk_pop_2(thr);
36080 break;
36081 }
36082 }
36083
36084 if (count_func >= DUK_USE_TRACEBACK_DEPTH) {
36085 /* Possibly truncated; there is no explicit truncation
36086 * marker so this is the best we can do.
36087 */
36088
36090 }
36091 }
36092
36093 /* [ ... this tracedata sep this str1 ... strN ] */
36094
36095 if (output_type != DUK__OUTPUT_TYPE_TRACEBACK) {
36096 return 0;
36097 } else {
36098 /* The 'this' after 'sep' will get ToString() coerced by
36099 * duk_join() automatically. We don't want to do that
36100 * coercion when providing .fileName or .lineNumber (GH-254).
36101 */
36102 duk_join(thr, duk_get_top(thr) - (idx_td + 2) /*count, not including sep*/);
36103 return 1;
36104 }
36105}
36106
36107/* XXX: Output type could be encoded into native function 'magic' value to
36108 * save space. For setters the stridx could be encoded into 'magic'.
36109 */
36110
36113}
36114
36117}
36118
36121}
36122
36123#else /* DUK_USE_TRACEBACKS */
36124
36125/*
36126 * Traceback handling when tracebacks disabled.
36127 *
36128 * The fileName / lineNumber stubs are now necessary because built-in
36129 * data will include the accessor properties in Error.prototype. If those
36130 * are removed for builds without tracebacks, these can also be removed.
36131 * 'stack' should still be present and produce a ToString() equivalent:
36132 * this is useful for user code which prints a stacktrace and expects to
36133 * see something useful. A normal stacktrace also begins with a ToString()
36134 * of the error so this makes sense.
36135 */
36136
36138 /* XXX: remove this native function and map 'stack' accessor
36139 * to the toString() implementation directly.
36140 */
36142}
36143
36145 DUK_UNREF(thr);
36146 return 0;
36147}
36148
36150 DUK_UNREF(thr);
36151 return 0;
36152}
36153
36154#endif /* DUK_USE_TRACEBACKS */
36155
36157 /* Attempt to write 'stack', 'fileName', 'lineNumber' works as if
36158 * user code called Object.defineProperty() to create an overriding
36159 * own property. This allows user code to overwrite .fileName etc
36160 * intuitively as e.g. "err.fileName = 'dummy'" as one might expect.
36161 * See https://github.com/svaarala/duktape/issues/387.
36162 */
36163
36164 DUK_ASSERT_TOP(thr, 1); /* fixed arg count: value */
36165
36166 duk_push_this(thr);
36167 duk_push_hstring_stridx(thr, stridx_key);
36168 duk_dup_0(thr);
36169
36170 /* [ ... obj key value ] */
36171
36172 DUK_DD(DUK_DDPRINT("error setter: %!T %!T %!T", duk_get_tval(thr, -3), duk_get_tval(thr, -2), duk_get_tval(thr, -1)));
36173
36175 -3,
36177 DUK_DEFPROP_HAVE_ENUMERABLE | /*not enumerable*/
36179 return 0;
36180}
36181
36184}
36185
36188}
36189
36192}
36194/* automatic undefs */
36195#undef DUK__OUTPUT_TYPE_FILENAME
36196#undef DUK__OUTPUT_TYPE_LINENUMBER
36197#undef DUK__OUTPUT_TYPE_TRACEBACK
36198/*
36199 * Function built-ins
36201
36202/* #include duk_internal.h -> already included */
36203
36204/* Needed even when Function built-in is disabled. */
36206 /* ignore arguments, return undefined (E5 Section 15.3.4) */
36207 DUK_UNREF(thr);
36208 return 0;
36209}
36210
36211#if defined(DUK_USE_FUNCTION_BUILTIN)
36213 duk_hstring *h_sourcecode;
36214 duk_idx_t nargs;
36215 duk_idx_t i;
36216 duk_small_uint_t comp_flags;
36217 duk_hcompfunc *func;
36218 duk_hobject *outer_lex_env;
36219 duk_hobject *outer_var_env;
36220
36221 /* normal and constructor calls have identical semantics */
36222
36223 nargs = duk_get_top(thr);
36224 for (i = 0; i < nargs; i++) {
36225 duk_to_string(thr, i); /* Rejects Symbols during coercion. */
36226 }
36227
36228 if (nargs == 0) {
36231 } else if (nargs == 1) {
36232 /* XXX: cover this with the generic >1 case? */
36234 } else {
36235 duk_insert(thr, 0); /* [ arg1 ... argN-1 body] -> [body arg1 ... argN-1] */
36236 duk_push_literal(thr, ",");
36237 duk_insert(thr, 1);
36238 duk_join(thr, nargs - 1);
36239 }
36240
36241 /* [ body formals ], formals is comma separated list that needs to be parsed */
36242
36243 DUK_ASSERT_TOP(thr, 2);
36244
36245 /* XXX: this placeholder is not always correct, but use for now.
36246 * It will fail in corner cases; see test-dev-func-cons-args.js.
36247 */
36248 duk_push_literal(thr, "function(");
36249 duk_dup_1(thr);
36250 duk_push_literal(thr, "){");
36251 duk_dup_0(thr);
36252 duk_push_literal(thr, "\n}"); /* Newline is important to handle trailing // comment. */
36253 duk_concat(thr, 5);
36254
36255 /* [ body formals source ] */
36256
36257 DUK_ASSERT_TOP(thr, 3);
36258
36259 /* strictness is not inherited, intentional */
36260 comp_flags = DUK_COMPILE_FUNCEXPR;
36261
36262 duk_push_hstring_stridx(thr, DUK_STRIDX_COMPILE); /* XXX: copy from caller? */ /* XXX: ignored now */
36263 h_sourcecode = duk_require_hstring(thr, -2); /* no symbol check needed; -2 is concat'd code */
36264 duk_js_compile(thr,
36265 (const duk_uint8_t *) DUK_HSTRING_GET_DATA(h_sourcecode),
36266 (duk_size_t) DUK_HSTRING_GET_BYTELEN(h_sourcecode),
36267 comp_flags);
36268
36269 /* Force .name to 'anonymous' (ES2015). */
36270 duk_push_literal(thr, "anonymous");
36272
36273 func = (duk_hcompfunc *) duk_known_hobject(thr, -1);
36276
36277 /* [ body formals source template ] */
36278
36279 /* only outer_lex_env matters, as functions always get a new
36280 * variable declaration environment.
36281 */
36282
36283 outer_lex_env = thr->builtins[DUK_BIDX_GLOBAL_ENV];
36284 outer_var_env = thr->builtins[DUK_BIDX_GLOBAL_ENV];
36285
36286 duk_js_push_closure(thr, func, outer_var_env, outer_lex_env, 1 /*add_auto_proto*/);
36287
36288 /* [ body formals source template closure ] */
36289
36290 return 1;
36291}
36292#endif /* DUK_USE_FUNCTION_BUILTIN */
36293
36294#if defined(DUK_USE_FUNCTION_BUILTIN)
36296 duk_tval *tv;
36297
36298 /*
36299 * E5 Section 15.3.4.2 places few requirements on the output of
36300 * this function: the result is implementation dependent, must
36301 * follow FunctionDeclaration syntax (in particular, must have a
36302 * name even for anonymous functions or functions with empty name).
36303 * The output does NOT need to compile into anything useful.
36304 *
36305 * E6 Section 19.2.3.5 changes the requirements completely: the
36306 * result must either eval() to a functionally equivalent object
36307 * OR eval() to a SyntaxError.
36308 *
36309 * We opt for the SyntaxError approach for now, with a syntax that
36310 * mimics V8's native function syntax:
36311 *
36312 * 'function cos() { [native code] }'
36313 *
36314 * but extended with [ecmascript code], [bound code], and
36315 * [lightfunc code].
36316 */
36317
36318 duk_push_this(thr);
36319 tv = DUK_GET_TVAL_NEGIDX(thr, -1);
36320 DUK_ASSERT(tv != NULL);
36321
36322 if (DUK_TVAL_IS_OBJECT(tv)) {
36324 const char *func_name;
36325
36326 /* Function name: missing/undefined is mapped to empty string,
36327 * otherwise coerce to string. No handling for invalid identifier
36328 * characters or e.g. '{' in the function name. This doesn't
36329 * really matter as long as a SyntaxError results. Technically
36330 * if the name contained a suitable prefix followed by '//' it
36331 * might cause the result to parse without error.
36332 */
36334 if (duk_is_undefined(thr, -1)) {
36335 func_name = "";
36336 } else {
36337 func_name = duk_to_string(thr, -1);
36338 DUK_ASSERT(func_name != NULL);
36339 }
36340
36341 if (DUK_HOBJECT_IS_COMPFUNC(obj)) {
36342 duk_push_sprintf(thr, "function %s() { [ecmascript code] }", (const char *) func_name);
36343 } else if (DUK_HOBJECT_IS_NATFUNC(obj)) {
36344 duk_push_sprintf(thr, "function %s() { [native code] }", (const char *) func_name);
36345 } else if (DUK_HOBJECT_IS_BOUNDFUNC(obj)) {
36346 duk_push_sprintf(thr, "function %s() { [bound code] }", (const char *) func_name);
36347 } else {
36348 goto type_error;
36349 }
36350 } else if (DUK_TVAL_IS_LIGHTFUNC(tv)) {
36352 } else {
36353 goto type_error;
36355
36356 return 1;
36357
36358type_error:
36360}
36361#endif
36363/* Always present because the native function pointer is needed in call
36364 * handling.
36365 */
36367 /* .call() is dealt with in call handling by simulating its
36368 * effects so this function is actually never called.
36369 */
36370 DUK_UNREF(thr);
36371 return DUK_RET_TYPE_ERROR;
36372}
36373
36375 /* Like .call(), never actually called. */
36376 DUK_UNREF(thr);
36377 return DUK_RET_TYPE_ERROR;
36378}
36379
36381 /* Like .call(), never actually called. */
36382 DUK_UNREF(thr);
36383 return DUK_RET_TYPE_ERROR;
36384}
36385
36387 /* Like .call(), never actually called. */
36388 DUK_UNREF(thr);
36389 return DUK_RET_TYPE_ERROR;
36390}
36391
36392#if defined(DUK_USE_FUNCTION_BUILTIN)
36393/* Create a bound function which points to a target function which may
36394 * be bound or non-bound. If the target is bound, the argument lists
36395 * and 'this' binding of the functions are merged and the resulting
36396 * function points directly to the non-bound target.
36397 */
36399 duk_hboundfunc *h_bound;
36400 duk_idx_t nargs; /* bound args, not counting 'this' binding */
36401 duk_idx_t bound_nargs;
36402 duk_int_t bound_len;
36403 duk_tval *tv_prevbound;
36404 duk_idx_t n_prevbound;
36405 duk_tval *tv_res;
36406 duk_tval *tv_tmp;
36407
36408 /* XXX: C API call, e.g. duk_push_bound_function(thr, target_idx, nargs); */
36409
36410 /* Vararg function, careful arg handling, e.g. thisArg may not
36411 * be present.
36412 */
36413 nargs = duk_get_top(thr) - 1; /* actual args, not counting 'this' binding */
36414 if (nargs < 0) {
36415 nargs++;
36416 duk_push_undefined(thr);
36417 }
36418 DUK_ASSERT(nargs >= 0);
36419
36420 /* Limit 'nargs' for bound functions to guarantee arithmetic
36421 * below will never wrap.
36422 */
36423 if (nargs > (duk_idx_t) DUK_HBOUNDFUNC_MAX_ARGS) {
36425 }
36426
36427 duk_push_this(thr);
36428 duk_require_callable(thr, -1);
36429
36430 /* [ thisArg arg1 ... argN func ] (thisArg+args == nargs+1 total) */
36431 DUK_ASSERT_TOP(thr, nargs + 2);
36432
36433 /* Create bound function object. */
36434 h_bound = duk_push_hboundfunc(thr);
36437 DUK_ASSERT(h_bound->args == NULL);
36438 DUK_ASSERT(h_bound->nargs == 0);
36439 DUK_ASSERT(DUK_HOBJECT_GET_PROTOTYPE(thr->heap, (duk_hobject *) h_bound) == NULL);
36440
36441 /* [ thisArg arg1 ... argN func boundFunc ] */
36442
36443 /* If the target is a bound function, argument lists must be
36444 * merged. The 'this' binding closest to the target function
36445 * wins because in call handling the 'this' gets replaced over
36446 * and over again until we call the non-bound function.
36447 */
36448 tv_prevbound = NULL;
36449 n_prevbound = 0;
36450 tv_tmp = DUK_GET_TVAL_POSIDX(thr, 0);
36451 DUK_TVAL_SET_TVAL(&h_bound->this_binding, tv_tmp);
36452 tv_tmp = DUK_GET_TVAL_NEGIDX(thr, -2);
36453 DUK_TVAL_SET_TVAL(&h_bound->target, tv_tmp);
36454
36455 if (DUK_TVAL_IS_OBJECT(tv_tmp)) {
36456 duk_hobject *h_target;
36457 duk_hobject *bound_proto;
36458
36459 h_target = DUK_TVAL_GET_OBJECT(tv_tmp);
36461
36462 /* Internal prototype must be copied from the target.
36463 * For lightfuncs Function.prototype is used and is already
36464 * in place.
36465 */
36466 bound_proto = DUK_HOBJECT_GET_PROTOTYPE(thr->heap, h_target);
36467 DUK_HOBJECT_SET_PROTOTYPE_INIT_INCREF(thr, (duk_hobject *) h_bound, bound_proto);
36468
36469 /* The 'strict' flag is copied to get the special [[Get]] of E5.1
36470 * Section 15.3.5.4 to apply when a 'caller' value is a strict bound
36471 * function. Not sure if this is correct, because the specification
36472 * is a bit ambiguous on this point but it would make sense.
36473 */
36474 /* Strictness is inherited from target. */
36475 if (DUK_HOBJECT_HAS_STRICT(h_target)) {
36477 }
36478
36479 if (DUK_HOBJECT_HAS_BOUNDFUNC(h_target)) {
36480 duk_hboundfunc *h_boundtarget;
36481
36482 h_boundtarget = (duk_hboundfunc *) (void *) h_target;
36483
36484 /* The final function should always be non-bound, unless
36485 * there's a bug in the internals. Assert for it.
36486 */
36487 DUK_ASSERT(DUK_TVAL_IS_LIGHTFUNC(&h_boundtarget->target) ||
36488 (DUK_TVAL_IS_OBJECT(&h_boundtarget->target) &&
36491
36492 DUK_TVAL_SET_TVAL(&h_bound->target, &h_boundtarget->target);
36493 DUK_TVAL_SET_TVAL(&h_bound->this_binding, &h_boundtarget->this_binding);
36494
36495 tv_prevbound = h_boundtarget->args;
36496 n_prevbound = h_boundtarget->nargs;
36497 }
36498 } else {
36499 /* Lightfuncs are always strict. */
36500 duk_hobject *bound_proto;
36501
36504 bound_proto = thr->builtins[DUK_BIDX_FUNCTION_PROTOTYPE];
36505 DUK_HOBJECT_SET_PROTOTYPE_INIT_INCREF(thr, (duk_hobject *) h_bound, bound_proto);
36506 }
36507
36508 DUK_TVAL_INCREF(thr, &h_bound->target); /* old values undefined, no decref needed */
36509 DUK_TVAL_INCREF(thr, &h_bound->this_binding);
36510
36511 bound_nargs = n_prevbound + nargs;
36512 if (bound_nargs > (duk_idx_t) DUK_HBOUNDFUNC_MAX_ARGS) {
36514 }
36515 tv_res = (duk_tval *) DUK_ALLOC_CHECKED(thr, ((duk_size_t) bound_nargs) * sizeof(duk_tval));
36516 DUK_ASSERT(tv_res != NULL || bound_nargs == 0);
36517 DUK_ASSERT(h_bound->args == NULL);
36518 DUK_ASSERT(h_bound->nargs == 0);
36519 h_bound->args = tv_res;
36520 h_bound->nargs = bound_nargs;
36521
36522 DUK_ASSERT(n_prevbound >= 0);
36523 duk_copy_tvals_incref(thr, tv_res, tv_prevbound, (duk_size_t) n_prevbound);
36524 DUK_ASSERT(nargs >= 0);
36525 duk_copy_tvals_incref(thr, tv_res + n_prevbound, DUK_GET_TVAL_POSIDX(thr, 1), (duk_size_t) nargs);
36526
36527 /* [ thisArg arg1 ... argN func boundFunc ] */
36528
36529 /* Bound function 'length' property is interesting.
36530 * For lightfuncs, simply read the virtual property.
36531 */
36533 bound_len = duk_get_int(thr, -1); /* ES2015: no coercion */
36534 if (bound_len < nargs) {
36535 bound_len = 0;
36536 } else {
36537 bound_len -= nargs;
36538 }
36539 if (sizeof(duk_int_t) > 4 && bound_len > (duk_int_t) DUK_UINT32_MAX) {
36540 bound_len = (duk_int_t) DUK_UINT32_MAX;
36541 }
36542 duk_pop(thr);
36543 DUK_ASSERT(bound_len >= 0);
36544 tv_tmp = thr->valstack_top++;
36547 DUK_TVAL_SET_U32(tv_tmp, (duk_uint32_t) bound_len); /* in-place update, fastint */
36548 duk_xdef_prop_stridx_short(thr, -2, DUK_STRIDX_LENGTH, DUK_PROPDESC_FLAGS_C); /* attrs in E6 Section 9.2.4 */
36549
36550 /* XXX: could these be virtual? */
36551 /* Caller and arguments must use the same thrower, [[ThrowTypeError]]. */
36554
36555 /* Function name and fileName (non-standard). */
36556 duk_push_literal(thr, "bound "); /* ES2015 19.2.3.2. */
36558 if (!duk_is_string_notsymbol(thr, -1)) {
36559 /* ES2015 has requirement to check that .name of target is a string
36560 * (also must check for Symbol); if not, targetName should be the
36561 * empty string. ES2015 19.2.3.2.
36562 */
36563 duk_pop(thr);
36565 }
36566 duk_concat(thr, 2);
36568#if defined(DUK_USE_FUNC_FILENAME_PROPERTY)
36571#endif
36572
36573 DUK_DDD(DUK_DDDPRINT("created bound function: %!iT", (duk_tval *) duk_get_tval(thr, -1)));
36574
36575 return 1;
36576}
36577#endif /* DUK_USE_FUNCTION_BUILTIN */
36578
36579/* %NativeFunctionPrototype% .length getter. */
36581 duk_tval *tv;
36582 duk_hnatfunc *h;
36583 duk_int16_t func_nargs;
36584
36586 DUK_ASSERT(tv != NULL);
36587
36588 if (DUK_TVAL_IS_OBJECT(tv)) {
36590 DUK_ASSERT(h != NULL);
36591 if (!DUK_HOBJECT_IS_NATFUNC((duk_hobject *) h)) {
36592 goto fail_type;
36593 }
36594 func_nargs = h->nargs;
36595 duk_push_int(thr, func_nargs == DUK_HNATFUNC_NARGS_VARARGS ? 0 : func_nargs);
36596 } else if (DUK_TVAL_IS_LIGHTFUNC(tv)) {
36597 duk_small_uint_t lf_flags;
36598 duk_small_uint_t lf_len;
36599
36600 lf_flags = DUK_TVAL_GET_LIGHTFUNC_FLAGS(tv);
36601 lf_len = DUK_LFUNC_FLAGS_GET_LENGTH(lf_flags);
36602 duk_push_uint(thr, lf_len);
36603 } else {
36604 goto fail_type;
36605 }
36606 return 1;
36607
36608fail_type:
36610}
36611
36612/* %NativeFunctionPrototype% .name getter. */
36614 duk_tval *tv;
36615 duk_hnatfunc *h;
36616
36618 DUK_ASSERT(tv != NULL);
36619
36620 if (DUK_TVAL_IS_OBJECT(tv)) {
36622 DUK_ASSERT(h != NULL);
36623 if (!DUK_HOBJECT_IS_NATFUNC((duk_hobject *) h)) {
36624 goto fail_type;
36625 }
36626#if 0
36627 duk_push_hnatfunc_name(thr, h);
36628#endif
36630 } else if (DUK_TVAL_IS_LIGHTFUNC(tv)) {
36631 duk_push_lightfunc_name(thr, tv);
36632 } else {
36633 goto fail_type;
36634 }
36635 return 1;
36636
36637fail_type:
36639}
36640
36641#if defined(DUK_USE_SYMBOL_BUILTIN)
36643 /* This binding: RHS, stack index 0: LHS. */
36644 duk_bool_t ret;
36645
36647 duk_push_boolean(thr, ret);
36648 return 1;
36649}
36650#endif /* DUK_USE_SYMBOL_BUILTIN */
36651/*
36652 * Global object built-ins
36653 */
36654
36655/* #include duk_internal.h -> already included */
36656
36658 * Encoding/decoding helpers
36660
36661/* XXX: Could add fast path (for each transform callback) with direct byte
36662 * lookups (no shifting) and no explicit check for x < 0x80 before table
36663 * lookup.
36664 */
36665
36666/* Macros for creating and checking bitmasks for character encoding.
36667 * Bit number is a bit counterintuitive, but minimizes code size.
36668 */
36669#define DUK__MKBITS(a, b, c, d, e, f, g, h) \
36670 ((duk_uint8_t) (((a) << 0) | ((b) << 1) | ((c) << 2) | ((d) << 3) | ((e) << 4) | ((f) << 5) | ((g) << 6) | ((h) << 7)))
36671#define DUK__CHECK_BITMASK(table, cp) ((table)[(cp) >> 3] & (1 << ((cp) &0x07)))
36672
36673/* E5.1 Section 15.1.3.3: uriReserved + uriUnescaped + '#' */
36675 DUK__MKBITS(0, 0, 0, 0, 0, 0, 0, 0), DUK__MKBITS(0, 0, 0, 0, 0, 0, 0, 0), /* 0x00-0x0f */
36676 DUK__MKBITS(0, 0, 0, 0, 0, 0, 0, 0), DUK__MKBITS(0, 0, 0, 0, 0, 0, 0, 0), /* 0x10-0x1f */
36677 DUK__MKBITS(0, 1, 0, 1, 1, 0, 1, 1), DUK__MKBITS(1, 1, 1, 1, 1, 1, 1, 1), /* 0x20-0x2f */
36678 DUK__MKBITS(1, 1, 1, 1, 1, 1, 1, 1), DUK__MKBITS(1, 1, 1, 1, 0, 1, 0, 1), /* 0x30-0x3f */
36679 DUK__MKBITS(1, 1, 1, 1, 1, 1, 1, 1), DUK__MKBITS(1, 1, 1, 1, 1, 1, 1, 1), /* 0x40-0x4f */
36680 DUK__MKBITS(1, 1, 1, 1, 1, 1, 1, 1), DUK__MKBITS(1, 1, 1, 0, 0, 0, 0, 1), /* 0x50-0x5f */
36681 DUK__MKBITS(0, 1, 1, 1, 1, 1, 1, 1), DUK__MKBITS(1, 1, 1, 1, 1, 1, 1, 1), /* 0x60-0x6f */
36682 DUK__MKBITS(1, 1, 1, 1, 1, 1, 1, 1), DUK__MKBITS(1, 1, 1, 0, 0, 0, 1, 0), /* 0x70-0x7f */
36683};
36684
36685/* E5.1 Section 15.1.3.4: uriUnescaped */
36687 DUK__MKBITS(0, 0, 0, 0, 0, 0, 0, 0), DUK__MKBITS(0, 0, 0, 0, 0, 0, 0, 0), /* 0x00-0x0f */
36688 DUK__MKBITS(0, 0, 0, 0, 0, 0, 0, 0), DUK__MKBITS(0, 0, 0, 0, 0, 0, 0, 0), /* 0x10-0x1f */
36689 DUK__MKBITS(0, 1, 0, 0, 0, 0, 0, 1), DUK__MKBITS(1, 1, 1, 0, 0, 1, 1, 0), /* 0x20-0x2f */
36690 DUK__MKBITS(1, 1, 1, 1, 1, 1, 1, 1), DUK__MKBITS(1, 1, 0, 0, 0, 0, 0, 0), /* 0x30-0x3f */
36691 DUK__MKBITS(0, 1, 1, 1, 1, 1, 1, 1), DUK__MKBITS(1, 1, 1, 1, 1, 1, 1, 1), /* 0x40-0x4f */
36692 DUK__MKBITS(1, 1, 1, 1, 1, 1, 1, 1), DUK__MKBITS(1, 1, 1, 0, 0, 0, 0, 1), /* 0x50-0x5f */
36693 DUK__MKBITS(0, 1, 1, 1, 1, 1, 1, 1), DUK__MKBITS(1, 1, 1, 1, 1, 1, 1, 1), /* 0x60-0x6f */
36694 DUK__MKBITS(1, 1, 1, 1, 1, 1, 1, 1), DUK__MKBITS(1, 1, 1, 0, 0, 0, 1, 0), /* 0x70-0x7f */
36695};
36696
36697/* E5.1 Section 15.1.3.1: uriReserved + '#' */
36699 DUK__MKBITS(0, 0, 0, 0, 0, 0, 0, 0), DUK__MKBITS(0, 0, 0, 0, 0, 0, 0, 0), /* 0x00-0x0f */
36700 DUK__MKBITS(0, 0, 0, 0, 0, 0, 0, 0), DUK__MKBITS(0, 0, 0, 0, 0, 0, 0, 0), /* 0x10-0x1f */
36701 DUK__MKBITS(0, 0, 0, 1, 1, 0, 1, 0), DUK__MKBITS(0, 0, 0, 1, 1, 0, 0, 1), /* 0x20-0x2f */
36702 DUK__MKBITS(0, 0, 0, 0, 0, 0, 0, 0), DUK__MKBITS(0, 0, 1, 1, 0, 1, 0, 1), /* 0x30-0x3f */
36703 DUK__MKBITS(1, 0, 0, 0, 0, 0, 0, 0), DUK__MKBITS(0, 0, 0, 0, 0, 0, 0, 0), /* 0x40-0x4f */
36704 DUK__MKBITS(0, 0, 0, 0, 0, 0, 0, 0), DUK__MKBITS(0, 0, 0, 0, 0, 0, 0, 0), /* 0x50-0x5f */
36705 DUK__MKBITS(0, 0, 0, 0, 0, 0, 0, 0), DUK__MKBITS(0, 0, 0, 0, 0, 0, 0, 0), /* 0x60-0x6f */
36706 DUK__MKBITS(0, 0, 0, 0, 0, 0, 0, 0), DUK__MKBITS(0, 0, 0, 0, 0, 0, 0, 0), /* 0x70-0x7f */
36707};
36708
36709/* E5.1 Section 15.1.3.2: empty */
36711 DUK__MKBITS(0, 0, 0, 0, 0, 0, 0, 0), DUK__MKBITS(0, 0, 0, 0, 0, 0, 0, 0), /* 0x00-0x0f */
36712 DUK__MKBITS(0, 0, 0, 0, 0, 0, 0, 0), DUK__MKBITS(0, 0, 0, 0, 0, 0, 0, 0), /* 0x10-0x1f */
36713 DUK__MKBITS(0, 0, 0, 0, 0, 0, 0, 0), DUK__MKBITS(0, 0, 0, 0, 0, 0, 0, 0), /* 0x20-0x2f */
36714 DUK__MKBITS(0, 0, 0, 0, 0, 0, 0, 0), DUK__MKBITS(0, 0, 0, 0, 0, 0, 0, 0), /* 0x30-0x3f */
36715 DUK__MKBITS(0, 0, 0, 0, 0, 0, 0, 0), DUK__MKBITS(0, 0, 0, 0, 0, 0, 0, 0), /* 0x40-0x4f */
36716 DUK__MKBITS(0, 0, 0, 0, 0, 0, 0, 0), DUK__MKBITS(0, 0, 0, 0, 0, 0, 0, 0), /* 0x50-0x5f */
36717 DUK__MKBITS(0, 0, 0, 0, 0, 0, 0, 0), DUK__MKBITS(0, 0, 0, 0, 0, 0, 0, 0), /* 0x60-0x6f */
36718 DUK__MKBITS(0, 0, 0, 0, 0, 0, 0, 0), DUK__MKBITS(0, 0, 0, 0, 0, 0, 0, 0), /* 0x70-0x7f */
36719};
36720
36721#if defined(DUK_USE_SECTION_B)
36722/* E5.1 Section B.2.2, step 7. */
36724 DUK__MKBITS(0, 0, 0, 0, 0, 0, 0, 0), DUK__MKBITS(0, 0, 0, 0, 0, 0, 0, 0), /* 0x00-0x0f */
36725 DUK__MKBITS(0, 0, 0, 0, 0, 0, 0, 0), DUK__MKBITS(0, 0, 0, 0, 0, 0, 0, 0), /* 0x10-0x1f */
36726 DUK__MKBITS(0, 0, 0, 0, 0, 0, 0, 0), DUK__MKBITS(0, 0, 1, 1, 0, 1, 1, 1), /* 0x20-0x2f */
36727 DUK__MKBITS(1, 1, 1, 1, 1, 1, 1, 1), DUK__MKBITS(1, 1, 0, 0, 0, 0, 0, 0), /* 0x30-0x3f */
36728 DUK__MKBITS(1, 1, 1, 1, 1, 1, 1, 1), DUK__MKBITS(1, 1, 1, 1, 1, 1, 1, 1), /* 0x40-0x4f */
36729 DUK__MKBITS(1, 1, 1, 1, 1, 1, 1, 1), DUK__MKBITS(1, 1, 1, 0, 0, 0, 0, 1), /* 0x50-0x5f */
36730 DUK__MKBITS(0, 1, 1, 1, 1, 1, 1, 1), DUK__MKBITS(1, 1, 1, 1, 1, 1, 1, 1), /* 0x60-0x6f */
36731 DUK__MKBITS(1, 1, 1, 1, 1, 1, 1, 1), DUK__MKBITS(1, 1, 1, 0, 0, 0, 0, 0) /* 0x70-0x7f */
36733#endif /* DUK_USE_SECTION_B */
36734
36735typedef struct {
36736 duk_hthread *thr;
36737 duk_hstring *h_str;
36739 const duk_uint8_t *p;
36740 const duk_uint8_t *p_start;
36741 const duk_uint8_t *p_end;
36743
36744typedef void (*duk__transform_callback)(duk__transform_context *tfm_ctx, const void *udata, duk_codepoint_t cp);
36745
36746/* XXX: refactor and share with other code */
36748 duk_small_int_t ch;
36749 duk_small_int_t t = 0;
36750
36751 while (n > 0) {
36752 t = t * 16;
36753 ch = (duk_small_int_t) duk_hex_dectab[*p++];
36754 if (DUK_LIKELY(ch >= 0)) {
36755 t += ch;
36756 } else {
36757 return -1;
36758 }
36759 n--;
36760 }
36761 return t;
36762}
36763
36764DUK_LOCAL int duk__transform_helper(duk_hthread *thr, duk__transform_callback callback, const void *udata) {
36765 duk__transform_context tfm_ctx_alloc;
36766 duk__transform_context *tfm_ctx = &tfm_ctx_alloc;
36767 duk_codepoint_t cp;
36768
36769 tfm_ctx->thr = thr;
36770
36771 tfm_ctx->h_str = duk_to_hstring(thr, 0);
36772 DUK_ASSERT(tfm_ctx->h_str != NULL);
36773
36774 DUK_BW_INIT_PUSHBUF(thr, &tfm_ctx->bw, DUK_HSTRING_GET_BYTELEN(tfm_ctx->h_str)); /* initial size guess */
36775
36776 tfm_ctx->p_start = DUK_HSTRING_GET_DATA(tfm_ctx->h_str);
36777 tfm_ctx->p_end = tfm_ctx->p_start + DUK_HSTRING_GET_BYTELEN(tfm_ctx->h_str);
36778 tfm_ctx->p = tfm_ctx->p_start;
36780 while (tfm_ctx->p < tfm_ctx->p_end) {
36781 cp = (duk_codepoint_t) duk_unicode_decode_xutf8_checked(thr, &tfm_ctx->p, tfm_ctx->p_start, tfm_ctx->p_end);
36782 callback(tfm_ctx, udata, cp);
36783 }
36784
36785 DUK_BW_COMPACT(thr, &tfm_ctx->bw);
36786
36787 (void) duk_buffer_to_string(thr, -1); /* Safe if transform is safe. */
36788 return 1;
36789}
36790
36792 duk_uint8_t xutf8_buf[DUK_UNICODE_MAX_XUTF8_LENGTH];
36793 duk_small_int_t len;
36794 duk_codepoint_t cp1, cp2;
36795 duk_small_int_t i, t;
36796 const duk_uint8_t *unescaped_table = (const duk_uint8_t *) udata;
36797
36798 /* UTF-8 encoded bytes escaped as %xx%xx%xx... -> 3 * nbytes.
36799 * Codepoint range is restricted so this is a slightly too large
36800 * but doesn't matter.
36801 */
36802 DUK_BW_ENSURE(tfm_ctx->thr, &tfm_ctx->bw, 3 * DUK_UNICODE_MAX_XUTF8_LENGTH);
36803
36804 if (cp < 0) {
36805 goto uri_error;
36806 } else if ((cp < 0x80L) && DUK__CHECK_BITMASK(unescaped_table, cp)) {
36807 DUK_BW_WRITE_RAW_U8(tfm_ctx->thr, &tfm_ctx->bw, (duk_uint8_t) cp);
36808 return;
36809 } else if (cp >= 0xdc00L && cp <= 0xdfffL) {
36810 goto uri_error;
36811 } else if (cp >= 0xd800L && cp <= 0xdbffL) {
36812 /* Needs lookahead */
36813 if (duk_unicode_decode_xutf8(tfm_ctx->thr,
36814 &tfm_ctx->p,
36815 tfm_ctx->p_start,
36816 tfm_ctx->p_end,
36817 (duk_ucodepoint_t *) &cp2) == 0) {
36818 goto uri_error;
36819 }
36820 if (!(cp2 >= 0xdc00L && cp2 <= 0xdfffL)) {
36821 goto uri_error;
36822 }
36823 cp1 = cp;
36824 cp = (duk_codepoint_t) (((cp1 - 0xd800L) << 10) + (cp2 - 0xdc00L) + 0x10000L);
36825 } else if (cp > 0x10ffffL) {
36826 /* Although we can allow non-BMP characters (they'll decode
36827 * back into surrogate pairs), we don't allow extended UTF-8
36828 * characters; they would encode to URIs which won't decode
36829 * back because of strict UTF-8 checks in URI decoding.
36830 * (However, we could just as well allow them here.)
36831 */
36832 goto uri_error;
36833 } else {
36834 /* Non-BMP characters within valid UTF-8 range: encode as is.
36835 * They'll decode back into surrogate pairs if the escaped
36836 * output is decoded.
36837 */
36838 ;
36839 }
36840
36841 len = duk_unicode_encode_xutf8((duk_ucodepoint_t) cp, xutf8_buf);
36842 for (i = 0; i < len; i++) {
36843 t = (duk_small_int_t) xutf8_buf[i];
36844 DUK_BW_WRITE_RAW_U8_3(tfm_ctx->thr,
36845 &tfm_ctx->bw,
36847 (duk_uint8_t) duk_uc_nybbles[t >> 4],
36848 (duk_uint8_t) duk_uc_nybbles[t & 0x0f]);
36849 }
36850
36851 return;
36852
36853uri_error:
36855 DUK_WO_NORETURN(return;);
36856}
36857
36859 const duk_uint8_t *reserved_table = (const duk_uint8_t *) udata;
36860 duk_small_uint_t utf8_blen;
36861 duk_codepoint_t min_cp;
36862 duk_small_int_t t; /* must be signed */
36864
36865 /* Maximum write size: XUTF8 path writes max DUK_UNICODE_MAX_XUTF8_LENGTH,
36866 * percent escape path writes max two times CESU-8 encoded BMP length.
36867 */
36868 DUK_BW_ENSURE(tfm_ctx->thr,
36869 &tfm_ctx->bw,
36872
36873 if (cp == (duk_codepoint_t) '%') {
36874 const duk_uint8_t *p = tfm_ctx->p;
36875 duk_size_t left = (duk_size_t) (tfm_ctx->p_end - p); /* bytes left */
36876
36877 DUK_DDD(DUK_DDDPRINT("percent encoding, left=%ld", (long) left));
36878
36879 if (left < 2) {
36880 goto uri_error;
36881 }
36882
36883 t = duk__decode_hex_escape(p, 2);
36884 DUK_DDD(DUK_DDDPRINT("first byte: %ld", (long) t));
36885 if (t < 0) {
36886 goto uri_error;
36887 }
36888
36889 if (t < 0x80) {
36890 if (DUK__CHECK_BITMASK(reserved_table, t)) {
36891 /* decode '%xx' to '%xx' if decoded char in reserved set */
36892 DUK_ASSERT(tfm_ctx->p - 1 >= tfm_ctx->p_start);
36893 DUK_BW_WRITE_RAW_U8_3(tfm_ctx->thr, &tfm_ctx->bw, DUK_ASC_PERCENT, p[0], p[1]);
36894 } else {
36895 DUK_BW_WRITE_RAW_U8(tfm_ctx->thr, &tfm_ctx->bw, (duk_uint8_t) t);
36896 }
36897 tfm_ctx->p += 2;
36898 return;
36899 }
36900
36901 /* Decode UTF-8 codepoint from a sequence of hex escapes. The
36902 * first byte of the sequence has been decoded to 't'.
36903 *
36904 * Note that UTF-8 validation must be strict according to the
36905 * specification: E5.1 Section 15.1.3, decode algorithm step
36906 * 4.d.vii.8. URIError from non-shortest encodings is also
36907 * specifically noted in the spec.
36908 */
36909
36910 DUK_ASSERT(t >= 0x80);
36911 if (t < 0xc0) {
36912 /* continuation byte */
36913 goto uri_error;
36914 } else if (t < 0xe0) {
36915 /* 110x xxxx; 2 bytes */
36916 utf8_blen = 2;
36917 min_cp = 0x80L;
36918 cp = t & 0x1f;
36919 } else if (t < 0xf0) {
36920 /* 1110 xxxx; 3 bytes */
36921 utf8_blen = 3;
36922 min_cp = 0x800L;
36923 cp = t & 0x0f;
36924 } else if (t < 0xf8) {
36925 /* 1111 0xxx; 4 bytes */
36926 utf8_blen = 4;
36927 min_cp = 0x10000L;
36928 cp = t & 0x07;
36929 } else {
36930 /* extended utf-8 not allowed for URIs */
36931 goto uri_error;
36932 }
36933
36934 if (left < utf8_blen * 3 - 1) {
36935 /* '%xx%xx...%xx', p points to char after first '%' */
36936 goto uri_error;
36937 }
36938
36939 p += 3;
36940 for (i = 1; i < utf8_blen; i++) {
36941 /* p points to digit part ('%xy', p points to 'x') */
36942 t = duk__decode_hex_escape(p, 2);
36943 DUK_DDD(DUK_DDDPRINT("i=%ld utf8_blen=%ld cp=%ld t=0x%02lx",
36944 (long) i,
36945 (long) utf8_blen,
36946 (long) cp,
36947 (unsigned long) t));
36948 if (t < 0) {
36949 goto uri_error;
36950 }
36951 if ((t & 0xc0) != 0x80) {
36952 goto uri_error;
36953 }
36954 cp = (cp << 6) + (t & 0x3f);
36955 p += 3;
36956 }
36957 p--; /* p overshoots */
36958 tfm_ctx->p = p;
36959
36960 DUK_DDD(DUK_DDDPRINT("final cp=%ld, min_cp=%ld", (long) cp, (long) min_cp));
36961
36962 if (cp < min_cp || cp > 0x10ffffL || (cp >= 0xd800L && cp <= 0xdfffL)) {
36963 goto uri_error;
36964 }
36965
36966 /* The E5.1 algorithm checks whether or not a decoded codepoint
36967 * is below 0x80 and perhaps may be in the "reserved" set.
36968 * This seems pointless because the single byte UTF-8 case is
36969 * handled separately, and non-shortest encodings are rejected.
36970 * So, 'cp' cannot be below 0x80 here, and thus cannot be in
36971 * the reserved set.
36972 */
36973
36974 /* utf-8 validation ensures these */
36975 DUK_ASSERT(cp >= 0x80L && cp <= 0x10ffffL);
36976
36977 if (cp >= 0x10000L) {
36978 cp -= 0x10000L;
36979 DUK_ASSERT(cp < 0x100000L);
36980
36981 DUK_BW_WRITE_RAW_XUTF8(tfm_ctx->thr, &tfm_ctx->bw, ((cp >> 10) + 0xd800L));
36982 DUK_BW_WRITE_RAW_XUTF8(tfm_ctx->thr, &tfm_ctx->bw, ((cp & 0x03ffL) + 0xdc00L));
36983 } else {
36984 DUK_BW_WRITE_RAW_XUTF8(tfm_ctx->thr, &tfm_ctx->bw, cp);
36986 } else {
36987 DUK_BW_WRITE_RAW_XUTF8(tfm_ctx->thr, &tfm_ctx->bw, cp);
36988 }
36989 return;
36990
36991uri_error:
36993 DUK_WO_NORETURN(return;);
36994}
36995
36996#if defined(DUK_USE_SECTION_B)
36998 DUK_UNREF(udata);
36999
37000 DUK_BW_ENSURE(tfm_ctx->thr, &tfm_ctx->bw, 6);
37001
37002 if (cp < 0) {
37003 goto esc_error;
37004 } else if ((cp < 0x80L) && DUK__CHECK_BITMASK(duk__escape_unescaped_table, cp)) {
37005 DUK_BW_WRITE_RAW_U8(tfm_ctx->thr, &tfm_ctx->bw, (duk_uint8_t) cp);
37006 } else if (cp < 0x100L) {
37007 DUK_BW_WRITE_RAW_U8_3(tfm_ctx->thr,
37008 &tfm_ctx->bw,
37009 (duk_uint8_t) DUK_ASC_PERCENT,
37010 (duk_uint8_t) duk_uc_nybbles[cp >> 4],
37011 (duk_uint8_t) duk_uc_nybbles[cp & 0x0f]);
37012 } else if (cp < 0x10000L) {
37013 DUK_BW_WRITE_RAW_U8_6(tfm_ctx->thr,
37014 &tfm_ctx->bw,
37015 (duk_uint8_t) DUK_ASC_PERCENT,
37016 (duk_uint8_t) DUK_ASC_LC_U,
37017 (duk_uint8_t) duk_uc_nybbles[cp >> 12],
37018 (duk_uint8_t) duk_uc_nybbles[(cp >> 8) & 0x0f],
37019 (duk_uint8_t) duk_uc_nybbles[(cp >> 4) & 0x0f],
37020 (duk_uint8_t) duk_uc_nybbles[cp & 0x0f]);
37021 } else {
37022 /* Characters outside BMP cannot be escape()'d. We could
37023 * encode them as surrogate pairs (for codepoints inside
37024 * valid UTF-8 range, but not extended UTF-8). Because
37025 * escape() and unescape() are legacy functions, we don't.
37026 */
37027 goto esc_error;
37028 }
37029
37030 return;
37031
37032esc_error:
37034 DUK_WO_NORETURN(return;);
37035}
37036
37039
37040 DUK_UNREF(udata);
37041
37042 if (cp == (duk_codepoint_t) '%') {
37043 const duk_uint8_t *p = tfm_ctx->p;
37044 duk_size_t left = (duk_size_t) (tfm_ctx->p_end - p); /* bytes left */
37045
37046 if (left >= 5 && p[0] == 'u' && ((t = duk__decode_hex_escape(p + 1, 4)) >= 0)) {
37047 cp = (duk_codepoint_t) t;
37048 tfm_ctx->p += 5;
37049 } else if (left >= 2 && ((t = duk__decode_hex_escape(p, 2)) >= 0)) {
37050 cp = (duk_codepoint_t) t;
37051 tfm_ctx->p += 2;
37052 }
37053 }
37054
37055 DUK_BW_WRITE_ENSURE_XUTF8(tfm_ctx->thr, &tfm_ctx->bw, cp);
37056}
37057#endif /* DUK_USE_SECTION_B */
37059/*
37060 * Eval
37061 *
37062 * Eval needs to handle both a "direct eval" and an "indirect eval".
37063 * Direct eval handling needs access to the caller's activation so that its
37064 * lexical environment can be accessed. A direct eval is only possible from
37065 * ECMAScript code; an indirect eval call is possible also from C code.
37066 * When an indirect eval call is made from C code, there may not be a
37067 * calling activation at all which needs careful handling.
37068 */
37069
37071 duk_hstring *h;
37072 duk_activation *act_caller;
37073 duk_activation *act_eval;
37074 duk_hcompfunc *func;
37075 duk_hobject *outer_lex_env;
37076 duk_hobject *outer_var_env;
37077 duk_bool_t this_to_global = 1;
37078 duk_small_uint_t comp_flags;
37079 duk_int_t level = -2;
37080 duk_small_uint_t call_flags;
37081
37082 DUK_ASSERT(duk_get_top(thr) == 1 || duk_get_top(thr) == 2); /* 2 when called by debugger */
37083 DUK_ASSERT(thr->callstack_top >= 1); /* at least this function exists */
37084 DUK_ASSERT(thr->callstack_curr != NULL);
37085 DUK_ASSERT((thr->callstack_curr->flags & DUK_ACT_FLAG_DIRECT_EVAL) == 0 || /* indirect eval */
37086 (thr->callstack_top >= 2)); /* if direct eval, calling activation must exist */
37087
37088 /*
37089 * callstack_top - 1 --> this function
37090 * callstack_top - 2 --> caller (may not exist)
37091 *
37092 * If called directly from C, callstack_top might be 1. If calling
37093 * activation doesn't exist, call must be indirect.
37094 */
37095
37096 h = duk_get_hstring_notsymbol(thr, 0);
37097 if (!h) {
37098 /* Symbol must be returned as is, like any non-string values. */
37099 return 1; /* return arg as-is */
37100 }
37101
37102#if defined(DUK_USE_DEBUGGER_SUPPORT)
37103 /* NOTE: level is used only by the debugger and should never be present
37104 * for an ECMAScript eval().
37105 */
37106 DUK_ASSERT(level == -2); /* by default, use caller's environment */
37107 if (duk_get_top(thr) >= 2 && duk_is_number(thr, 1)) {
37108 level = duk_get_int(thr, 1);
37109 }
37110 DUK_ASSERT(level <= -2); /* This is guaranteed by debugger code. */
37111#endif
37112
37113 /* [ source ] */
37114
37115 comp_flags = DUK_COMPILE_EVAL;
37116 act_eval = thr->callstack_curr; /* this function */
37117 DUK_ASSERT(act_eval != NULL);
37118 act_caller = duk_hthread_get_activation_for_level(thr, level);
37119 if (act_caller != NULL) {
37120 /* Have a calling activation, check for direct eval (otherwise
37121 * assume indirect eval.
37122 */
37123 if ((act_caller->flags & DUK_ACT_FLAG_STRICT) && (act_eval->flags & DUK_ACT_FLAG_DIRECT_EVAL)) {
37124 /* Only direct eval inherits strictness from calling code
37125 * (E5.1 Section 10.1.1).
37126 */
37127 comp_flags |= DUK_COMPILE_STRICT;
37128 }
37129 } else {
37130 DUK_ASSERT((act_eval->flags & DUK_ACT_FLAG_DIRECT_EVAL) == 0);
37131 }
37132
37133 duk_push_hstring_stridx(thr, DUK_STRIDX_INPUT); /* XXX: copy from caller? */
37134 duk_js_compile(thr, (const duk_uint8_t *) DUK_HSTRING_GET_DATA(h), (duk_size_t) DUK_HSTRING_GET_BYTELEN(h), comp_flags);
37135 func = (duk_hcompfunc *) duk_known_hobject(thr, -1);
37137
37138 /* [ source template ] */
37139
37140 /* E5 Section 10.4.2 */
37141
37142 if (act_eval->flags & DUK_ACT_FLAG_DIRECT_EVAL) {
37143 DUK_ASSERT(thr->callstack_top >= 2);
37144 DUK_ASSERT(act_caller != NULL);
37145 if (act_caller->lex_env == NULL) {
37146 DUK_ASSERT(act_caller->var_env == NULL);
37147 DUK_DDD(DUK_DDDPRINT("delayed environment initialization"));
37148
37149 /* this may have side effects, so re-lookup act */
37151 }
37152 DUK_ASSERT(act_caller->lex_env != NULL);
37153 DUK_ASSERT(act_caller->var_env != NULL);
37154
37155 this_to_global = 0;
37156
37157 if (DUK_HOBJECT_HAS_STRICT((duk_hobject *) func)) {
37158 duk_hdecenv *new_env;
37159 duk_hobject *act_lex_env;
37160
37161 DUK_DDD(DUK_DDDPRINT("direct eval call to a strict function -> "
37162 "var_env and lex_env to a fresh env, "
37163 "this_binding to caller's this_binding"));
37164
37165 act_lex_env = act_caller->lex_env;
37166
37167 new_env =
37170 DUK_ASSERT(new_env != NULL);
37171 duk_push_hobject(thr, (duk_hobject *) new_env);
37172
37173 DUK_ASSERT(DUK_HOBJECT_GET_PROTOTYPE(thr->heap, (duk_hobject *) new_env) == NULL);
37174 DUK_HOBJECT_SET_PROTOTYPE(thr->heap, (duk_hobject *) new_env, act_lex_env);
37175 DUK_HOBJECT_INCREF_ALLOWNULL(thr, act_lex_env);
37176 DUK_DDD(DUK_DDDPRINT("new_env allocated: %!iO", (duk_heaphdr *) new_env));
37177
37178 outer_lex_env = (duk_hobject *) new_env;
37179 outer_var_env = (duk_hobject *) new_env;
37180
37181 duk_insert(thr, 0); /* stash to bottom of value stack to keep new_env reachable for duration of eval */
37182
37183 /* compiler's responsibility */
37185 } else {
37186 DUK_DDD(DUK_DDDPRINT("direct eval call to a non-strict function -> "
37187 "var_env and lex_env to caller's envs, "
37188 "this_binding to caller's this_binding"));
37189
37190 outer_lex_env = act_caller->lex_env;
37191 outer_var_env = act_caller->var_env;
37192
37193 /* compiler's responsibility */
37195 }
37196 } else {
37197 DUK_DDD(DUK_DDDPRINT("indirect eval call -> var_env and lex_env to "
37198 "global object, this_binding to global object"));
37199
37200 this_to_global = 1;
37201 outer_lex_env = thr->builtins[DUK_BIDX_GLOBAL_ENV];
37202 outer_var_env = thr->builtins[DUK_BIDX_GLOBAL_ENV];
37203 }
37204
37205 /* Eval code doesn't need an automatic .prototype object. */
37206 duk_js_push_closure(thr, func, outer_var_env, outer_lex_env, 0 /*add_auto_proto*/);
37207
37208 /* [ env? source template closure ] */
37209
37210 if (this_to_global) {
37211 DUK_ASSERT(thr->builtins[DUK_BIDX_GLOBAL] != NULL);
37213 } else {
37214 duk_tval *tv;
37215 DUK_ASSERT(thr->callstack_top >= 2);
37216 DUK_ASSERT(act_caller != NULL);
37217 tv = (duk_tval *) (void *) ((duk_uint8_t *) thr->valstack + act_caller->bottom_byteoff -
37218 sizeof(duk_tval)); /* this is just beneath bottom */
37219 DUK_ASSERT(tv >= thr->valstack);
37220 duk_push_tval(thr, tv);
37221 }
37222
37223 DUK_DDD(DUK_DDDPRINT("eval -> lex_env=%!iO, var_env=%!iO, this_binding=%!T",
37224 (duk_heaphdr *) outer_lex_env,
37225 (duk_heaphdr *) outer_var_env,
37226 duk_get_tval(thr, -1)));
37227
37228 /* [ env? source template closure this ] */
37229
37230 call_flags = 0;
37231 if (act_eval->flags & DUK_ACT_FLAG_DIRECT_EVAL) {
37232 /* Set DIRECT_EVAL flag for the call; it's not strictly
37233 * needed for the 'inner' eval call (the eval body) but
37234 * current new.target implementation expects to find it
37235 * so it can traverse direct eval chains up to the real
37236 * calling function.
37237 */
37238 call_flags |= DUK_CALL_FLAG_DIRECT_EVAL;
37239 }
37241
37242 /* [ env? source template result ] */
37243
37244 return 1;
37245}
37246
37247/*
37248 * Parsing of ints and floats
37249 */
37250
37251#if defined(DUK_USE_GLOBAL_BUILTIN)
37253 duk_int32_t radix;
37254 duk_small_uint_t s2n_flags;
37255
37256 DUK_ASSERT_TOP(thr, 2);
37257 duk_to_string(thr, 0); /* Reject symbols. */
37258
37259 radix = duk_to_int32(thr, 1);
37260
37261 /* While parseInt() recognizes 0xdeadbeef, it doesn't recognize
37262 * ES2015 0o123 or 0b10001.
37263 */
37266
37267 /* Specification stripPrefix maps to DUK_S2N_FLAG_ALLOW_AUTO_HEX_INT.
37268 *
37269 * Don't autodetect octals (from leading zeroes), require user code to
37270 * provide an explicit radix 8 for parsing octal. See write-up from Mozilla:
37271 * https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/parseInt#ECMAScript_5_Removes_Octal_Interpretation
37272 */
37273
37274 if (radix != 0) {
37275 if (radix < 2 || radix > 36) {
37276 goto ret_nan;
37277 }
37278 if (radix != 16) {
37279 s2n_flags &= ~DUK_S2N_FLAG_ALLOW_AUTO_HEX_INT;
37280 }
37281 } else {
37282 radix = 10;
37283 }
37285 duk_dup_0(thr);
37286 duk_numconv_parse(thr, (duk_small_int_t) radix, s2n_flags);
37287 return 1;
37288
37289ret_nan:
37290 duk_push_nan(thr);
37291 return 1;
37292}
37293#endif /* DUK_USE_GLOBAL_BUILTIN */
37294
37295#if defined(DUK_USE_GLOBAL_BUILTIN)
37297 duk_small_uint_t s2n_flags;
37298
37299 DUK_ASSERT_TOP(thr, 1);
37300 duk_to_string(thr, 0); /* Reject symbols. */
37301
37302 /* XXX: check flags */
37306
37307 duk_numconv_parse(thr, 10 /*radix*/, s2n_flags);
37308 return 1;
37309}
37310#endif /* DUK_USE_GLOBAL_BUILTIN */
37311
37312/*
37313 * Number checkers
37314 */
37315
37316#if defined(DUK_USE_GLOBAL_BUILTIN)
37318 duk_double_t d = duk_to_number(thr, 0);
37320 return 1;
37321}
37322#endif /* DUK_USE_GLOBAL_BUILTIN */
37323
37324#if defined(DUK_USE_GLOBAL_BUILTIN)
37326 duk_double_t d = duk_to_number(thr, 0);
37328 return 1;
37330#endif /* DUK_USE_GLOBAL_BUILTIN */
37331
37332/*
37333 * URI handling
37334 */
37336#if defined(DUK_USE_GLOBAL_BUILTIN)
37340
37342 return duk__transform_helper(thr,
37345}
37349}
37352 return duk__transform_helper(thr,
37355}
37356
37357#if defined(DUK_USE_SECTION_B)
37359 return duk__transform_helper(thr, duk__transform_callback_escape, (const void *) NULL);
37360}
37361
37363 return duk__transform_helper(thr, duk__transform_callback_unescape, (const void *) NULL);
37364}
37365#endif /* DUK_USE_SECTION_B */
37366#endif /* DUK_USE_GLOBAL_BUILTIN */
37367
37368/* automatic undefs */
37369#undef DUK__CHECK_BITMASK
37370#undef DUK__MKBITS
37371/*
37372 * JSON built-ins.
37373 *
37374 * See doc/json.rst.
37375 *
37376 * Codepoints are handled as duk_uint_fast32_t to ensure that the full
37377 * unsigned 32-bit range is supported. This matters to e.g. JX.
37378 *
37379 * Input parsing doesn't do an explicit end-of-input check at all. This is
37380 * safe: input string data is always NUL-terminated (0x00) and valid JSON
37381 * inputs never contain plain NUL characters, so that as long as syntax checks
37382 * are correct, we'll never read past the NUL. This approach reduces code size
37383 * and improves parsing performance, but it's critical that syntax checks are
37384 * indeed correct!
37387/* #include duk_internal.h -> already included */
37388
37389#if defined(DUK_USE_JSON_SUPPORT)
37390
37391/*
37392 * Local defines and forward declarations.
37393 */
37394
37395#define DUK__JSON_DECSTR_BUFSIZE 128
37396#define DUK__JSON_DECSTR_CHUNKSIZE 64
37397#define DUK__JSON_ENCSTR_CHUNKSIZE 64
37398#define DUK__JSON_STRINGIFY_BUFSIZE 128
37399#define DUK__JSON_MAX_ESC_LEN 10 /* '\Udeadbeef' */
37400
37403#if defined(DUK_USE_JX)
37405#endif
37411#if defined(DUK_USE_JX)
37415#endif
37423
37428#if defined(DUK_USE_FASTINT)
37429DUK_LOCAL_DECL void duk__emit_cstring(duk_json_enc_ctx *js_ctx, const char *p);
37430#endif
37432DUK_LOCAL_DECL duk_uint8_t *duk__emit_esc_auto_fast(duk_json_enc_ctx *js_ctx, duk_uint_fast32_t cp, duk_uint8_t *q);
37442#if defined(DUK_USE_FASTINT)
37444#endif
37445#if defined(DUK_USE_JX) || defined(DUK_USE_JC)
37448#if defined(DUK_USE_BUFFEROBJECT_SUPPORT)
37450#endif
37451#endif
37452#if defined(DUK_USE_JSON_STRINGIFY_FASTPATH)
37453DUK_LOCAL_DECL void duk__json_enc_buffer_json_fastpath(duk_json_enc_ctx *js_ctx, duk_hbuffer *h);
37454#endif
37456
37457/*
37458 * Helper tables
37459 */
37460
37461#if defined(DUK_USE_JSON_QUOTESTRING_FASTPATH)
37462DUK_LOCAL const duk_uint8_t duk__json_quotestr_lookup[256] = {
37463 /* 0x00 ... 0x7f: as is
37464 * 0x80: escape generically
37465 * 0x81: slow path
37466 * 0xa0 ... 0xff: backslash + one char
37467 */
37468
37469 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0xe2, 0xf4, 0xee, 0x80, 0xe6, 0xf2, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80,
37470 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x20, 0x21, 0xa2, 0x23, 0x24, 0x25, 0x26, 0x27,
37471 0x28, 0x29, 0x2a, 0x2b, 0x2c, 0x2d, 0x2e, 0x2f, 0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, 0x38, 0x39, 0x3a, 0x3b,
37472 0x3c, 0x3d, 0x3e, 0x3f, 0x40, 0x41, 0x42, 0x43, 0x44, 0x45, 0x46, 0x47, 0x48, 0x49, 0x4a, 0x4b, 0x4c, 0x4d, 0x4e, 0x4f,
37473 0x50, 0x51, 0x52, 0x53, 0x54, 0x55, 0x56, 0x57, 0x58, 0x59, 0x5a, 0x5b, 0xdc, 0x5d, 0x5e, 0x5f, 0x60, 0x61, 0x62, 0x63,
37474 0x64, 0x65, 0x66, 0x67, 0x68, 0x69, 0x6a, 0x6b, 0x6c, 0x6d, 0x6e, 0x6f, 0x70, 0x71, 0x72, 0x73, 0x74, 0x75, 0x76, 0x77,
37475 0x78, 0x79, 0x7a, 0x7b, 0x7c, 0x7d, 0x7e, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81,
37476 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81,
37477 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81,
37478 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81,
37479 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81,
37480 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81,
37481 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81
37482};
37483#else /* DUK_USE_JSON_QUOTESTRING_FASTPATH */
37484DUK_LOCAL const duk_uint8_t duk__json_quotestr_esc[14] = { DUK_ASC_NUL, DUK_ASC_NUL, DUK_ASC_NUL, DUK_ASC_NUL, DUK_ASC_NUL,
37487#endif /* DUK_USE_JSON_QUOTESTRING_FASTPATH */
37488
37489#if defined(DUK_USE_JSON_DECSTRING_FASTPATH)
37490DUK_LOCAL const duk_uint8_t duk__json_decstr_lookup[256] = {
37491 /* 0x00: slow path
37492 * other: as is
37493 */
37494 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
37495 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x20, 0x21, 0x00, 0x23, 0x24, 0x25, 0x26, 0x27,
37496 0x28, 0x29, 0x2a, 0x2b, 0x2c, 0x2d, 0x2e, 0x2f, 0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, 0x38, 0x39, 0x3a, 0x3b,
37497 0x3c, 0x3d, 0x3e, 0x3f, 0x40, 0x41, 0x42, 0x43, 0x44, 0x45, 0x46, 0x47, 0x48, 0x49, 0x4a, 0x4b, 0x4c, 0x4d, 0x4e, 0x4f,
37498 0x50, 0x51, 0x52, 0x53, 0x54, 0x55, 0x56, 0x57, 0x58, 0x59, 0x5a, 0x5b, 0x00, 0x5d, 0x5e, 0x5f, 0x60, 0x61, 0x62, 0x63,
37499 0x64, 0x65, 0x66, 0x67, 0x68, 0x69, 0x6a, 0x6b, 0x6c, 0x6d, 0x6e, 0x6f, 0x70, 0x71, 0x72, 0x73, 0x74, 0x75, 0x76, 0x77,
37500 0x78, 0x79, 0x7a, 0x7b, 0x7c, 0x7d, 0x7e, 0x7f, 0x80, 0x81, 0x82, 0x83, 0x84, 0x85, 0x86, 0x87, 0x88, 0x89, 0x8a, 0x8b,
37501 0x8c, 0x8d, 0x8e, 0x8f, 0x90, 0x91, 0x92, 0x93, 0x94, 0x95, 0x96, 0x97, 0x98, 0x99, 0x9a, 0x9b, 0x9c, 0x9d, 0x9e, 0x9f,
37502 0xa0, 0xa1, 0xa2, 0xa3, 0xa4, 0xa5, 0xa6, 0xa7, 0xa8, 0xa9, 0xaa, 0xab, 0xac, 0xad, 0xae, 0xaf, 0xb0, 0xb1, 0xb2, 0xb3,
37503 0xb4, 0xb5, 0xb6, 0xb7, 0xb8, 0xb9, 0xba, 0xbb, 0xbc, 0xbd, 0xbe, 0xbf, 0xc0, 0xc1, 0xc2, 0xc3, 0xc4, 0xc5, 0xc6, 0xc7,
37504 0xc8, 0xc9, 0xca, 0xcb, 0xcc, 0xcd, 0xce, 0xcf, 0xd0, 0xd1, 0xd2, 0xd3, 0xd4, 0xd5, 0xd6, 0xd7, 0xd8, 0xd9, 0xda, 0xdb,
37505 0xdc, 0xdd, 0xde, 0xdf, 0xe0, 0xe1, 0xe2, 0xe3, 0xe4, 0xe5, 0xe6, 0xe7, 0xe8, 0xe9, 0xea, 0xeb, 0xec, 0xed, 0xee, 0xef,
37506 0xf0, 0xf1, 0xf2, 0xf3, 0xf4, 0xf5, 0xf6, 0xf7, 0xf8, 0xf9, 0xfa, 0xfb, 0xfc, 0xfd, 0xfe, 0xff
37507};
37508#endif /* DUK_USE_JSON_DECSTRING_FASTPATH */
37509
37510#if defined(DUK_USE_JSON_EATWHITE_FASTPATH)
37511DUK_LOCAL const duk_uint8_t duk__json_eatwhite_lookup[256] = {
37512 /* 0x00: finish (non-white)
37513 * 0x01: continue
37514 */
37515 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x01, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
37516 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
37517 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
37518 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
37519 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
37520 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
37521 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
37522 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
37523 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
37524 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
37525 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
37526 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
37527 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
37528};
37529#endif /* DUK_USE_JSON_EATWHITE_FASTPATH */
37530
37531#if defined(DUK_USE_JSON_DECNUMBER_FASTPATH)
37532DUK_LOCAL const duk_uint8_t duk__json_decnumber_lookup[256] = {
37533 /* 0x00: finish (not part of number)
37534 * 0x01: continue
37535 */
37536 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
37537 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
37538 0x00, 0x00, 0x00, 0x01, 0x00, 0x01, 0x01, 0x00, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x00, 0x00,
37539 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
37540 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
37541 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
37542 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
37543 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
37544 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
37545 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
37546 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
37547 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
37548 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
37549};
37550#endif /* DUK_USE_JSON_DECNUMBER_FASTPATH */
37551
37552/*
37553 * Parsing implementation.
37554 *
37555 * JSON lexer is now separate from duk_lexer.c because there are numerous
37556 * small differences making it difficult to share the lexer.
37557 *
37558 * The parser here works with raw bytes directly; this works because all
37559 * JSON delimiters are ASCII characters. Invalid xUTF-8 encoded values
37560 * inside strings will be passed on without normalization; this is not a
37561 * compliance concern because compliant inputs will always be valid
37562 * CESU-8 encodings.
37563 */
37564
37566 /* Shared handler to minimize parser size. Cause will be
37567 * hidden, unfortunately, but we'll have an offset which
37568 * is often quite enough.
37569 */
37570 DUK_ERROR_FMT1(js_ctx->thr, DUK_ERR_SYNTAX_ERROR, DUK_STR_FMT_INVALID_JSON, (long) (js_ctx->p - js_ctx->p_start));
37571 DUK_WO_NORETURN(return;);
37572}
37573
37575 const duk_uint8_t *p;
37576 duk_uint8_t t;
37577
37578 p = js_ctx->p;
37579 for (;;) {
37580 DUK_ASSERT(p <= js_ctx->p_end);
37581 t = *p;
37582
37583#if defined(DUK_USE_JSON_EATWHITE_FASTPATH)
37584 /* This fast path is pretty marginal in practice.
37585 * XXX: candidate for removal.
37586 */
37587 DUK_ASSERT(duk__json_eatwhite_lookup[0x00] == 0x00); /* end-of-input breaks */
37588 if (duk__json_eatwhite_lookup[t] == 0) {
37589 break;
37590 }
37591#else /* DUK_USE_JSON_EATWHITE_FASTPATH */
37592 if (!(t == 0x20 || t == 0x0a || t == 0x0d || t == 0x09)) {
37593 /* NUL also comes here. Comparison order matters, 0x20
37594 * is most common whitespace.
37595 */
37596 break;
37597 }
37598#endif /* DUK_USE_JSON_EATWHITE_FASTPATH */
37599 p++;
37600 }
37601 js_ctx->p = p;
37602}
37603
37604#if defined(DUK_USE_JX)
37605DUK_LOCAL duk_uint8_t duk__json_dec_peek(duk_json_dec_ctx *js_ctx) {
37606 DUK_ASSERT(js_ctx->p <= js_ctx->p_end);
37607 return *js_ctx->p;
37608}
37609#endif
37611DUK_LOCAL duk_uint8_t duk__json_dec_get(duk_json_dec_ctx *js_ctx) {
37612 DUK_ASSERT(js_ctx->p <= js_ctx->p_end);
37613 return *js_ctx->p++;
37614}
37615
37618 return duk__json_dec_get(js_ctx);
37619}
37620
37621/* For JX, expressing the whole unsigned 32-bit range matters. */
37624 duk_uint_fast32_t res = 0;
37625 duk_uint8_t x;
37627
37628 for (i = 0; i < n; i++) {
37629 /* XXX: share helper from lexer; duk_lexer.c / hexval(). */
37630
37631 x = duk__json_dec_get(js_ctx);
37632 DUK_DDD(DUK_DDDPRINT("decode_hex_escape: i=%ld, n=%ld, res=%ld, x=%ld", (long) i, (long) n, (long) res, (long) x));
37633
37634 /* x == 0x00 (EOF) causes syntax_error */
37635 DUK_ASSERT(duk_hex_dectab[0] == -1);
37636 t = duk_hex_dectab[x & 0xff];
37637 if (DUK_LIKELY(t >= 0)) {
37638 res = (res * 16) + (duk_uint_fast32_t) t;
37639 } else {
37640 /* catches EOF and invalid digits */
37641 goto syntax_error;
37643 }
37644
37645 DUK_DDD(DUK_DDDPRINT("final hex decoded value: %ld", (long) res));
37646 return res;
37647
37648syntax_error:
37651 return 0;
37652}
37653
37655 duk_hstring *h;
37656 const duk_uint8_t *p;
37657 duk_uint8_t x, y;
37658
37659 /* First character has already been eaten and checked by the caller.
37660 * We can scan until a NUL in stridx string because no built-in strings
37661 * have internal NULs.
37662 */
37663
37665 h = DUK_HTHREAD_GET_STRING(js_ctx->thr, stridx);
37666 DUK_ASSERT(h != NULL);
37667
37668 p = (const duk_uint8_t *) DUK_HSTRING_GET_DATA(h) + 1;
37669 DUK_ASSERT(*(js_ctx->p - 1) == *(p - 1)); /* first character has been matched */
37670
37671 for (;;) {
37672 x = *p;
37673 if (x == 0) {
37674 break;
37675 }
37676 y = duk__json_dec_get(js_ctx);
37677 if (x != y) {
37678 /* Catches EOF of JSON input. */
37679 goto syntax_error;
37680 }
37681 p++;
37682 }
37683
37684 return;
37685
37686syntax_error:
37689}
37690
37693
37694 /* EOF (-1) will be cast to an unsigned value first
37695 * and then re-cast for the switch. In any case, it
37696 * will match the default case (syntax error).
37697 */
37698 cp = (duk_uint_fast32_t) duk__json_dec_get(js_ctx);
37699 switch (cp) {
37700 case DUK_ASC_BACKSLASH:
37701 break;
37703 break;
37704 case DUK_ASC_SLASH:
37705 break;
37706 case DUK_ASC_LC_T:
37707 cp = 0x09;
37708 break;
37709 case DUK_ASC_LC_N:
37710 cp = 0x0a;
37711 break;
37712 case DUK_ASC_LC_R:
37713 cp = 0x0d;
37714 break;
37715 case DUK_ASC_LC_F:
37716 cp = 0x0c;
37717 break;
37718 case DUK_ASC_LC_B:
37719 cp = 0x08;
37720 break;
37721 case DUK_ASC_LC_U: {
37722 cp = duk__json_dec_decode_hex_escape(js_ctx, 4);
37723 break;
37724 }
37725#if defined(DUK_USE_JX)
37726 case DUK_ASC_UC_U: {
37727 if (js_ctx->flag_ext_custom) {
37728 cp = duk__json_dec_decode_hex_escape(js_ctx, 8);
37729 } else {
37730 return 1; /* syntax error */
37731 }
37732 break;
37733 }
37734 case DUK_ASC_LC_X: {
37735 if (js_ctx->flag_ext_custom) {
37736 cp = duk__json_dec_decode_hex_escape(js_ctx, 2);
37737 } else {
37738 return 1; /* syntax error */
37739 }
37740 break;
37742#endif /* DUK_USE_JX */
37743 default:
37744 /* catches EOF (0x00) */
37745 return 1; /* syntax error */
37746 }
37747
37748 DUK_RAW_WRITEINC_XUTF8(*ext_p, cp);
37749
37750 return 0;
37751}
37752
37754 duk_hthread *thr = js_ctx->thr;
37755 duk_bufwriter_ctx bw_alloc;
37757 duk_uint8_t *q;
37758
37759 /* '"' was eaten by caller */
37760
37761 /* Note that we currently parse -bytes-, not codepoints.
37762 * All non-ASCII extended UTF-8 will encode to bytes >= 0x80,
37763 * so they'll simply pass through (valid UTF-8 or not).
37764 */
37765
37766 bw = &bw_alloc;
37768 q = DUK_BW_GET_PTR(js_ctx->thr, bw);
37769
37770#if defined(DUK_USE_JSON_DECSTRING_FASTPATH)
37771 for (;;) {
37772 duk_small_uint_t safe;
37773 duk_uint8_t b, x;
37774 const duk_uint8_t *p;
37775
37776 /* Select a safe loop count where no output checks are
37777 * needed assuming we won't encounter escapes. Input
37778 * bound checks are not necessary as a NUL (guaranteed)
37779 * will cause a SyntaxError before we read out of bounds.
37780 */
37781
37783
37784 /* Ensure space for 1:1 output plus one escape. */
37785 q = DUK_BW_ENSURE_RAW(js_ctx->thr, bw, safe + DUK_UNICODE_MAX_XUTF8_LENGTH, q);
37786
37787 p = js_ctx->p; /* temp copy, write back for next loop */
37788 for (;;) {
37789 if (safe == 0) {
37790 js_ctx->p = p;
37791 break;
37792 }
37793 safe--;
37794
37795 /* End of input (NUL) goes through slow path and causes SyntaxError. */
37797
37798 b = *p++;
37800 if (DUK_LIKELY(x != 0)) {
37801 /* Fast path, decode as is. */
37802 *q++ = b;
37803 } else if (b == DUK_ASC_DOUBLEQUOTE) {
37804 js_ctx->p = p;
37805 goto found_quote;
37806 } else if (b == DUK_ASC_BACKSLASH) {
37807 /* We've ensured space for one escaped input; then
37808 * bail out and recheck (this makes escape handling
37809 * quite slow but it's uncommon).
37810 */
37811 js_ctx->p = p;
37812 if (duk__json_dec_string_escape(js_ctx, &q) != 0) {
37813 goto syntax_error;
37814 }
37815 break;
37816 } else {
37817 js_ctx->p = p;
37818 goto syntax_error;
37819 }
37820 }
37821 }
37822found_quote:
37823#else /* DUK_USE_JSON_DECSTRING_FASTPATH */
37824 for (;;) {
37825 duk_uint8_t x;
37826
37828
37829 x = duk__json_dec_get(js_ctx);
37830
37831 if (x == DUK_ASC_DOUBLEQUOTE) {
37832 break;
37833 } else if (x == DUK_ASC_BACKSLASH) {
37834 if (duk__json_dec_string_escape(js_ctx, &q) != 0) {
37835 goto syntax_error;
37836 }
37837 } else if (x < 0x20) {
37838 /* catches EOF (NUL) */
37839 goto syntax_error;
37840 } else {
37841 *q++ = (duk_uint8_t) x;
37842 }
37843 }
37844#endif /* DUK_USE_JSON_DECSTRING_FASTPATH */
37845
37846 DUK_BW_SETPTR_AND_COMPACT(js_ctx->thr, bw, q);
37847 (void) duk_buffer_to_string(thr, -1); /* Safe if input string is safe. */
37848
37849 /* [ ... str ] */
37851 return;
37852
37853syntax_error:
37856}
37857
37858#if defined(DUK_USE_JX)
37859/* Decode a plain string consisting entirely of identifier characters.
37860 * Used to parse plain keys (e.g. "foo: 123").
37861 */
37863 duk_hthread *thr = js_ctx->thr;
37864 const duk_uint8_t *p;
37866
37867 /* Caller has already eaten the first char so backtrack one byte. */
37868
37869 js_ctx->p--; /* safe */
37870 p = js_ctx->p;
37871
37872 /* Here again we parse bytes, and non-ASCII UTF-8 will cause end of
37873 * parsing (which is correct except if there are non-shortest encodings).
37874 * There is also no need to check explicitly for end of input buffer as
37875 * the input is NUL padded and NUL will exit the parsing loop.
37876 *
37877 * Because no unescaping takes place, we can just scan to the end of the
37878 * plain string and intern from the input buffer.
37879 */
37880
37881 for (;;) {
37882 x = *p;
37883
37884 /* There is no need to check the first character specially here
37885 * (i.e. reject digits): the caller only accepts valid initial
37886 * characters and won't call us if the first character is a digit.
37887 * This also ensures that the plain string won't be empty.
37888 */
37889
37891 break;
37893 p++;
37894 }
37895
37896 duk_push_lstring(thr, (const char *) js_ctx->p, (duk_size_t) (p - js_ctx->p));
37897 js_ctx->p = p;
37898
37899 /* [ ... str ] */
37900}
37901#endif /* DUK_USE_JX */
37902
37903#if defined(DUK_USE_JX)
37905 duk_hthread *thr = js_ctx->thr;
37906 const duk_uint8_t *p;
37908 void *voidptr;
37909
37910 /* Caller has already eaten the first character ('(') which we don't need. */
37911
37912 p = js_ctx->p;
37913
37914 for (;;) {
37915 x = *p;
37916
37917 /* Assume that the native representation never contains a closing
37918 * parenthesis.
37919 */
37920
37921 if (x == DUK_ASC_RPAREN) {
37922 break;
37923 } else if (x <= 0) {
37924 /* NUL term or -1 (EOF), NUL check would suffice */
37925 goto syntax_error;
37926 }
37927 p++;
37928 }
37929
37930 /* There is no need to NUL delimit the sscanf() call: trailing garbage is
37931 * ignored and there is always a NUL terminator which will force an error
37932 * if no error is encountered before it. It's possible that the scan
37933 * would scan further than between [js_ctx->p,p[ though and we'd advance
37934 * by less than the scanned value.
37935 *
37936 * Because pointers are platform specific, a failure to scan a pointer
37937 * results in a null pointer which is a better placeholder than a missing
37938 * value or an error.
37939 */
37940
37941 voidptr = NULL;
37942 (void) DUK_SSCANF((const char *) js_ctx->p, DUK_STR_FMT_PTR, &voidptr);
37943 duk_push_pointer(thr, voidptr);
37944 js_ctx->p = p + 1; /* skip ')' */
37946 /* [ ... ptr ] */
37947
37948 return;
37949
37950syntax_error:
37953}
37954#endif /* DUK_USE_JX */
37955
37956#if defined(DUK_USE_JX)
37958 duk_hthread *thr = js_ctx->thr;
37959 const duk_uint8_t *p;
37960 duk_uint8_t *buf;
37961 duk_size_t src_len;
37963
37964 /* Caller has already eaten the first character ('|') which we don't need. */
37965
37966 p = js_ctx->p;
37967
37968 /* XXX: Would be nice to share the fast path loop from duk_hex_decode()
37969 * and avoid creating a temporary buffer. However, there are some
37970 * differences which prevent trivial sharing:
37971 *
37972 * - Pipe char detection
37973 * - EOF detection
37974 * - Unknown length of input and output
37975 *
37976 * The best approach here would be a bufwriter and a reasonaly sized
37977 * safe inner loop (e.g. 64 output bytes at a time).
37978 */
37979
37980 for (;;) {
37981 x = *p;
37982
37983 /* This loop intentionally does not ensure characters are valid
37984 * ([0-9a-fA-F]) because the hex decode call below will do that.
37985 */
37986 if (x == DUK_ASC_PIPE) {
37987 break;
37988 } else if (x <= 0) {
37989 /* NUL term or -1 (EOF), NUL check would suffice */
37990 goto syntax_error;
37991 }
37992 p++;
37993 }
37994
37995 /* XXX: this is not very nice; unnecessary copy is made. */
37996 src_len = (duk_size_t) (p - js_ctx->p);
37997 buf = (duk_uint8_t *) duk_push_fixed_buffer_nozero(thr, src_len);
37998 DUK_ASSERT(buf != NULL);
37999 duk_memcpy((void *) buf, (const void *) js_ctx->p, src_len);
38000 duk_hex_decode(thr, -1);
38001
38002 js_ctx->p = p + 1; /* skip '|' */
38004 /* [ ... buf ] */
38005
38006 return;
38007
38008syntax_error:
38011}
38012#endif /* DUK_USE_JX */
38013
38014/* Parse a number, other than NaN or +/- Infinity */
38016 duk_hthread *thr = js_ctx->thr;
38017 const duk_uint8_t *p_start;
38018 const duk_uint8_t *p;
38019 duk_uint8_t x;
38020 duk_small_uint_t s2n_flags;
38021
38022 DUK_DDD(DUK_DDDPRINT("parse_number"));
38023
38024 p_start = js_ctx->p;
38025
38026 /* First pass parse is very lenient (e.g. allows '1.2.3') and extracts a
38027 * string for strict number parsing.
38028 */
38029
38030 p = js_ctx->p;
38031 for (;;) {
38032 x = *p;
38033
38034 DUK_DDD(DUK_DDDPRINT("parse_number: p_start=%p, p=%p, p_end=%p, x=%ld",
38035 (const void *) p_start,
38036 (const void *) p,
38037 (const void *) js_ctx->p_end,
38038 (long) x));
38039
38040#if defined(DUK_USE_JSON_DECNUMBER_FASTPATH)
38041 /* This fast path is pretty marginal in practice.
38042 * XXX: candidate for removal.
38043 */
38044 DUK_ASSERT(duk__json_decnumber_lookup[0x00] == 0x00); /* end-of-input breaks */
38045 if (duk__json_decnumber_lookup[x] == 0) {
38046 break;
38047 }
38048#else /* DUK_USE_JSON_DECNUMBER_FASTPATH */
38049 if (!((x >= DUK_ASC_0 && x <= DUK_ASC_9) ||
38050 (x == DUK_ASC_PERIOD || x == DUK_ASC_LC_E || x == DUK_ASC_UC_E || x == DUK_ASC_MINUS || x == DUK_ASC_PLUS))) {
38051 /* Plus sign must be accepted for positive exponents
38052 * (e.g. '1.5e+2'). This clause catches NULs.
38053 */
38054 break;
38055 }
38056#endif /* DUK_USE_JSON_DECNUMBER_FASTPATH */
38057 p++; /* safe, because matched (NUL causes a break) */
38058 }
38059 js_ctx->p = p;
38060
38061 DUK_ASSERT(js_ctx->p > p_start);
38062 duk_push_lstring(thr, (const char *) p_start, (duk_size_t) (p - p_start));
38063
38064 s2n_flags = DUK_S2N_FLAG_ALLOW_EXP | DUK_S2N_FLAG_ALLOW_MINUS | /* but don't allow leading plus */
38067 DUK_DDD(DUK_DDDPRINT("parse_number: string before parsing: %!T", (duk_tval *) duk_get_tval(thr, -1)));
38068 duk_numconv_parse(thr, 10 /*radix*/, s2n_flags);
38069 if (duk_is_nan(thr, -1)) {
38071 }
38072 DUK_ASSERT(duk_is_number(thr, -1));
38073 DUK_DDD(DUK_DDDPRINT("parse_number: final number: %!T", (duk_tval *) duk_get_tval(thr, -1)));
38074
38075 /* [ ... num ] */
38076}
38077
38079 duk_hthread *thr = js_ctx->thr;
38081
38082 /* c recursion check */
38085
38086 DUK_ASSERT_DISABLE(js_ctx->recursion_depth >= 0); /* unsigned */
38087 DUK_ASSERT(js_ctx->recursion_depth <= js_ctx->recursion_limit);
38088 if (js_ctx->recursion_depth >= js_ctx->recursion_limit) {
38090 DUK_WO_NORETURN(return;);
38092 js_ctx->recursion_depth++;
38093}
38094
38096 /* c recursion check */
38097
38098 DUK_ASSERT(js_ctx->recursion_depth > 0);
38099 DUK_ASSERT(js_ctx->recursion_depth <= js_ctx->recursion_limit);
38100 js_ctx->recursion_depth--;
38101}
38102
38104 duk_hthread *thr = js_ctx->thr;
38105 duk_int_t key_count; /* XXX: a "first" flag would suffice */
38106 duk_uint8_t x;
38107
38108 DUK_DDD(DUK_DDDPRINT("parse_object"));
38109
38111
38112 duk_push_object(thr);
38113
38114 /* Initial '{' has been checked and eaten by caller. */
38115
38116 key_count = 0;
38117 for (;;) {
38118 x = duk__json_dec_get_nonwhite(js_ctx);
38119
38120 DUK_DDD(DUK_DDDPRINT("parse_object: obj=%!T, x=%ld, key_count=%ld",
38121 (duk_tval *) duk_get_tval(thr, -1),
38122 (long) x,
38123 (long) key_count));
38124
38125 /* handle comma and closing brace */
38126
38127 if (x == DUK_ASC_COMMA && key_count > 0) {
38128 /* accept comma, expect new value */
38129 x = duk__json_dec_get_nonwhite(js_ctx);
38130 } else if (x == DUK_ASC_RCURLY) {
38131 /* eat closing brace */
38132 break;
38133 } else if (key_count == 0) {
38134 /* accept anything, expect first value (EOF will be
38135 * caught by key parsing below.
38136 */
38137 ;
38138 } else {
38139 /* catches EOF (NUL) and initial comma */
38140 goto syntax_error;
38141 }
38142
38143 /* parse key and value */
38144
38145 if (x == DUK_ASC_DOUBLEQUOTE) {
38146 duk__json_dec_string(js_ctx);
38147#if defined(DUK_USE_JX)
38150#endif
38151 } else {
38152 goto syntax_error;
38153 }
38154
38155 /* [ ... obj key ] */
38156
38157 x = duk__json_dec_get_nonwhite(js_ctx);
38158 if (x != DUK_ASC_COLON) {
38159 goto syntax_error;
38160 }
38161
38162 duk__json_dec_value(js_ctx);
38163
38164 /* [ ... obj key val ] */
38165
38166 duk_xdef_prop_wec(thr, -3);
38167
38168 /* [ ... obj ] */
38169
38170 key_count++;
38171 }
38172
38173 /* [ ... obj ] */
38174
38175 DUK_DDD(DUK_DDDPRINT("parse_object: final object is %!T", (duk_tval *) duk_get_tval(thr, -1)));
38176
38178 return;
38179
38180syntax_error:
38183}
38184
38186 duk_hthread *thr = js_ctx->thr;
38187 duk_uarridx_t arr_idx;
38188 duk_uint8_t x;
38189
38190 DUK_DDD(DUK_DDDPRINT("parse_array"));
38191
38193
38194 duk_push_array(thr);
38195
38196 /* Initial '[' has been checked and eaten by caller. */
38197
38198 arr_idx = 0;
38199 for (;;) {
38200 x = duk__json_dec_get_nonwhite(js_ctx);
38201
38202 DUK_DDD(DUK_DDDPRINT("parse_array: arr=%!T, x=%ld, arr_idx=%ld",
38203 (duk_tval *) duk_get_tval(thr, -1),
38204 (long) x,
38205 (long) arr_idx));
38206
38207 /* handle comma and closing bracket */
38208
38209 if ((x == DUK_ASC_COMMA) && (arr_idx != 0)) {
38210 /* accept comma, expect new value */
38211 ;
38212 } else if (x == DUK_ASC_RBRACKET) {
38213 /* eat closing bracket */
38214 break;
38215 } else if (arr_idx == 0) {
38216 /* accept anything, expect first value (EOF will be
38217 * caught by duk__json_dec_value() below.
38218 */
38219 js_ctx->p--; /* backtrack (safe) */
38220 } else {
38221 /* catches EOF (NUL) and initial comma */
38222 goto syntax_error;
38223 }
38224
38225 /* parse value */
38226
38227 duk__json_dec_value(js_ctx);
38228
38229 /* [ ... arr val ] */
38230
38231 duk_xdef_prop_index_wec(thr, -2, arr_idx);
38232 arr_idx++;
38233 }
38234
38235 /* Must set 'length' explicitly when using duk_xdef_prop_xxx() to
38236 * set the values.
38237 */
38238
38239 duk_set_length(thr, -1, arr_idx);
38240
38241 /* [ ... arr ] */
38242
38243 DUK_DDD(DUK_DDDPRINT("parse_array: final array is %!T", (duk_tval *) duk_get_tval(thr, -1)));
38244
38246 return;
38247
38248syntax_error:
38251}
38252
38254 duk_hthread *thr = js_ctx->thr;
38255 duk_uint8_t x;
38256
38257 x = duk__json_dec_get_nonwhite(js_ctx);
38258
38259 DUK_DDD(DUK_DDDPRINT("parse_value: initial x=%ld", (long) x));
38260
38261 /* Note: duk__json_dec_req_stridx() backtracks one char */
38262
38263 if (x == DUK_ASC_DOUBLEQUOTE) {
38264 duk__json_dec_string(js_ctx);
38265 } else if ((x >= DUK_ASC_0 && x <= DUK_ASC_9) || (x == DUK_ASC_MINUS)) {
38266#if defined(DUK_USE_JX)
38267 if (js_ctx->flag_ext_custom && x == DUK_ASC_MINUS && duk__json_dec_peek(js_ctx) == DUK_ASC_UC_I) {
38268 duk__json_dec_req_stridx(js_ctx, DUK_STRIDX_MINUS_INFINITY); /* "-Infinity", '-' has been eaten */
38270 } else {
38271#else
38272 { /* unconditional block */
38273#endif
38274 /* We already ate 'x', so backup one byte. */
38275 js_ctx->p--; /* safe */
38276 duk__json_dec_number(js_ctx);
38277 }
38278 } else if (x == DUK_ASC_LC_T) {
38280 duk_push_true(thr);
38281 } else if (x == DUK_ASC_LC_F) {
38283 duk_push_false(thr);
38284 } else if (x == DUK_ASC_LC_N) {
38286 duk_push_null(thr);
38287#if defined(DUK_USE_JX)
38288 } else if (js_ctx->flag_ext_custom && x == DUK_ASC_LC_U) {
38290 duk_push_undefined(thr);
38291 } else if (js_ctx->flag_ext_custom && x == DUK_ASC_UC_N) {
38293 duk_push_nan(thr);
38294 } else if (js_ctx->flag_ext_custom && x == DUK_ASC_UC_I) {
38297 } else if (js_ctx->flag_ext_custom && x == DUK_ASC_LPAREN) {
38298 duk__json_dec_pointer(js_ctx);
38299 } else if (js_ctx->flag_ext_custom && x == DUK_ASC_PIPE) {
38300 duk__json_dec_buffer(js_ctx);
38301#endif
38302 } else if (x == DUK_ASC_LCURLY) {
38303 duk__json_dec_object(js_ctx);
38304 } else if (x == DUK_ASC_LBRACKET) {
38305 duk__json_dec_array(js_ctx);
38306 } else {
38307 /* catches EOF (NUL) */
38308 goto syntax_error;
38309 }
38310
38312
38313 /* [ ... val ] */
38314 return;
38315
38316syntax_error:
38319}
38320
38321/* Recursive value reviver, implements the Walk() algorithm. The parsing
38322 * step ensures there is a reasonable depth limit to the input. However,
38323 * the reviver may create more depth by editing object or array entries, so
38324 * we have both C recursion limit and native stack checks here.
38325 */
38327 duk_hthread *thr = js_ctx->thr;
38328 duk_hobject *h;
38329 duk_uarridx_t i, arr_len;
38330
38332
38333 DUK_DDD(DUK_DDDPRINT("walk: top=%ld, holder=%!T, name=%!T",
38334 (long) duk_get_top(thr),
38335 (duk_tval *) duk_get_tval(thr, -2),
38336 (duk_tval *) duk_get_tval(thr, -1)));
38337
38338 duk_dup_top(thr);
38339 duk_get_prop(thr, -3); /* -> [ ... holder name val ] */
38340
38341 h = duk_get_hobject(thr, -1);
38342 if (h != NULL) {
38343 if (duk_js_isarray_hobject(h)) {
38344 arr_len = (duk_uarridx_t) duk_get_length(thr, -1);
38345 for (i = 0; i < arr_len; i++) {
38346 /* [ ... holder name val ] */
38347
38348 DUK_DDD(DUK_DDDPRINT("walk: array, top=%ld, i=%ld, arr_len=%ld, holder=%!T, name=%!T, val=%!T",
38349 (long) duk_get_top(thr),
38350 (long) i,
38351 (long) arr_len,
38352 (duk_tval *) duk_get_tval(thr, -3),
38353 (duk_tval *) duk_get_tval(thr, -2),
38354 (duk_tval *) duk_get_tval(thr, -1)));
38355
38356 duk_dup_top(thr);
38357 (void) duk_push_uint_to_hstring(thr,
38358 (duk_uint_t) i); /* -> [ ... holder name val val ToString(i) ] */
38359 duk__json_dec_reviver_walk(js_ctx); /* -> [ ... holder name val new_elem ] */
38360
38361 if (duk_is_undefined(thr, -1)) {
38362 duk_pop(thr);
38363 duk_del_prop_index(thr, -1, i);
38364 } else {
38365 /* XXX: duk_xdef_prop_index_wec() would be more appropriate
38366 * here but it currently makes some assumptions that might
38367 * not hold (e.g. that previous property is not an accessor).
38368 */
38369 duk_put_prop_index(thr, -2, i);
38370 }
38371 }
38372 } else {
38373 /* [ ... holder name val ] */
38374 duk_enum(thr, -1, DUK_ENUM_OWN_PROPERTIES_ONLY /*flags*/);
38375 while (duk_next(thr, -1 /*enum_index*/, 0 /*get_value*/)) {
38376 DUK_DDD(DUK_DDDPRINT("walk: object, top=%ld, holder=%!T, name=%!T, val=%!T, enum=%!iT, obj_key=%!T",
38377 (long) duk_get_top(thr),
38378 (duk_tval *) duk_get_tval(thr, -5),
38379 (duk_tval *) duk_get_tval(thr, -4),
38380 (duk_tval *) duk_get_tval(thr, -3),
38381 (duk_tval *) duk_get_tval(thr, -2),
38382 (duk_tval *) duk_get_tval(thr, -1)));
38383
38384 /* [ ... holder name val enum obj_key ] */
38385 duk_dup_m3(thr);
38386 duk_dup_m2(thr);
38387
38388 /* [ ... holder name val enum obj_key val obj_key ] */
38390
38391 /* [ ... holder name val enum obj_key new_elem ] */
38392 if (duk_is_undefined(thr, -1)) {
38393 duk_pop(thr);
38394 duk_del_prop(thr, -3);
38395 } else {
38396 /* XXX: duk_xdef_prop_index_wec() would be more appropriate
38397 * here but it currently makes some assumptions that might
38398 * not hold (e.g. that previous property is not an accessor).
38399 *
38400 * Using duk_put_prop() works incorrectly with '__proto__'
38401 * if the own property with that name has been deleted. This
38402 * does not happen normally, but a clever reviver can trigger
38403 * that, see complex reviver case in: test-bug-json-parse-__proto__.js.
38404 */
38405 duk_put_prop(thr, -4);
38406 }
38407 }
38408 duk_pop(thr); /* pop enum */
38409 }
38410 }
38411
38412 /* [ ... holder name val ] */
38413
38414 duk_dup(thr, js_ctx->idx_reviver);
38415 duk_insert(thr, -4); /* -> [ ... reviver holder name val ] */
38416 duk_call_method(thr, 2); /* -> [ ... res ] */
38420 DUK_DDD(DUK_DDDPRINT("walk: top=%ld, result=%!T", (long) duk_get_top(thr), (duk_tval *) duk_get_tval(thr, -1)));
38423/*
38424 * Stringify implementation.
38425 */
38426
38427#define DUK__EMIT_1(js_ctx, ch) duk__emit_1((js_ctx), (duk_uint_fast8_t) (ch))
38428#define DUK__EMIT_2(js_ctx, ch1, ch2) duk__emit_2((js_ctx), (duk_uint_fast8_t) (ch1), (duk_uint_fast8_t) (ch2))
38429#define DUK__EMIT_HSTR(js_ctx, h) duk__emit_hstring((js_ctx), (h))
38430#if defined(DUK_USE_FASTINT) || defined(DUK_USE_JX) || defined(DUK_USE_JC)
38431#define DUK__EMIT_CSTR(js_ctx, p) duk__emit_cstring((js_ctx), (p))
38432#endif
38433#define DUK__EMIT_STRIDX(js_ctx, i) duk__emit_stridx((js_ctx), (i))
38434#define DUK__UNEMIT_1(js_ctx) duk__unemit_1((js_ctx))
38435
38437 DUK_BW_WRITE_ENSURE_U8(js_ctx->thr, &js_ctx->bw, ch);
38438}
38439
38441 DUK_BW_WRITE_ENSURE_U8_2(js_ctx->thr, &js_ctx->bw, ch1, ch2);
38443
38445 DUK_BW_WRITE_ENSURE_HSTRING(js_ctx->thr, &js_ctx->bw, h);
38446}
38447
38448#if defined(DUK_USE_FASTINT) || defined(DUK_USE_JX) || defined(DUK_USE_JC)
38449DUK_LOCAL void duk__emit_cstring(duk_json_enc_ctx *js_ctx, const char *str) {
38450 DUK_BW_WRITE_ENSURE_CSTRING(js_ctx->thr, &js_ctx->bw, str);
38451}
38452#endif
38453
38455 duk_hstring *h;
38456
38458 h = DUK_HTHREAD_GET_STRING(js_ctx->thr, stridx);
38459 DUK_ASSERT(h != NULL);
38461 DUK_BW_WRITE_ENSURE_HSTRING(js_ctx->thr, &js_ctx->bw, h);
38462}
38463
38465 DUK_ASSERT(DUK_BW_GET_SIZE(js_ctx->thr, &js_ctx->bw) >= 1);
38466 DUK_BW_ADD_PTR(js_ctx->thr, &js_ctx->bw, -1);
38467}
38468
38469#define DUK__MKESC(nybbles, esc1, esc2) \
38470 (((duk_uint_fast32_t) (nybbles)) << 16) | (((duk_uint_fast32_t) (esc1)) << 8) | ((duk_uint_fast32_t) (esc2))
38471
38472DUK_LOCAL duk_uint8_t *duk__emit_esc_auto_fast(duk_json_enc_ctx *js_ctx, duk_uint_fast32_t cp, duk_uint8_t *q) {
38474 duk_small_uint_t dig;
38475
38476 DUK_UNREF(js_ctx);
38477
38478 /* Caller ensures space for at least DUK__JSON_MAX_ESC_LEN. */
38479
38480 /* Select appropriate escape format automatically, and set 'tmp' to a
38481 * value encoding both the escape format character and the nybble count:
38482 *
38483 * (nybble_count << 16) | (escape_char1) | (escape_char2)
38484 */
38485
38486#if defined(DUK_USE_JX)
38487 if (DUK_LIKELY(cp < 0x100UL)) {
38488 if (DUK_UNLIKELY(js_ctx->flag_ext_custom != 0U)) {
38490 } else {
38492 }
38493 } else
38494#endif
38495 if (DUK_LIKELY(cp < 0x10000UL)) {
38497 } else {
38498#if defined(DUK_USE_JX)
38499 if (DUK_LIKELY(js_ctx->flag_ext_custom != 0U)) {
38501 } else
38502#endif
38503 {
38504 /* In compatible mode and standard JSON mode, output
38505 * something useful for non-BMP characters. This won't
38506 * roundtrip but will still be more or less readable and
38507 * more useful than an error.
38508 */
38510 }
38511 }
38512
38513 *q++ = (duk_uint8_t) ((tmp >> 8) & 0xff);
38514 *q++ = (duk_uint8_t) (tmp & 0xff);
38515
38516 tmp = tmp >> 16;
38517 while (tmp > 0) {
38518 tmp--;
38519 dig = (duk_small_uint_t) ((cp >> (4 * tmp)) & 0x0f);
38520 *q++ = duk_lc_digits[dig];
38521 }
38522
38523 return q;
38524}
38525
38527 const duk_int8_t *p, *p_start, *p_end; /* Note: intentionally signed. */
38528 duk_size_t k_len;
38529 duk_codepoint_t cp;
38530
38531 DUK_ASSERT(k != NULL);
38532
38533 /* Accept ASCII strings which conform to identifier requirements
38534 * as being emitted without key quotes. Since we only accept ASCII
38535 * there's no need for actual decoding: 'p' is intentionally signed
38536 * so that bytes >= 0x80 extend to negative values and are rejected
38537 * as invalid identifier codepoints.
38538 */
38539
38540 if (js_ctx->flag_avoid_key_quotes) {
38541 k_len = DUK_HSTRING_GET_BYTELEN(k);
38542 p_start = (const duk_int8_t *) DUK_HSTRING_GET_DATA(k);
38543 p_end = p_start + k_len;
38544 p = p_start;
38545
38546 if (p == p_end) {
38547 /* Zero length string is not accepted without quotes */
38548 goto quote_normally;
38549 }
38550 cp = (duk_codepoint_t) (*p++);
38552 goto quote_normally;
38553 }
38554 while (p < p_end) {
38555 cp = (duk_codepoint_t) (*p++);
38557 goto quote_normally;
38558 }
38559 }
38560
38561 /* This seems faster than emitting bytes one at a time and
38562 * then potentially rewinding.
38563 */
38564 DUK__EMIT_HSTR(js_ctx, k);
38565 return;
38566 }
38567
38568quote_normally:
38569 duk__json_enc_quote_string(js_ctx, k);
38570}
38571
38572/* The Quote(value) operation: quote a string.
38573 *
38574 * Stack policy: [ ] -> [ ].
38575 */
38576
38578 duk_hthread *thr = js_ctx->thr;
38579 const duk_uint8_t *p, *p_start, *p_end, *p_now, *p_tmp;
38580 duk_uint8_t *q;
38581 duk_ucodepoint_t cp; /* typed for duk_unicode_decode_xutf8() */
38582
38583 DUK_DDD(DUK_DDDPRINT("duk__json_enc_quote_string: h_str=%!O", (duk_heaphdr *) h_str));
38584
38585 DUK_ASSERT(h_str != NULL);
38586 p_start = DUK_HSTRING_GET_DATA(h_str);
38587 p_end = p_start + DUK_HSTRING_GET_BYTELEN(h_str);
38588 p = p_start;
38589
38591
38592 /* Encode string in small chunks, estimating the maximum expansion so that
38593 * there's no need to ensure space while processing the chunk.
38594 */
38595
38596 while (p < p_end) {
38597 duk_size_t left, now, space;
38598
38599 left = (duk_size_t) (p_end - p);
38601
38602 /* Maximum expansion per input byte is 6:
38603 * - invalid UTF-8 byte causes "\uXXXX" to be emitted (6/1 = 6).
38604 * - 2-byte UTF-8 encodes as "\uXXXX" (6/2 = 3).
38605 * - 4-byte UTF-8 encodes as "\Uxxxxxxxx" (10/4 = 2.5).
38606 */
38607 space = now * 6;
38608 q = DUK_BW_ENSURE_GETPTR(thr, &js_ctx->bw, space);
38609
38610 p_now = p + now;
38611
38612 while (p < p_now) {
38613#if defined(DUK_USE_JSON_QUOTESTRING_FASTPATH)
38614 duk_uint8_t b;
38615
38616 b = duk__json_quotestr_lookup[*p++];
38617 if (DUK_LIKELY(b < 0x80)) {
38618 /* Most input bytes go through here. */
38619 *q++ = b;
38620 } else if (b >= 0xa0) {
38621 *q++ = DUK_ASC_BACKSLASH;
38622 *q++ = (duk_uint8_t) (b - 0x80);
38623 } else if (b == 0x80) {
38624 cp = (duk_ucodepoint_t) (*(p - 1));
38625 q = duk__emit_esc_auto_fast(js_ctx, cp, q);
38626 } else if (b == 0x7f && js_ctx->flag_ascii_only) {
38627 /* 0x7F is special */
38628 DUK_ASSERT(b == 0x81);
38629 cp = (duk_ucodepoint_t) 0x7f;
38630 q = duk__emit_esc_auto_fast(js_ctx, cp, q);
38631 } else {
38632 DUK_ASSERT(b == 0x81);
38633 p--;
38634
38635 /* slow path is shared */
38636#else /* DUK_USE_JSON_QUOTESTRING_FASTPATH */
38637 cp = *p;
38638
38639 if (DUK_LIKELY(cp <= 0x7f)) {
38640 /* ascii fast path: avoid decoding utf-8 */
38641 p++;
38642 if (cp == 0x22 || cp == 0x5c) {
38643 /* double quote or backslash */
38644 *q++ = DUK_ASC_BACKSLASH;
38645 *q++ = (duk_uint8_t) cp;
38646 } else if (cp < 0x20) {
38647 duk_uint_fast8_t esc_char;
38648
38649 /* This approach is a bit shorter than a straight
38650 * if-else-ladder and also a bit faster.
38651 */
38652 if (cp < (sizeof(duk__json_quotestr_esc) / sizeof(duk_uint8_t)) &&
38653 (esc_char = duk__json_quotestr_esc[cp]) != 0) {
38654 *q++ = DUK_ASC_BACKSLASH;
38655 *q++ = (duk_uint8_t) esc_char;
38656 } else {
38657 q = duk__emit_esc_auto_fast(js_ctx, cp, q);
38658 }
38659 } else if (cp == 0x7f && js_ctx->flag_ascii_only) {
38660 q = duk__emit_esc_auto_fast(js_ctx, cp, q);
38661 } else {
38662 /* any other printable -> as is */
38663 *q++ = (duk_uint8_t) cp;
38664 }
38665 } else {
38666 /* slow path is shared */
38667#endif /* DUK_USE_JSON_QUOTESTRING_FASTPATH */
38668
38669 /* slow path decode */
38670
38671 /* If XUTF-8 decoding fails, treat the offending byte as a codepoint directly
38672 * and go forward one byte. This is of course very lossy, but allows some kind
38673 * of output to be produced even for internal strings which don't conform to
38674 * XUTF-8. All standard ECMAScript strings are always CESU-8, so this behavior
38675 * does not violate the ECMAScript specification. The behavior is applied to
38676 * all modes, including ECMAScript standard JSON. Because the current XUTF-8
38677 * decoding is not very strict, this behavior only really affects initial bytes
38678 * and truncated codepoints.
38679 *
38680 * Another alternative would be to scan forwards to start of next codepoint
38681 * (or end of input) and emit just one replacement codepoint.
38682 */
38683
38684 p_tmp = p;
38685 if (!duk_unicode_decode_xutf8(thr, &p, p_start, p_end, &cp)) {
38686 /* Decode failed. */
38687 cp = *p_tmp;
38688 p = p_tmp + 1;
38689 }
38690
38691#if defined(DUK_USE_NONSTD_JSON_ESC_U2028_U2029)
38692 if (js_ctx->flag_ascii_only || cp == 0x2028 || cp == 0x2029) {
38693#else
38694 if (js_ctx->flag_ascii_only) {
38695#endif
38696 q = duk__emit_esc_auto_fast(js_ctx, cp, q);
38697 } else {
38698 /* as is */
38700 }
38702 }
38703
38704 DUK_BW_SET_PTR(thr, &js_ctx->bw, q);
38705 }
38706
38708}
38709
38710/* Encode a double (checked by caller) from stack top. Stack top may be
38711 * replaced by serialized string but is not popped (caller does that).
38712 */
38714 duk_hthread *thr;
38715 duk_tval *tv;
38716 duk_double_t d;
38719 duk_small_uint_t stridx;
38720 duk_small_uint_t n2s_flags;
38721 duk_hstring *h_str;
38722
38723 DUK_ASSERT(js_ctx != NULL);
38724 thr = js_ctx->thr;
38725 DUK_ASSERT(thr != NULL);
38726
38727 /* Caller must ensure 'tv' is indeed a double and not a fastint! */
38728 tv = DUK_GET_TVAL_NEGIDX(thr, -1);
38730 d = DUK_TVAL_GET_DOUBLE(tv);
38731
38734 DUK_UNREF(s);
38735
38736 if (DUK_LIKELY(!(c == DUK_FP_INFINITE || c == DUK_FP_NAN))) {
38738
38739#if defined(DUK_USE_JX) || defined(DUK_USE_JC)
38740 /* Negative zero needs special handling in JX/JC because
38741 * it would otherwise serialize to '0', not '-0'.
38742 */
38743 if (DUK_UNLIKELY(c == DUK_FP_ZERO && s != 0 && (js_ctx->flag_ext_custom_or_compatible))) {
38745 } else
38746#endif /* DUK_USE_JX || DUK_USE_JC */
38747 {
38748 n2s_flags = 0;
38749 /* [ ... number ] -> [ ... string ] */
38750 duk_numconv_stringify(thr, 10 /*radix*/, 0 /*digits*/, n2s_flags);
38751 }
38752 h_str = duk_known_hstring(thr, -1);
38753 DUK__EMIT_HSTR(js_ctx, h_str);
38754 return;
38755 }
38756
38757#if defined(DUK_USE_JX) || defined(DUK_USE_JC)
38759 stridx = DUK_STRIDX_LC_NULL;
38760 } else if (c == DUK_FP_NAN) {
38761 stridx = js_ctx->stridx_custom_nan;
38762 } else if (s == 0) {
38763 stridx = js_ctx->stridx_custom_posinf;
38764 } else {
38765 stridx = js_ctx->stridx_custom_neginf;
38766 }
38767#else
38768 stridx = DUK_STRIDX_LC_NULL;
38769#endif
38770 DUK__EMIT_STRIDX(js_ctx, stridx);
38771}
38772
38773#if defined(DUK_USE_FASTINT)
38774/* Encode a fastint from duk_tval ptr, no value stack effects. */
38776 duk_int64_t v;
38777
38778 /* Fastint range is signed 48-bit so longest value is -2^47 = -140737488355328
38779 * (16 chars long), longest signed 64-bit value is -2^63 = -9223372036854775808
38780 * (20 chars long). Alloc space for 64-bit range to be safe.
38781 */
38782 duk_uint8_t buf[20 + 1];
38783
38784 /* Caller must ensure 'tv' is indeed a fastint! */
38786 v = DUK_TVAL_GET_FASTINT(tv);
38787
38788 /* XXX: There are no format strings in duk_config.h yet, could add
38789 * one for formatting duk_int64_t. For now, assumes "%lld" and that
38790 * "long long" type exists. Could also rely on C99 directly but that
38791 * won't work for older MSVC.
38792 */
38793 DUK_SPRINTF((char *) buf, "%lld", (long long) v);
38794 DUK__EMIT_CSTR(js_ctx, (const char *) buf);
38795}
38796#endif
38797
38798#if defined(DUK_USE_JX) || defined(DUK_USE_JC)
38799#if defined(DUK_USE_HEX_FASTPATH)
38800DUK_LOCAL duk_uint8_t *duk__json_enc_buffer_data_hex(const duk_uint8_t *src, duk_size_t src_len, duk_uint8_t *dst) {
38801 duk_uint8_t *q;
38802 duk_uint16_t *q16;
38804 duk_size_t i, len_safe;
38805#if !defined(DUK_USE_UNALIGNED_ACCESSES_POSSIBLE)
38806 duk_bool_t shift_dst;
38807#endif
38808
38809 /* Unlike in duk_hex_encode() 'dst' is not necessarily aligned by 2.
38810 * For platforms where unaligned accesses are not allowed, shift 'dst'
38811 * ahead by 1 byte to get alignment and then duk_memmove() the result
38812 * in place. The faster encoding loop makes up the difference.
38813 * There's always space for one extra byte because a terminator always
38814 * follows the hex data and that's been accounted for by the caller.
38815 */
38816
38817#if defined(DUK_USE_UNALIGNED_ACCESSES_POSSIBLE)
38818 q16 = (duk_uint16_t *) (void *) dst;
38819#else
38820 shift_dst = (duk_bool_t) (((duk_size_t) dst) & 0x01U);
38821 if (shift_dst) {
38822 DUK_DD(DUK_DDPRINT("unaligned accesses not possible, dst not aligned -> step to dst + 1"));
38823 q16 = (duk_uint16_t *) (void *) (dst + 1);
38824 } else {
38825 DUK_DD(DUK_DDPRINT("unaligned accesses not possible, dst is aligned"));
38826 q16 = (duk_uint16_t *) (void *) dst;
38827 }
38828 DUK_ASSERT((((duk_size_t) q16) & 0x01U) == 0);
38829#endif
38830
38831 len_safe = src_len & ~0x03U;
38832 for (i = 0; i < len_safe; i += 4) {
38833 q16[0] = duk_hex_enctab[src[i]];
38834 q16[1] = duk_hex_enctab[src[i + 1]];
38835 q16[2] = duk_hex_enctab[src[i + 2]];
38836 q16[3] = duk_hex_enctab[src[i + 3]];
38837 q16 += 4;
38838 }
38839 q = (duk_uint8_t *) q16;
38840
38841#if !defined(DUK_USE_UNALIGNED_ACCESSES_POSSIBLE)
38842 if (shift_dst) {
38843 q--;
38844 duk_memmove((void *) dst, (const void *) (dst + 1), 2 * len_safe);
38845 DUK_ASSERT(dst + 2 * len_safe == q);
38846 }
38847#endif
38848
38849 for (; i < src_len; i++) {
38850 x = src[i];
38851 *q++ = duk_lc_digits[x >> 4];
38852 *q++ = duk_lc_digits[x & 0x0f];
38853 }
38854
38855 return q;
38856}
38857#else /* DUK_USE_HEX_FASTPATH */
38858DUK_LOCAL duk_uint8_t *duk__json_enc_buffer_data_hex(const duk_uint8_t *src, duk_size_t src_len, duk_uint8_t *dst) {
38859 const duk_uint8_t *p;
38860 const duk_uint8_t *p_end;
38861 duk_uint8_t *q;
38863
38864 p = src;
38865 p_end = src + src_len;
38866 q = dst;
38867 while (p != p_end) {
38868 x = *p++;
38869 *q++ = duk_lc_digits[x >> 4];
38870 *q++ = duk_lc_digits[x & 0x0f];
38871 }
38872
38873 return q;
38874}
38875#endif /* DUK_USE_HEX_FASTPATH */
38876
38877DUK_LOCAL void duk__json_enc_buffer_data(duk_json_enc_ctx *js_ctx, duk_uint8_t *buf_data, duk_size_t buf_len) {
38878 duk_hthread *thr;
38879 duk_uint8_t *q;
38880 duk_size_t space;
38881
38882 thr = js_ctx->thr;
38883
38884 DUK_ASSERT(js_ctx->flag_ext_custom || js_ctx->flag_ext_compatible); /* caller checks */
38886
38887 /* Buffer values are encoded in (lowercase) hex to make the
38888 * binary data readable. Base64 or similar would be more
38889 * compact but less readable, and the point of JX/JC
38890 * variants is to be as useful to a programmer as possible.
38891 */
38892
38893 /* The #if defined() clutter here needs to handle the three
38894 * cases: (1) JX+JC, (2) JX only, (3) JC only.
38895 */
38896
38897 /* Note: space must cater for both JX and JC. */
38898 space = 9 + buf_len * 2 + 2;
38899 DUK_ASSERT(DUK_HBUFFER_MAX_BYTELEN <= 0x7ffffffeUL);
38900 DUK_ASSERT((space - 2) / 2 >= buf_len); /* overflow not possible, buffer limits */
38901 q = DUK_BW_ENSURE_GETPTR(thr, &js_ctx->bw, space);
38902
38903#if defined(DUK_USE_JX) && defined(DUK_USE_JC)
38904 if (js_ctx->flag_ext_custom)
38905#endif
38906#if defined(DUK_USE_JX)
38907 {
38908 *q++ = DUK_ASC_PIPE;
38909 q = duk__json_enc_buffer_data_hex(buf_data, buf_len, q);
38910 *q++ = DUK_ASC_PIPE;
38911
38912 }
38913#endif
38914#if defined(DUK_USE_JX) && defined(DUK_USE_JC)
38915 else
38916#endif
38917#if defined(DUK_USE_JC)
38918 {
38920 duk_memcpy((void *) q, (const void *) "{\"_buf\":\"", 9); /* len: 9 */
38921 q += 9;
38922 q = duk__json_enc_buffer_data_hex(buf_data, buf_len, q);
38923 *q++ = DUK_ASC_DOUBLEQUOTE;
38924 *q++ = DUK_ASC_RCURLY;
38925 }
38926#endif
38927
38928 DUK_BW_SET_PTR(thr, &js_ctx->bw, q);
38929}
38930
38933 (duk_uint8_t *) DUK_HBUFFER_GET_DATA_PTR(js_ctx->thr->heap, h),
38935}
38936#endif /* DUK_USE_JX || DUK_USE_JC */
38937
38938#if defined(DUK_USE_JSON_STRINGIFY_FASTPATH)
38939DUK_LOCAL void duk__json_enc_buffer_json_fastpath(duk_json_enc_ctx *js_ctx, duk_hbuffer *h) {
38940 duk_size_t i, n;
38941 const duk_uint8_t *buf;
38942 duk_uint8_t *q;
38943
38944 n = DUK_HBUFFER_GET_SIZE(h);
38945 if (n == 0) {
38947 return;
38948 }
38949
38950 DUK__EMIT_1(js_ctx, DUK_ASC_LCURLY);
38951
38952 /* Maximum encoded length with 32-bit index: 1 + 10 + 2 + 3 + 1 + 1 = 18,
38953 * with 64-bit index: 1 + 20 + 2 + 3 + 1 + 1 = 28. 32 has some slack.
38954 *
38955 * Note that because the output buffer is reallocated from time to time,
38956 * side effects (such as finalizers) affecting the buffer 'h' must be
38957 * disabled. This is the case in the JSON.stringify() fast path.
38958 */
38959
38960 buf = (const duk_uint8_t *) DUK_HBUFFER_GET_DATA_PTR(js_ctx->thr->heap, h);
38961 if (DUK_UNLIKELY(js_ctx->h_gap != NULL)) {
38962 for (i = 0; i < n; i++) {
38963 duk__json_enc_newline_indent(js_ctx, js_ctx->recursion_depth + 1);
38964 q = DUK_BW_ENSURE_GETPTR(js_ctx->thr, &js_ctx->bw, 32);
38965 q += DUK_SPRINTF((char *) q, "\"%lu\": %u,", (unsigned long) i, (unsigned int) buf[i]);
38966 DUK_BW_SET_PTR(js_ctx->thr, &js_ctx->bw, q);
38967 }
38968 } else {
38969 q = DUK_BW_GET_PTR(js_ctx->thr, &js_ctx->bw);
38970 for (i = 0; i < n; i++) {
38971 q = DUK_BW_ENSURE_RAW(js_ctx->thr, &js_ctx->bw, 32, q);
38972 q += DUK_SPRINTF((char *) q, "\"%lu\":%u,", (unsigned long) i, (unsigned int) buf[i]);
38973 }
38974 DUK_BW_SET_PTR(js_ctx->thr, &js_ctx->bw, q);
38975 }
38976 DUK__UNEMIT_1(js_ctx); /* eat trailing comma */
38977
38978 if (DUK_UNLIKELY(js_ctx->h_gap != NULL)) {
38980 }
38981 DUK__EMIT_1(js_ctx, DUK_ASC_RCURLY);
38982}
38983#endif /* DUK_USE_JSON_STRINGIFY_FASTPATH */
38984
38985#if defined(DUK_USE_JX) || defined(DUK_USE_JC)
38986DUK_LOCAL void duk__json_enc_pointer(duk_json_enc_ctx *js_ctx, void *ptr) {
38987 char buf[64]; /* XXX: how to figure correct size? */
38988 const char *fmt;
38989
38990 DUK_ASSERT(js_ctx->flag_ext_custom || js_ctx->flag_ext_compatible); /* caller checks */
38992
38993 duk_memzero(buf, sizeof(buf));
38994
38995 /* The #if defined() clutter here needs to handle the three
38996 * cases: (1) JX+JC, (2) JX only, (3) JC only.
38997 */
38998#if defined(DUK_USE_JX) && defined(DUK_USE_JC)
38999 if (js_ctx->flag_ext_custom)
39000#endif
39001#if defined(DUK_USE_JX)
39002 {
39003 fmt = ptr ? "(%p)" : "(null)";
39004 }
39005#endif
39006#if defined(DUK_USE_JX) && defined(DUK_USE_JC)
39007 else
39008#endif
39009#if defined(DUK_USE_JC)
39010 {
39012 fmt = ptr ? "{\"_ptr\":\"%p\"}" : "{\"_ptr\":\"null\"}";
39013 }
39014#endif
39015
39016 /* When ptr == NULL, the format argument is unused. */
39017 DUK_SNPRINTF(buf, sizeof(buf) - 1, fmt, ptr); /* must not truncate */
39018 DUK__EMIT_CSTR(js_ctx, buf);
39019}
39020#endif /* DUK_USE_JX || DUK_USE_JC */
39021
39022#if defined(DUK_USE_BUFFEROBJECT_SUPPORT)
39023#if defined(DUK_USE_JX) || defined(DUK_USE_JC)
39025 DUK_HBUFOBJ_ASSERT_VALID(h_bufobj);
39026
39027 if (h_bufobj->buf == NULL || !DUK_HBUFOBJ_VALID_SLICE(h_bufobj)) {
39029 } else {
39030 /* Handle both full and partial slice (as long as covered). */
39032 (duk_uint8_t *) DUK_HBUFOBJ_GET_SLICE_BASE(js_ctx->thr->heap, h_bufobj),
39033 (duk_size_t) h_bufobj->length);
39034 }
39035}
39036#endif /* DUK_USE_JX || DUK_USE_JC */
39037#endif /* DUK_USE_BUFFEROBJECT_SUPPORT */
39038
39039/* Indent helper. Calling code relies on js_ctx->recursion_depth also being
39040 * directly related to indent depth.
39042#if defined(DUK_USE_PREFER_SIZE)
39044 DUK_ASSERT(js_ctx->h_gap != NULL);
39045 DUK_ASSERT(DUK_HSTRING_GET_BYTELEN(js_ctx->h_gap) > 0); /* caller guarantees */
39046
39047 DUK__EMIT_1(js_ctx, 0x0a);
39048 while (depth-- > 0) {
39049 DUK__EMIT_HSTR(js_ctx, js_ctx->h_gap);
39050 }
39051}
39052#else /* DUK_USE_PREFER_SIZE */
39054 const duk_uint8_t *gap_data;
39055 duk_size_t gap_len;
39056 duk_size_t avail_bytes; /* bytes of indent available for copying */
39057 duk_size_t need_bytes; /* bytes of indent still needed */
39058 duk_uint8_t *p_start;
39059 duk_uint8_t *p;
39060
39061 DUK_ASSERT(js_ctx->h_gap != NULL);
39062 DUK_ASSERT(DUK_HSTRING_GET_BYTELEN(js_ctx->h_gap) > 0); /* caller guarantees */
39063
39064 DUK__EMIT_1(js_ctx, 0x0a);
39065 if (DUK_UNLIKELY(depth == 0)) {
39066 return;
39067 }
39068
39069 /* To handle deeper indents efficiently, make use of copies we've
39070 * already emitted. In effect we can emit a sequence of 1, 2, 4,
39071 * 8, etc copies, and then finish the last run. Byte counters
39072 * avoid multiply with gap_len on every loop.
39073 */
39074
39075 gap_data = (const duk_uint8_t *) DUK_HSTRING_GET_DATA(js_ctx->h_gap);
39076 gap_len = (duk_size_t) DUK_HSTRING_GET_BYTELEN(js_ctx->h_gap);
39077 DUK_ASSERT(gap_len > 0);
39078
39079 need_bytes = gap_len * depth;
39080 p = DUK_BW_ENSURE_GETPTR(js_ctx->thr, &js_ctx->bw, need_bytes);
39081 p_start = p;
39082
39083 duk_memcpy((void *) p, (const void *) gap_data, (size_t) gap_len);
39084 p += gap_len;
39085 avail_bytes = gap_len;
39086 DUK_ASSERT(need_bytes >= gap_len);
39087 need_bytes -= gap_len;
39088
39089 while (need_bytes >= avail_bytes) {
39090 duk_memcpy((void *) p, (const void *) p_start, (size_t) avail_bytes);
39091 p += avail_bytes;
39092 need_bytes -= avail_bytes;
39093 avail_bytes <<= 1;
39095
39096 DUK_ASSERT(need_bytes < avail_bytes); /* need_bytes may be zero */
39097 duk_memcpy((void *) p, (const void *) p_start, (size_t) need_bytes);
39098 p += need_bytes;
39099 /*avail_bytes += need_bytes*/
39100
39101 DUK_BW_SET_PTR(js_ctx->thr, &js_ctx->bw, p);
39102}
39103#endif /* DUK_USE_PREFER_SIZE */
39104
39105/* Shared entry handling for object/array serialization. */
39107 duk_hthread *thr = js_ctx->thr;
39108 duk_hobject *h_target;
39109 duk_uint_fast32_t i, n;
39110
39111 *entry_top = duk_get_top(thr);
39112
39115
39116 /* Loop check using a hybrid approach: a fixed-size visited[] array
39117 * with overflow in a loop check object.
39118 */
39119
39120 h_target = duk_known_hobject(thr, -1); /* object or array */
39121
39122 n = js_ctx->recursion_depth;
39125 }
39126 for (i = 0; i < n; i++) {
39127 if (DUK_UNLIKELY(js_ctx->visiting[i] == h_target)) {
39128 DUK_DD(DUK_DDPRINT("slow path loop detect"));
39130 DUK_WO_NORETURN(return;);
39131 }
39132 }
39134 js_ctx->visiting[js_ctx->recursion_depth] = h_target;
39135 } else {
39136 duk_push_sprintf(thr, DUK_STR_FMT_PTR, (void *) h_target);
39137 duk_dup_top(thr); /* -> [ ... voidp voidp ] */
39138 if (duk_has_prop(thr, js_ctx->idx_loop)) {
39140 DUK_WO_NORETURN(return;);
39141 }
39142 duk_push_true(thr); /* -> [ ... voidp true ] */
39143 duk_put_prop(thr, js_ctx->idx_loop); /* -> [ ... ] */
39144 }
39145
39146 /* C recursion check. */
39147
39148 DUK_ASSERT_DISABLE(js_ctx->recursion_depth >= 0); /* unsigned */
39149 DUK_ASSERT(js_ctx->recursion_depth <= js_ctx->recursion_limit);
39150 if (js_ctx->recursion_depth >= js_ctx->recursion_limit) {
39152 DUK_WO_NORETURN(return;);
39153 }
39154 js_ctx->recursion_depth++;
39155
39156 DUK_DDD(DUK_DDDPRINT("shared entry finished: top=%ld, loop=%!T",
39157 (long) duk_get_top(thr),
39158 (duk_tval *) duk_get_tval(thr, js_ctx->idx_loop)));
39159}
39160
39161/* Shared exit handling for object/array serialization. */
39163 duk_hthread *thr = js_ctx->thr;
39164 duk_hobject *h_target;
39165
39166 /* C recursion check. */
39167
39168 DUK_ASSERT(js_ctx->recursion_depth > 0);
39169 DUK_ASSERT(js_ctx->recursion_depth <= js_ctx->recursion_limit);
39170 js_ctx->recursion_depth--;
39171
39172 /* Loop check. */
39173
39174 h_target = duk_known_hobject(thr, *entry_top - 1); /* original target at entry_top - 1 */
39175
39177 /* Previous entry was inside visited[], nothing to do. */
39178 } else {
39179 duk_push_sprintf(thr, DUK_STR_FMT_PTR, (void *) h_target);
39180 duk_del_prop(thr, js_ctx->idx_loop); /* -> [ ... ] */
39181 }
39182
39183 /* Restore stack top after unbalanced code paths. */
39184 duk_set_top(thr, *entry_top);
39185
39186 DUK_DDD(DUK_DDDPRINT("shared entry finished: top=%ld, loop=%!T",
39187 (long) duk_get_top(thr),
39188 (duk_tval *) duk_get_tval(thr, js_ctx->idx_loop)));
39189}
39190
39191/* The JO(value) operation: encode object.
39192 *
39193 * Stack policy: [ object ] -> [ object ].
39194 */
39196 duk_hthread *thr = js_ctx->thr;
39197 duk_hstring *h_key;
39198 duk_idx_t entry_top;
39199 duk_idx_t idx_obj;
39200 duk_idx_t idx_keys;
39201 duk_bool_t emitted;
39202 duk_uarridx_t arr_len, i;
39203 duk_size_t prev_size;
39204
39205 DUK_DDD(DUK_DDDPRINT("duk__json_enc_object: obj=%!T", (duk_tval *) duk_get_tval(thr, -1)));
39206
39207 duk__json_enc_objarr_entry(js_ctx, &entry_top);
39208
39209 idx_obj = entry_top - 1;
39210
39211 if (js_ctx->idx_proplist >= 0) {
39212 idx_keys = js_ctx->idx_proplist;
39213 } else {
39214 /* XXX: would be nice to enumerate an object at specified index */
39215 duk_dup(thr, idx_obj);
39217 thr,
39218 DUK_ENUM_OWN_PROPERTIES_ONLY /*flags*/); /* [ ... target ] -> [ ... target keys ] */
39219 idx_keys = duk_require_normalize_index(thr, -1);
39220 /* leave stack unbalanced on purpose */
39221 }
39222
39223 DUK_DDD(DUK_DDDPRINT("idx_keys=%ld, h_keys=%!T", (long) idx_keys, (duk_tval *) duk_get_tval(thr, idx_keys)));
39224
39225 /* Steps 8-10 have been merged to avoid a "partial" variable. */
39226
39227 DUK__EMIT_1(js_ctx, DUK_ASC_LCURLY);
39228
39229 /* XXX: keys is an internal object with all keys to be processed
39230 * in its (gapless) array part. Because nobody can touch the keys
39231 * object, we could iterate its array part directly (keeping in mind
39232 * that it can be reallocated).
39233 */
39234
39235 arr_len = (duk_uarridx_t) duk_get_length(thr, idx_keys);
39236 emitted = 0;
39237 for (i = 0; i < arr_len; i++) {
39238 duk_get_prop_index(thr, idx_keys, i); /* -> [ ... key ] */
39239
39240 DUK_DDD(DUK_DDDPRINT("object property loop: holder=%!T, key=%!T",
39241 (duk_tval *) duk_get_tval(thr, idx_obj),
39242 (duk_tval *) duk_get_tval(thr, -1)));
39243
39244 h_key = duk_known_hstring(thr, -1);
39245 DUK_ASSERT(h_key != NULL);
39246 DUK_ASSERT(!DUK_HSTRING_HAS_SYMBOL(h_key)); /* proplist filtering; enum options */
39247
39248 prev_size = DUK_BW_GET_SIZE(js_ctx->thr, &js_ctx->bw);
39249 if (DUK_UNLIKELY(js_ctx->h_gap != NULL)) {
39251 duk__json_enc_key_autoquote(js_ctx, h_key);
39253 } else {
39254 duk__json_enc_key_autoquote(js_ctx, h_key);
39255 DUK__EMIT_1(js_ctx, DUK_ASC_COLON);
39256 }
39257
39258 /* [ ... key ] */
39259
39260 if (DUK_UNLIKELY(duk__json_enc_value(js_ctx, idx_obj) == 0)) {
39261 /* Value would yield 'undefined', so skip key altogether.
39262 * Side effects have already happened.
39263 */
39264 DUK_BW_SET_SIZE(js_ctx->thr, &js_ctx->bw, prev_size);
39265 } else {
39266 DUK__EMIT_1(js_ctx, DUK_ASC_COMMA);
39267 emitted = 1;
39268 }
39269
39270 /* [ ... ] */
39271 }
39272
39273 if (emitted) {
39274 DUK_ASSERT(*((duk_uint8_t *) DUK_BW_GET_PTR(js_ctx->thr, &js_ctx->bw) - 1) == DUK_ASC_COMMA);
39275 DUK__UNEMIT_1(js_ctx); /* eat trailing comma */
39276 if (DUK_UNLIKELY(js_ctx->h_gap != NULL)) {
39277 DUK_ASSERT(js_ctx->recursion_depth >= 1);
39278 duk__json_enc_newline_indent(js_ctx, js_ctx->recursion_depth - 1U);
39279 }
39281 DUK__EMIT_1(js_ctx, DUK_ASC_RCURLY);
39282
39283 duk__json_enc_objarr_exit(js_ctx, &entry_top);
39284
39285 DUK_ASSERT_TOP(thr, entry_top);
39286}
39287
39288/* The JA(value) operation: encode array.
39289 *
39290 * Stack policy: [ array ] -> [ array ].
39291 */
39293 duk_hthread *thr = js_ctx->thr;
39294 duk_idx_t entry_top;
39295 duk_idx_t idx_arr;
39296 duk_bool_t emitted;
39297 duk_uarridx_t i, arr_len;
39298
39299 DUK_DDD(DUK_DDDPRINT("duk__json_enc_array: array=%!T", (duk_tval *) duk_get_tval(thr, -1)));
39300
39301 duk__json_enc_objarr_entry(js_ctx, &entry_top);
39302
39303 idx_arr = entry_top - 1;
39304
39305 /* Steps 8-10 have been merged to avoid a "partial" variable. */
39306
39308
39309 arr_len = (duk_uarridx_t) duk_get_length(thr, idx_arr);
39310 emitted = 0;
39311 for (i = 0; i < arr_len; i++) {
39312 DUK_DDD(DUK_DDDPRINT("array entry loop: array=%!T, index=%ld, arr_len=%ld",
39313 (duk_tval *) duk_get_tval(thr, idx_arr),
39314 (long) i,
39315 (long) arr_len));
39316
39317 if (DUK_UNLIKELY(js_ctx->h_gap != NULL)) {
39318 DUK_ASSERT(js_ctx->recursion_depth >= 1);
39320 }
39321
39322 (void) duk_push_uint_to_hstring(thr, (duk_uint_t) i); /* -> [ ... key ] */
39323
39324 /* [ ... key ] */
39325
39326 if (DUK_UNLIKELY(duk__json_enc_value(js_ctx, idx_arr) == 0)) {
39327 /* Value would normally be omitted, replace with 'null'. */
39329 } else {
39330 ;
39331 }
39332
39333 /* [ ... ] */
39334
39335 DUK__EMIT_1(js_ctx, DUK_ASC_COMMA);
39336 emitted = 1;
39337 }
39338
39339 if (emitted) {
39340 DUK_ASSERT(*((duk_uint8_t *) DUK_BW_GET_PTR(js_ctx->thr, &js_ctx->bw) - 1) == DUK_ASC_COMMA);
39341 DUK__UNEMIT_1(js_ctx); /* eat trailing comma */
39342 if (DUK_UNLIKELY(js_ctx->h_gap != NULL)) {
39343 DUK_ASSERT(js_ctx->recursion_depth >= 1);
39344 duk__json_enc_newline_indent(js_ctx, js_ctx->recursion_depth - 1U);
39345 }
39348
39349 duk__json_enc_objarr_exit(js_ctx, &entry_top);
39350
39351 DUK_ASSERT_TOP(thr, entry_top);
39352}
39353
39354/* The Str(key, holder) operation.
39355 *
39356 * Stack policy: [ ... key ] -> [ ... ]
39357 */
39359 duk_hthread *thr = js_ctx->thr;
39360 duk_tval *tv;
39361 duk_tval *tv_holder;
39362 duk_tval *tv_key;
39364
39365 DUK_DDD(DUK_DDDPRINT("duk__json_enc_value: idx_holder=%ld, holder=%!T, key=%!T",
39366 (long) idx_holder,
39367 (duk_tval *) duk_get_tval(thr, idx_holder),
39368 (duk_tval *) duk_get_tval(thr, -1)));
39369
39370 tv_holder = DUK_GET_TVAL_POSIDX(thr, idx_holder);
39371 DUK_ASSERT(DUK_TVAL_IS_OBJECT(tv_holder));
39372 tv_key = DUK_GET_TVAL_NEGIDX(thr, -1);
39374 DUK_ASSERT(!DUK_HSTRING_HAS_SYMBOL(DUK_TVAL_GET_STRING(tv_key))); /* Caller responsible. */
39375 (void) duk_hobject_getprop(thr, tv_holder, tv_key);
39376
39377 /* -> [ ... key val ] */
39378
39379 DUK_DDD(DUK_DDDPRINT("value=%!T", (duk_tval *) duk_get_tval(thr, -1)));
39380
39381 /* Standard JSON checks for .toJSON() only for actual objects; for
39382 * example, setting Number.prototype.toJSON and then serializing a
39383 * number won't invoke the .toJSON() method. However, lightfuncs and
39384 * plain buffers mimic objects so we check for their .toJSON() method.
39385 */
39388 if (duk_is_callable(thr, -1)) { /* toJSON() can also be a lightfunc */
39389 DUK_DDD(DUK_DDDPRINT("value is object, has callable toJSON() -> call it"));
39390 /* XXX: duk_dup_unvalidated(thr, -2) etc. */
39391 duk_dup_m2(thr); /* -> [ ... key val toJSON val ] */
39392 duk_dup_m4(thr); /* -> [ ... key val toJSON val key ] */
39393 duk_call_method(thr, 1); /* -> [ ... key val val' ] */
39394 duk_remove_m2(thr); /* -> [ ... key val' ] */
39395 } else {
39396 duk_pop(thr); /* -> [ ... key val ] */
39397 }
39398 }
39399
39400 /* [ ... key val ] */
39401
39402 DUK_DDD(DUK_DDDPRINT("value=%!T", (duk_tval *) duk_get_tval(thr, -1)));
39403
39404 if (js_ctx->h_replacer) {
39405 /* XXX: Here a "slice copy" would be useful. */
39406 DUK_DDD(DUK_DDDPRINT("replacer is set, call replacer"));
39407 duk_push_hobject(thr, js_ctx->h_replacer); /* -> [ ... key val replacer ] */
39408 duk_dup(thr, idx_holder); /* -> [ ... key val replacer holder ] */
39409 duk_dup_m4(thr); /* -> [ ... key val replacer holder key ] */
39410 duk_dup_m4(thr); /* -> [ ... key val replacer holder key val ] */
39411 duk_call_method(thr, 2); /* -> [ ... key val val' ] */
39412 duk_remove_m2(thr); /* -> [ ... key val' ] */
39413 }
39414
39415 /* [ ... key val ] */
39416
39417 DUK_DDD(DUK_DDDPRINT("value=%!T", (duk_tval *) duk_get_tval(thr, -1)));
39418
39419 tv = DUK_GET_TVAL_NEGIDX(thr, -1);
39420 if (DUK_TVAL_IS_OBJECT(tv)) {
39421 duk_hobject *h;
39422
39423 h = DUK_TVAL_GET_OBJECT(tv);
39424 DUK_ASSERT(h != NULL);
39425
39426#if defined(DUK_USE_BUFFEROBJECT_SUPPORT)
39427#if defined(DUK_USE_JX) || defined(DUK_USE_JC)
39429 /* With JX/JC a bufferobject gets serialized specially. */
39430 duk_hbufobj *h_bufobj;
39431 h_bufobj = (duk_hbufobj *) h;
39432 DUK_HBUFOBJ_ASSERT_VALID(h_bufobj);
39433 duk__json_enc_bufobj(js_ctx, h_bufobj);
39434 goto pop2_emitted;
39435 }
39436 /* Otherwise bufferobjects get serialized as normal objects. */
39437#endif /* JX || JC */
39438#endif /* DUK_USE_BUFFEROBJECT_SUPPORT */
39440 switch (c) {
39442 DUK_DDD(DUK_DDDPRINT("value is a Number object -> coerce with ToNumber()"));
39443 duk_to_number_m1(thr);
39444 /* The coercion potentially invokes user .valueOf() and .toString()
39445 * but can't result in a function value because ToPrimitive() would
39446 * reject such a result: test-dev-json-stringify-coercion-1.js.
39447 */
39448 DUK_ASSERT(!duk_is_callable(thr, -1));
39449 break;
39450 }
39452 DUK_DDD(DUK_DDDPRINT("value is a String object -> coerce with ToString()"));
39453 duk_to_string(thr, -1);
39454 /* Same coercion behavior as for Number. */
39455 DUK_ASSERT(!duk_is_callable(thr, -1));
39456 break;
39457 }
39458#if defined(DUK_USE_JX) || defined(DUK_USE_JC)
39460#endif
39462 DUK_DDD(DUK_DDDPRINT("value is a Boolean/Buffer/Pointer object -> get internal value"));
39464 duk_remove_m2(thr);
39465 break;
39466 }
39467 default: {
39468 /* Normal object which doesn't get automatically coerced to a
39469 * primitive value. Functions are checked for specially. The
39470 * primitive value coercions for Number, String, Pointer, and
39471 * Boolean can't result in functions so suffices to check here.
39472 * Symbol objects are handled like plain objects (their primitive
39473 * value is NOT looked up like for e.g. String objects).
39474 */
39475 DUK_ASSERT(h != NULL);
39476 if (DUK_HOBJECT_IS_CALLABLE(h)) {
39477#if defined(DUK_USE_JX) || defined(DUK_USE_JC)
39479 /* We only get here when doing non-standard JSON encoding */
39480 DUK_DDD(DUK_DDDPRINT("-> function allowed, serialize to custom format"));
39483 goto pop2_emitted;
39484 } else {
39485 DUK_DDD(DUK_DDDPRINT("-> will result in undefined (function)"));
39486 goto pop2_undef;
39487 }
39488#else /* DUK_USE_JX || DUK_USE_JC */
39489 DUK_DDD(DUK_DDDPRINT("-> will result in undefined (function)"));
39490 goto pop2_undef;
39491#endif /* DUK_USE_JX || DUK_USE_JC */
39492 }
39493 }
39494 } /* end switch */
39495 }
39496
39497 /* [ ... key val ] */
39498
39499 DUK_DDD(DUK_DDDPRINT("value=%!T", (duk_tval *) duk_get_tval(thr, -1)));
39500
39501 if (duk_check_type_mask(thr, -1, js_ctx->mask_for_undefined)) {
39502 /* will result in undefined */
39503 DUK_DDD(DUK_DDDPRINT("-> will result in undefined (type mask check)"));
39504 goto pop2_undef;
39505 }
39506 tv = DUK_GET_TVAL_NEGIDX(thr, -1);
39507
39508 switch (DUK_TVAL_GET_TAG(tv)) {
39509#if defined(DUK_USE_JX) || defined(DUK_USE_JC)
39510 /* When JX/JC not in use, the type mask above will avoid this case if needed. */
39511 case DUK_TAG_UNDEFINED: {
39513 break;
39514 }
39515#endif
39516 case DUK_TAG_NULL: {
39518 break;
39519 }
39520 case DUK_TAG_BOOLEAN: {
39522 break;
39523 }
39524#if defined(DUK_USE_JX) || defined(DUK_USE_JC)
39525 /* When JX/JC not in use, the type mask above will avoid this case if needed. */
39526 case DUK_TAG_POINTER: {
39528 break;
39529 }
39530#endif /* DUK_USE_JX || DUK_USE_JC */
39531 case DUK_TAG_STRING: {
39533 DUK_ASSERT(h != NULL);
39535 goto pop2_undef;
39536 }
39537 duk__json_enc_quote_string(js_ctx, h);
39538 break;
39539 }
39540 case DUK_TAG_OBJECT: {
39542 DUK_ASSERT(h != NULL);
39543
39544 /* Function values are handled completely above (including
39545 * coercion results):
39546 */
39548
39549 if (duk_js_isarray_hobject(h)) {
39550 duk__json_enc_array(js_ctx);
39551 } else {
39552 duk__json_enc_object(js_ctx);
39553 }
39554 break;
39555 }
39556 /* Because plain buffers mimics Uint8Array, they have enumerable
39557 * index properties [0,byteLength[. Because JSON only serializes
39558 * enumerable own properties, no properties can be serialized for
39559 * plain buffers (all virtual properties are non-enumerable). However,
39560 * there may be a .toJSON() method which was already handled above.
39561 */
39562 case DUK_TAG_BUFFER: {
39563#if defined(DUK_USE_JX) || defined(DUK_USE_JC)
39564 if (js_ctx->flag_ext_custom_or_compatible) {
39566 break;
39567 }
39568#endif
39569
39570 /* Could implement a fastpath, but the fast path would need
39571 * to handle realloc side effects correctly.
39572 */
39573 duk_to_object(thr, -1);
39574 duk__json_enc_object(js_ctx);
39575 break;
39576 }
39577 case DUK_TAG_LIGHTFUNC: {
39578#if defined(DUK_USE_JX) || defined(DUK_USE_JC)
39579 /* We only get here when doing non-standard JSON encoding */
39582#else
39583 /* Standard JSON omits functions */
39585#endif
39586 break;
39587 }
39588#if defined(DUK_USE_FASTINT)
39589 case DUK_TAG_FASTINT:
39590 /* Number serialization has a significant impact relative to
39591 * other fast path code, so careful fast path for fastints.
39592 */
39593 duk__json_enc_fastint_tval(js_ctx, tv);
39594 break;
39595#endif
39596 default: {
39597 /* number */
39600 /* XXX: A fast path for usual integers would be useful when
39601 * fastint support is not enabled.
39602 */
39603 duk__json_enc_double(js_ctx);
39604 break;
39605 }
39606 }
39607
39608#if defined(DUK_USE_JX) || defined(DUK_USE_JC)
39609pop2_emitted:
39610#endif
39611 duk_pop_2(thr); /* [ ... key val ] -> [ ... ] */
39612 return 1; /* emitted */
39613
39614pop2_undef:
39615 duk_pop_2(thr); /* [ ... key val ] -> [ ... ] */
39616 return 0; /* not emitted */
39617}
39618
39619/* E5 Section 15.12.3, main algorithm, step 4.b.ii steps 1-4. */
39622
39623 /* XXX: some kind of external internal type checker?
39624 * - type mask; symbol flag; class mask
39625 */
39626 DUK_ASSERT(tv != NULL);
39627 if (DUK_TVAL_IS_STRING(tv)) {
39628 duk_hstring *h;
39629 h = DUK_TVAL_GET_STRING(tv);
39630 DUK_ASSERT(h != NULL);
39632 return 0;
39633 }
39634 return 1;
39635 } else if (DUK_TVAL_IS_NUMBER(tv)) {
39636 return 1;
39637 } else if (DUK_TVAL_IS_OBJECT(tv)) {
39638 duk_hobject *h;
39639 h = DUK_TVAL_GET_OBJECT(tv);
39640 DUK_ASSERT(h != NULL);
39643 return 1;
39644 }
39645 }
39646
39647 return 0;
39648}
39649
39650/*
39651 * JSON.stringify() fast path
39652 *
39653 * Otherwise supports full JSON, JX, and JC features, but bails out on any
39654 * possible side effect which might change the value being serialized. The
39655 * fast path can take advantage of the fact that the value being serialized
39656 * is unchanged so that we can walk directly through property tables etc.
39657 */
39658
39659#if defined(DUK_USE_JSON_STRINGIFY_FASTPATH)
39660DUK_LOCAL duk_bool_t duk__json_stringify_fast_value(duk_json_enc_ctx *js_ctx, duk_tval *tv) {
39661 duk_uint_fast32_t i, n;
39662
39663 DUK_DDD(DUK_DDDPRINT("stringify fast: %!T", tv));
39664
39665 DUK_ASSERT(js_ctx != NULL);
39666 DUK_ASSERT(js_ctx->thr != NULL);
39667
39668#if 0 /* disabled for now */
39669 restart_match:
39670#endif
39671
39672 DUK_ASSERT(tv != NULL);
39673
39674 switch (DUK_TVAL_GET_TAG(tv)) {
39675 case DUK_TAG_UNDEFINED: {
39676#if defined(DUK_USE_JX) || defined(DUK_USE_JC)
39677 if (js_ctx->flag_ext_custom || js_ctx->flag_ext_compatible) {
39679 break;
39680 } else {
39681 goto emit_undefined;
39682 }
39683#else
39684 goto emit_undefined;
39685#endif
39686 }
39687 case DUK_TAG_NULL: {
39689 break;
39690 }
39691 case DUK_TAG_BOOLEAN: {
39693 break;
39694 }
39695 case DUK_TAG_STRING: {
39696 duk_hstring *h;
39697 h = DUK_TVAL_GET_STRING(tv);
39698 DUK_ASSERT(h != NULL);
39700 goto emit_undefined;
39701 }
39702 duk__json_enc_quote_string(js_ctx, h);
39703 break;
39704 }
39705 case DUK_TAG_OBJECT: {
39706 duk_hobject *obj;
39707 duk_tval *tv_val;
39708 duk_bool_t emitted = 0;
39709 duk_uint32_t c_bit, c_all, c_array, c_unbox, c_undef, c_func, c_bufobj, c_object, c_abort;
39710
39711 /* For objects JSON.stringify() only looks for own, enumerable
39712 * properties which is nice for the fast path here.
39713 *
39714 * For arrays JSON.stringify() uses [[Get]] so it will actually
39715 * inherit properties during serialization! This fast path
39716 * supports gappy arrays as long as there's no actual inherited
39717 * property (which might be a getter etc).
39718 *
39719 * Since recursion only happens for objects, we can have both
39720 * recursion and loop checks here. We use a simple, depth-limited
39721 * loop check in the fast path because the object-based tracking
39722 * is very slow (when tested, it accounted for 50% of fast path
39723 * execution time for input data with a lot of small objects!).
39724 */
39725
39726 /* XXX: for real world code, could just ignore array inheritance
39727 * and only look at array own properties.
39728 */
39729
39730 /* We rely on a few object flag / class number relationships here,
39731 * assert for them.
39732 */
39733
39734 obj = DUK_TVAL_GET_OBJECT(tv);
39735 DUK_ASSERT(obj != NULL);
39737
39738 /* Once recursion depth is increased, exit path must decrease
39739 * it (though it's OK to abort the fast path).
39740 */
39741
39742 DUK_ASSERT_DISABLE(js_ctx->recursion_depth >= 0); /* unsigned */
39743 DUK_ASSERT(js_ctx->recursion_depth <= js_ctx->recursion_limit);
39744 if (js_ctx->recursion_depth >= js_ctx->recursion_limit) {
39745 DUK_DD(DUK_DDPRINT("fast path recursion limit"));
39747 DUK_WO_NORETURN(return 0;);
39748 }
39749
39750 for (i = 0, n = (duk_uint_fast32_t) js_ctx->recursion_depth; i < n; i++) {
39751 if (DUK_UNLIKELY(js_ctx->visiting[i] == obj)) {
39752 DUK_DD(DUK_DDPRINT("fast path loop detect"));
39754 DUK_WO_NORETURN(return 0;);
39755 }
39756 }
39757
39758 /* Guaranteed by recursion_limit setup so we don't have to
39759 * check twice.
39760 */
39762 js_ctx->visiting[js_ctx->recursion_depth] = obj;
39763 js_ctx->recursion_depth++;
39764
39765 /* If object has a .toJSON() property, we can't be certain
39766 * that it wouldn't mutate any value arbitrarily, so bail
39767 * out of the fast path.
39768 *
39769 * If an object is a Proxy we also can't avoid side effects
39770 * so abandon.
39771 */
39772 /* XXX: non-callable .toJSON() doesn't need to cause an abort
39773 * but does at the moment, probably not worth fixing.
39774 */
39775 if (duk_hobject_hasprop_raw(js_ctx->thr, obj, DUK_HTHREAD_STRING_TO_JSON(js_ctx->thr)) ||
39776 DUK_HOBJECT_IS_PROXY(obj)) {
39777 DUK_DD(DUK_DDPRINT("object has a .toJSON property or object is a Proxy, abort fast path"));
39778 goto abort_fastpath;
39779 }
39780
39781 /* We could use a switch-case for the class number but it turns out
39782 * a small if-else ladder on class masks is better. The if-ladder
39783 * should be in order of relevancy.
39784 */
39785
39786 /* XXX: move masks to js_ctx? they don't change during one
39787 * fast path invocation.
39788 */
39790#if defined(DUK_USE_JX) || defined(DUK_USE_JC)
39791 if (js_ctx->flag_ext_custom_or_compatible) {
39792 c_all = DUK_HOBJECT_CMASK_ALL;
39793 c_array = DUK_HOBJECT_CMASK_ARRAY;
39795 DUK_HOBJECT_CMASK_POINTER; /* Symbols are not unboxed. */
39798 c_undef = 0;
39799 c_abort = 0;
39800 c_object = c_all & ~(c_array | c_unbox | c_func | c_bufobj | c_undef | c_abort);
39801 } else
39802#endif
39803 {
39804 c_all = DUK_HOBJECT_CMASK_ALL;
39805 c_array = DUK_HOBJECT_CMASK_ARRAY;
39807 DUK_HOBJECT_CMASK_BOOLEAN; /* Symbols are not unboxed. */
39808 c_func = 0;
39809 c_bufobj = 0;
39811 /* As the fast path doesn't currently properly support
39812 * duk_hbufobj virtual properties, abort fast path if
39813 * we encounter them in plain JSON mode.
39814 */
39816 c_object = c_all & ~(c_array | c_unbox | c_func | c_bufobj | c_undef | c_abort);
39817 }
39818
39819 c_bit = (duk_uint32_t) DUK_HOBJECT_GET_CLASS_MASK(obj);
39820 if (c_bit & c_object) {
39821 /* All other object types. */
39822 DUK__EMIT_1(js_ctx, DUK_ASC_LCURLY);
39823
39824 /* A non-Array object should not have an array part in practice.
39825 * But since it is supported internally (and perhaps used at some
39826 * point), check and abandon if that's the case.
39827 */
39828 if (DUK_HOBJECT_HAS_ARRAY_PART(obj)) {
39829 DUK_DD(DUK_DDPRINT("non-Array object has array part, abort fast path"));
39830 goto abort_fastpath;
39831 }
39832
39833 for (i = 0; i < (duk_uint_fast32_t) DUK_HOBJECT_GET_ENEXT(obj); i++) {
39834 duk_hstring *k;
39835 duk_size_t prev_size;
39836
39837 k = DUK_HOBJECT_E_GET_KEY(js_ctx->thr->heap, obj, i);
39838 if (!k) {
39839 continue;
39840 }
39841 if (DUK_HSTRING_HAS_ARRIDX(k)) {
39842 /* If an object has array index keys we would need
39843 * to sort them into the ES2015 enumeration order to
39844 * be consistent with the slow path. Abort the fast
39845 * path and handle in the slow path for now.
39846 */
39847 DUK_DD(DUK_DDPRINT("property key is an array index, abort fast path"));
39848 goto abort_fastpath;
39849 }
39850 if (!DUK_HOBJECT_E_SLOT_IS_ENUMERABLE(js_ctx->thr->heap, obj, i)) {
39851 continue;
39852 }
39853 if (DUK_HOBJECT_E_SLOT_IS_ACCESSOR(js_ctx->thr->heap, obj, i)) {
39854 /* Getter might have arbitrary side effects,
39855 * so bail out.
39856 */
39857 DUK_DD(DUK_DDPRINT("property is an accessor, abort fast path"));
39858 goto abort_fastpath;
39859 }
39861 continue;
39862 }
39863
39864 tv_val = DUK_HOBJECT_E_GET_VALUE_TVAL_PTR(js_ctx->thr->heap, obj, i);
39865
39866 prev_size = DUK_BW_GET_SIZE(js_ctx->thr, &js_ctx->bw);
39867 if (DUK_UNLIKELY(js_ctx->h_gap != NULL)) {
39869 duk__json_enc_key_autoquote(js_ctx, k);
39871 } else {
39872 duk__json_enc_key_autoquote(js_ctx, k);
39873 DUK__EMIT_1(js_ctx, DUK_ASC_COLON);
39874 }
39875
39876 if (duk__json_stringify_fast_value(js_ctx, tv_val) == 0) {
39877 DUK_DD(DUK_DDPRINT("prop value not supported, rewind key and colon"));
39878 DUK_BW_SET_SIZE(js_ctx->thr, &js_ctx->bw, prev_size);
39879 } else {
39880 DUK__EMIT_1(js_ctx, DUK_ASC_COMMA);
39881 emitted = 1;
39882 }
39883 }
39884
39885 /* If any non-Array value had enumerable virtual own
39886 * properties, they should be serialized here (actually,
39887 * before the explicit properties). Standard types don't.
39888 */
39889
39890 if (emitted) {
39891 DUK_ASSERT(*((duk_uint8_t *) DUK_BW_GET_PTR(js_ctx->thr, &js_ctx->bw) - 1) == DUK_ASC_COMMA);
39892 DUK__UNEMIT_1(js_ctx); /* eat trailing comma */
39893 if (DUK_UNLIKELY(js_ctx->h_gap != NULL)) {
39894 DUK_ASSERT(js_ctx->recursion_depth >= 1);
39895 duk__json_enc_newline_indent(js_ctx, js_ctx->recursion_depth - 1U);
39896 }
39897 }
39898 DUK__EMIT_1(js_ctx, DUK_ASC_RCURLY);
39899 } else if (c_bit & c_array) {
39900 duk_uint_fast32_t arr_len;
39901 duk_uint_fast32_t asize;
39902
39904
39905 /* Assume arrays are dense in the fast path. */
39906 if (!DUK_HOBJECT_HAS_ARRAY_PART(obj)) {
39907 DUK_DD(DUK_DDPRINT("Array object is sparse, abort fast path"));
39908 goto abort_fastpath;
39909 }
39910
39911 arr_len = (duk_uint_fast32_t) ((duk_harray *) obj)->length;
39913 /* Array part may be larger than 'length'; if so, iterate
39914 * only up to array 'length'. Array part may also be smaller
39915 * than 'length' in some cases.
39916 */
39917 for (i = 0; i < arr_len; i++) {
39918 duk_tval *tv_arrval;
39919 duk_hstring *h_tmp;
39920 duk_bool_t has_inherited;
39921
39922 if (DUK_UNLIKELY(js_ctx->h_gap != NULL)) {
39924 }
39925
39926 if (DUK_LIKELY(i < asize)) {
39927 tv_arrval = DUK_HOBJECT_A_GET_VALUE_PTR(js_ctx->thr->heap, obj, i);
39928 if (DUK_LIKELY(!DUK_TVAL_IS_UNUSED(tv_arrval))) {
39929 /* Expected case: element is present. */
39930 if (duk__json_stringify_fast_value(js_ctx, tv_arrval) == 0) {
39932 }
39933 goto elem_done;
39934 }
39935 }
39936
39937 /* Gap in array; check for inherited property,
39938 * bail out if one exists. This should be enough
39939 * to support gappy arrays for all practical code.
39940 */
39941
39942 h_tmp = duk_push_uint_to_hstring(js_ctx->thr, (duk_uint_t) i);
39943 has_inherited = duk_hobject_hasprop_raw(js_ctx->thr, obj, h_tmp);
39944 duk_pop(js_ctx->thr);
39945 if (has_inherited) {
39946 DUK_D(DUK_DPRINT("gap in array, conflicting inherited property, abort fast path"));
39947 goto abort_fastpath;
39948 }
39949
39950 /* Ordinary gap, undefined encodes to 'null' in
39951 * standard JSON, but JX/JC use their form for
39952 * undefined to better preserve the typing.
39953 */
39954 DUK_D(DUK_DPRINT("gap in array, no conflicting inherited property, remain on fast path"));
39955#if defined(DUK_USE_JX)
39957#else
39959#endif
39960 /* fall through */
39961
39962 elem_done:
39963 DUK__EMIT_1(js_ctx, DUK_ASC_COMMA);
39964 emitted = 1;
39965 }
39966
39967 if (emitted) {
39968 DUK_ASSERT(*((duk_uint8_t *) DUK_BW_GET_PTR(js_ctx->thr, &js_ctx->bw) - 1) == DUK_ASC_COMMA);
39969 DUK__UNEMIT_1(js_ctx); /* eat trailing comma */
39970 if (DUK_UNLIKELY(js_ctx->h_gap != NULL)) {
39971 DUK_ASSERT(js_ctx->recursion_depth >= 1);
39972 duk__json_enc_newline_indent(js_ctx, js_ctx->recursion_depth - 1U);
39973 }
39974 }
39976 } else if (c_bit & c_unbox) {
39977 /* Certain boxed types are required to go through
39978 * automatic unboxing. Rely on internal value being
39979 * sane (to avoid infinite recursion).
39980 */
39981 DUK_ASSERT((c_bit & DUK_HOBJECT_CMASK_SYMBOL) == 0); /* Symbols are not unboxed. */
39982
39983#if 1
39984 /* The code below is incorrect if .toString() or .valueOf() have
39985 * have been overridden. The correct approach would be to look up
39986 * the method(s) and if they resolve to the built-in function we
39987 * can safely bypass it and look up the internal value directly.
39988 * Unimplemented for now, abort fast path for boxed values.
39989 */
39990 goto abort_fastpath;
39991#else /* disabled */
39992 /* Disabled until fixed, see above. */
39993 duk_tval *tv_internal;
39994
39995 DUK_DD(DUK_DDPRINT("auto unboxing in fast path"));
39996
39997 tv_internal = duk_hobject_get_internal_value_tval_ptr(js_ctx->thr->heap, obj);
39998 DUK_ASSERT(tv_internal != NULL);
39999 DUK_ASSERT(DUK_TVAL_IS_STRING(tv_internal) || DUK_TVAL_IS_NUMBER(tv_internal) ||
40000 DUK_TVAL_IS_BOOLEAN(tv_internal) || DUK_TVAL_IS_POINTER(tv_internal));
40001
40002 tv = tv_internal;
40003 DUK_ASSERT(js_ctx->recursion_depth > 0);
40004 js_ctx->recursion_depth--; /* required to keep recursion depth correct */
40005 goto restart_match;
40006#endif /* disabled */
40007#if defined(DUK_USE_JX) || defined(DUK_USE_JC)
40008 } else if (c_bit & c_func) {
40010#if defined(DUK_USE_BUFFEROBJECT_SUPPORT)
40011 } else if (c_bit & c_bufobj) {
40012 duk__json_enc_bufobj(js_ctx, (duk_hbufobj *) obj);
40013#endif
40014#endif
40015 } else if (c_bit & c_abort) {
40016 DUK_DD(DUK_DDPRINT("abort fast path for unsupported type"));
40017 goto abort_fastpath;
40018 } else {
40019 DUK_ASSERT((c_bit & c_undef) != 0);
40020
40021 /* Must decrease recursion depth before returning. */
40022 DUK_ASSERT(js_ctx->recursion_depth > 0);
40023 DUK_ASSERT(js_ctx->recursion_depth <= js_ctx->recursion_limit);
40024 js_ctx->recursion_depth--;
40025 goto emit_undefined;
40026 }
40027
40028 DUK_ASSERT(js_ctx->recursion_depth > 0);
40029 DUK_ASSERT(js_ctx->recursion_depth <= js_ctx->recursion_limit);
40030 js_ctx->recursion_depth--;
40031 break;
40032 }
40033 case DUK_TAG_BUFFER: {
40034 /* Plain buffers are treated like Uint8Arrays: they have
40035 * enumerable indices. Other virtual properties are not
40036 * enumerable, and inherited properties are not serialized.
40037 * However, there can be a replacer (not relevant here) or
40038 * a .toJSON() method (which we need to check for explicitly).
40039 */
40040
40041#if defined(DUK_USE_BUFFEROBJECT_SUPPORT)
40042 if (duk_hobject_hasprop_raw(js_ctx->thr,
40044 DUK_HTHREAD_STRING_TO_JSON(js_ctx->thr))) {
40045 DUK_DD(DUK_DDPRINT("value is a plain buffer and there's an inherited .toJSON, abort fast path"));
40046 goto abort_fastpath;
40047 }
40048#endif
40049
40050#if defined(DUK_USE_JX) || defined(DUK_USE_JC)
40051 if (js_ctx->flag_ext_custom_or_compatible) {
40053 break;
40054 }
40055#endif
40056
40057 /* Plain buffers mimic Uint8Arrays, and have enumerable index
40058 * properties.
40059 */
40060 duk__json_enc_buffer_json_fastpath(js_ctx, DUK_TVAL_GET_BUFFER(tv));
40061 break;
40062 }
40063 case DUK_TAG_POINTER: {
40064#if defined(DUK_USE_JX) || defined(DUK_USE_JC)
40065 if (js_ctx->flag_ext_custom_or_compatible) {
40067 break;
40068 } else {
40069 goto emit_undefined;
40070 }
40071#else
40072 goto emit_undefined;
40073#endif
40074 }
40075 case DUK_TAG_LIGHTFUNC: {
40076 /* A lightfunc might also inherit a .toJSON() so just bail out. */
40077 /* XXX: Could just lookup .toJSON() and continue in fast path,
40078 * as it would almost never be defined.
40079 */
40080 DUK_DD(DUK_DDPRINT("value is a lightfunc, abort fast path"));
40081 goto abort_fastpath;
40082 }
40083#if defined(DUK_USE_FASTINT)
40084 case DUK_TAG_FASTINT: {
40085 /* Number serialization has a significant impact relative to
40086 * other fast path code, so careful fast path for fastints.
40087 */
40088 duk__json_enc_fastint_tval(js_ctx, tv);
40089 break;
40090 }
40091#endif
40092 default: {
40093 /* XXX: A fast path for usual integers would be useful when
40094 * fastint support is not enabled.
40095 */
40098
40099 /* XXX: Stack discipline is annoying, could be changed in numconv. */
40100 duk_push_tval(js_ctx->thr, tv);
40101 duk__json_enc_double(js_ctx);
40102 duk_pop(js_ctx->thr);
40103
40104#if 0
40105 /* Could also rely on native sprintf(), but it will handle
40106 * values like NaN, Infinity, -0, exponent notation etc in
40107 * a JSON-incompatible way.
40108 */
40109 duk_double_t d;
40110 char buf[64];
40111
40113 d = DUK_TVAL_GET_DOUBLE(tv);
40114 DUK_SPRINTF(buf, "%lg", d);
40115 DUK__EMIT_CSTR(js_ctx, buf);
40116#endif
40117 }
40118 }
40119 return 1; /* not undefined */
40120
40121emit_undefined:
40122 return 0; /* value was undefined/unsupported */
40123
40124abort_fastpath:
40125 /* Error message doesn't matter: the error is ignored anyway. */
40126 DUK_DD(DUK_DDPRINT("aborting fast path"));
40127 DUK_ERROR_INTERNAL(js_ctx->thr);
40128 DUK_WO_NORETURN(return 0;);
40129}
40130
40131DUK_LOCAL duk_ret_t duk__json_stringify_fast(duk_hthread *thr, void *udata) {
40132 duk_json_enc_ctx *js_ctx;
40133 duk_tval *tv;
40134
40135 DUK_ASSERT(thr != NULL);
40136 DUK_ASSERT(udata != NULL);
40137
40138 js_ctx = (duk_json_enc_ctx *) udata;
40139 DUK_ASSERT(js_ctx != NULL);
40140
40141 tv = DUK_GET_TVAL_NEGIDX(thr, -1);
40142 if (duk__json_stringify_fast_value(js_ctx, tv) == 0) {
40143 DUK_DD(DUK_DDPRINT("top level value not supported, fail fast path"));
40144 DUK_DCERROR_TYPE_INVALID_ARGS(thr); /* Error message is ignored, so doesn't matter. */
40145 }
40146
40147 return 0;
40148}
40149#endif /* DUK_USE_JSON_STRINGIFY_FASTPATH */
40150
40151/*
40152 * Top level wrappers
40153 */
40154
40156void duk_bi_json_parse_helper(duk_hthread *thr, duk_idx_t idx_value, duk_idx_t idx_reviver, duk_small_uint_t flags) {
40157 duk_json_dec_ctx js_ctx_alloc;
40158 duk_json_dec_ctx *js_ctx = &js_ctx_alloc;
40159 duk_hstring *h_text;
40160#if defined(DUK_USE_ASSERTIONS)
40161 duk_idx_t entry_top = duk_get_top(thr);
40162#endif
40163
40164 /* negative top-relative indices not allowed now */
40165 DUK_ASSERT(idx_value == DUK_INVALID_INDEX || idx_value >= 0);
40166 DUK_ASSERT(idx_reviver == DUK_INVALID_INDEX || idx_reviver >= 0);
40167
40168 DUK_DDD(DUK_DDDPRINT("JSON parse start: text=%!T, reviver=%!T, flags=0x%08lx, stack_top=%ld",
40169 (duk_tval *) duk_get_tval(thr, idx_value),
40170 (duk_tval *) duk_get_tval(thr, idx_reviver),
40171 (unsigned long) flags,
40172 (long) duk_get_top(thr)));
40173
40174 duk_memzero(&js_ctx_alloc, sizeof(js_ctx_alloc));
40175 js_ctx->thr = thr;
40176#if defined(DUK_USE_EXPLICIT_NULL_INIT)
40177 /* nothing now */
40178#endif
40180 DUK_ASSERT(js_ctx->recursion_depth == 0);
40181
40182 /* Flag handling currently assumes that flags are consistent. This is OK
40183 * because the call sites are now strictly controlled.
40184 */
40185
40186 js_ctx->flags = flags;
40187#if defined(DUK_USE_JX)
40188 js_ctx->flag_ext_custom = flags & DUK_JSON_FLAG_EXT_CUSTOM;
40189#endif
40190#if defined(DUK_USE_JC)
40192#endif
40193#if defined(DUK_USE_JX) || defined(DUK_USE_JC)
40195#endif
40196
40197 h_text = duk_to_hstring(thr, idx_value); /* coerce in-place; rejects Symbols */
40198 DUK_ASSERT(h_text != NULL);
40199
40200 /* JSON parsing code is allowed to read [p_start,p_end]: p_end is
40201 * valid and points to the string NUL terminator (which is always
40202 * guaranteed for duk_hstrings.
40203 */
40204 js_ctx->p_start = (const duk_uint8_t *) DUK_HSTRING_GET_DATA(h_text);
40205 js_ctx->p = js_ctx->p_start;
40206 js_ctx->p_end = ((const duk_uint8_t *) DUK_HSTRING_GET_DATA(h_text)) + DUK_HSTRING_GET_BYTELEN(h_text);
40207 DUK_ASSERT(*(js_ctx->p_end) == 0x00);
40208
40209 duk__json_dec_value(js_ctx); /* -> [ ... value ] */
40210 DUK_ASSERT(js_ctx->recursion_depth == 0);
40211
40212 /* Trailing whitespace has been eaten by duk__json_dec_value(), so if
40213 * we're not at end of input here, it's a SyntaxError.
40214 */
40215
40216 if (js_ctx->p != js_ctx->p_end) {
40218 }
40219
40220 if (duk_is_callable(thr, idx_reviver)) {
40221 DUK_DDD(DUK_DDDPRINT("applying reviver: %!T", (duk_tval *) duk_get_tval(thr, idx_reviver)));
40222
40223 js_ctx->idx_reviver = idx_reviver;
40224
40225 duk_push_object(thr);
40226 duk_dup_m2(thr); /* -> [ ... val root val ] */
40227 duk_put_prop_stridx_short(thr, -2, DUK_STRIDX_EMPTY_STRING); /* default attrs ok */
40228 duk_push_hstring_stridx(thr, DUK_STRIDX_EMPTY_STRING); /* -> [ ... val root "" ] */
40229
40230 DUK_DDD(DUK_DDDPRINT("start reviver walk, root=%!T, name=%!T",
40231 (duk_tval *) duk_get_tval(thr, -2),
40232 (duk_tval *) duk_get_tval(thr, -1)));
40233
40234 DUK_ASSERT(js_ctx->recursion_depth == 0);
40235 duk__json_dec_reviver_walk(js_ctx); /* [ ... val root "" ] -> [ ... val val' ] */
40236 DUK_ASSERT(js_ctx->recursion_depth == 0);
40237 duk_remove_m2(thr); /* -> [ ... val' ] */
40238 } else {
40239 DUK_DDD(
40240 DUK_DDDPRINT("reviver does not exist or is not callable: %!T", (duk_tval *) duk_get_tval(thr, idx_reviver)));
40241 }
40242
40243 /* Final result is at stack top. */
40245 DUK_DDD(DUK_DDDPRINT("JSON parse end: text=%!T, reviver=%!T, flags=0x%08lx, result=%!T, stack_top=%ld",
40246 (duk_tval *) duk_get_tval(thr, idx_value),
40247 (duk_tval *) duk_get_tval(thr, idx_reviver),
40248 (unsigned long) flags,
40249 (duk_tval *) duk_get_tval(thr, -1),
40250 (long) duk_get_top(thr)));
40251
40252 DUK_ASSERT(duk_get_top(thr) == entry_top + 1);
40253}
40254
40257 duk_idx_t idx_value,
40258 duk_idx_t idx_replacer,
40259 duk_idx_t idx_space,
40260 duk_small_uint_t flags) {
40261 duk_json_enc_ctx js_ctx_alloc;
40262 duk_json_enc_ctx *js_ctx = &js_ctx_alloc;
40263 duk_hobject *h;
40264 duk_idx_t idx_holder;
40265 duk_idx_t entry_top;
40266
40267 /* negative top-relative indices not allowed now */
40268 DUK_ASSERT(idx_value == DUK_INVALID_INDEX || idx_value >= 0);
40269 DUK_ASSERT(idx_replacer == DUK_INVALID_INDEX || idx_replacer >= 0);
40270 DUK_ASSERT(idx_space == DUK_INVALID_INDEX || idx_space >= 0);
40271
40272 DUK_DDD(DUK_DDDPRINT("JSON stringify start: value=%!T, replacer=%!T, space=%!T, flags=0x%08lx, stack_top=%ld",
40273 (duk_tval *) duk_get_tval(thr, idx_value),
40274 (duk_tval *) duk_get_tval(thr, idx_replacer),
40275 (duk_tval *) duk_get_tval(thr, idx_space),
40276 (unsigned long) flags,
40277 (long) duk_get_top(thr)));
40278
40279 entry_top = duk_get_top(thr);
40280
40281 /*
40282 * Context init
40283 */
40284
40285 duk_memzero(&js_ctx_alloc, sizeof(js_ctx_alloc));
40286 js_ctx->thr = thr;
40287#if defined(DUK_USE_EXPLICIT_NULL_INIT)
40288 js_ctx->h_replacer = NULL;
40289 js_ctx->h_gap = NULL;
40290#endif
40291 js_ctx->idx_proplist = -1;
40292
40293 /* Flag handling currently assumes that flags are consistent. This is OK
40294 * because the call sites are now strictly controlled.
40295 */
40296
40297 js_ctx->flags = flags;
40298 js_ctx->flag_ascii_only = flags & DUK_JSON_FLAG_ASCII_ONLY;
40300#if defined(DUK_USE_JX)
40301 js_ctx->flag_ext_custom = flags & DUK_JSON_FLAG_EXT_CUSTOM;
40302#endif
40303#if defined(DUK_USE_JC)
40305#endif
40306#if defined(DUK_USE_JX) || defined(DUK_USE_JC)
40308#endif
40309
40310 /* The #if defined() clutter here handles the JX/JC enable/disable
40311 * combinations properly.
40312 */
40313#if defined(DUK_USE_JX) || defined(DUK_USE_JC)
40314 js_ctx->stridx_custom_undefined = DUK_STRIDX_LC_NULL; /* standard JSON; array gaps */
40315#if defined(DUK_USE_JX)
40316 if (flags & DUK_JSON_FLAG_EXT_CUSTOM) {
40321 js_ctx->stridx_custom_function =
40323 }
40324#endif /* DUK_USE_JX */
40325#if defined(DUK_USE_JX) && defined(DUK_USE_JC)
40326 else
40327#endif /* DUK_USE_JX && DUK_USE_JC */
40328#if defined(DUK_USE_JC)
40329 if (js_ctx->flags & DUK_JSON_FLAG_EXT_COMPATIBLE) {
40335 }
40336#endif /* DUK_USE_JC */
40337#endif /* DUK_USE_JX || DUK_USE_JC */
40338
40339#if defined(DUK_USE_JX) || defined(DUK_USE_JC)
40341 DUK_ASSERT(js_ctx->mask_for_undefined == 0); /* already zero */
40342 } else
40343#endif /* DUK_USE_JX || DUK_USE_JC */
40344 {
40345 /* Plain buffer is treated like ArrayBuffer and serialized.
40346 * Lightfuncs are treated like objects, but JSON explicitly
40347 * skips serializing Function objects so we can just reject
40348 * lightfuncs here.
40349 */
40351 }
40352
40354
40355 js_ctx->idx_loop = duk_push_bare_object(thr);
40356 DUK_ASSERT(js_ctx->idx_loop >= 0);
40357
40358 /* [ ... buf loop ] */
40359
40360 /*
40361 * Process replacer/proplist (2nd argument to JSON.stringify)
40362 */
40363
40364 h = duk_get_hobject(thr, idx_replacer);
40365 if (h != NULL) {
40366 if (DUK_HOBJECT_IS_CALLABLE(h)) {
40367 js_ctx->h_replacer = h;
40368 } else if (duk_js_isarray_hobject(h)) {
40369 /* Here the specification requires correct array index enumeration
40370 * which is a bit tricky for sparse arrays (it is handled by the
40371 * enum setup code). We now enumerate ancestors too, although the
40372 * specification is not very clear on whether that is required.
40373 */
40374
40375 duk_uarridx_t plist_idx = 0;
40376 duk_small_uint_t enum_flags;
40377
40378 js_ctx->idx_proplist = duk_push_bare_array(thr);
40379
40380 enum_flags = DUK_ENUM_ARRAY_INDICES_ONLY | DUK_ENUM_SORT_ARRAY_INDICES; /* expensive flag */
40381 duk_enum(thr, idx_replacer, enum_flags);
40382 while (duk_next(thr, -1 /*enum_index*/, 1 /*get_value*/)) {
40383 /* [ ... proplist enum_obj key val ] */
40385 /* XXX: duplicates should be eliminated here */
40386 DUK_DDD(DUK_DDDPRINT("proplist enum: key=%!T, val=%!T --> accept",
40387 (duk_tval *) duk_get_tval(thr, -2),
40388 (duk_tval *) duk_get_tval(thr, -1)));
40389 duk_to_string(thr, -1); /* extra coercion of strings is OK */
40390 duk_put_prop_index(thr, -4, plist_idx); /* -> [ ... proplist enum_obj key ] */
40391 plist_idx++;
40392 duk_pop(thr);
40393 } else {
40394 DUK_DDD(DUK_DDDPRINT("proplist enum: key=%!T, val=%!T --> reject",
40395 (duk_tval *) duk_get_tval(thr, -2),
40396 (duk_tval *) duk_get_tval(thr, -1)));
40397 duk_pop_2(thr);
40398 }
40399 }
40400 duk_pop(thr); /* pop enum */
40401
40402 /* [ ... proplist ] */
40403 }
40404 }
40405
40406 /* [ ... buf loop (proplist) ] */
40407
40408 /*
40409 * Process space (3rd argument to JSON.stringify)
40410 */
40411
40412 h = duk_get_hobject(thr, idx_space);
40413 if (h != NULL) {
40415 if (c == DUK_HOBJECT_CLASS_NUMBER) {
40416 duk_to_number(thr, idx_space);
40417 } else if (c == DUK_HOBJECT_CLASS_STRING) {
40418 duk_to_string(thr, idx_space);
40419 }
40420 }
40421
40422 if (duk_is_number(thr, idx_space)) {
40423 duk_small_int_t nspace;
40424 /* spaces[] must be static to allow initializer with old compilers like BCC */
40425 static const char spaces[10] = {
40428 }; /* XXX: helper */
40429
40430 /* ToInteger() coercion; NaN -> 0, infinities are clamped to 0 and 10 */
40431 nspace = (duk_small_int_t) duk_to_int_clamped(thr, idx_space, 0 /*minval*/, 10 /*maxval*/);
40432 DUK_ASSERT(nspace >= 0 && nspace <= 10);
40433
40434 duk_push_lstring(thr, spaces, (duk_size_t) nspace);
40435 js_ctx->h_gap = duk_known_hstring(thr, -1);
40436 DUK_ASSERT(js_ctx->h_gap != NULL);
40437 } else if (duk_is_string_notsymbol(thr, idx_space)) {
40438 duk_dup(thr, idx_space);
40439 duk_substring(thr, -1, 0, 10); /* clamp to 10 chars */
40440 js_ctx->h_gap = duk_known_hstring(thr, -1);
40441 } else {
40442 /* nop */
40443 }
40444
40445 if (js_ctx->h_gap != NULL) {
40446 /* If gap is empty, behave as if not given at all. Check
40447 * against byte length because character length is more
40448 * expensive.
40449 */
40450 if (DUK_HSTRING_GET_BYTELEN(js_ctx->h_gap) == 0) {
40451 js_ctx->h_gap = NULL;
40452 }
40453 }
40454
40455 /* [ ... buf loop (proplist) (gap) ] */
40456
40457 /*
40458 * Fast path: assume no mutation, iterate object property tables
40459 * directly; bail out if that assumption doesn't hold.
40460 */
40461
40462#if defined(DUK_USE_JSON_STRINGIFY_FASTPATH)
40463 if (js_ctx->h_replacer == NULL && /* replacer is a mutation risk */
40464 js_ctx->idx_proplist == -1) { /* proplist is very rare */
40465 duk_int_t pcall_rc;
40466 duk_small_uint_t prev_ms_base_flags;
40467
40468 DUK_DD(DUK_DDPRINT("try JSON.stringify() fast path"));
40469
40470 /* Use recursion_limit to ensure we don't overwrite js_ctx->visiting[]
40471 * array so we don't need two counter checks in the fast path. The
40472 * slow path has a much larger recursion limit which we'll use if
40473 * necessary.
40474 */
40477 DUK_ASSERT(js_ctx->recursion_depth == 0);
40478
40479 /* Execute the fast path in a protected call. If any error is thrown,
40480 * fall back to the slow path. This includes e.g. recursion limit
40481 * because the fast path has a smaller recursion limit (and simpler,
40482 * limited loop detection).
40483 */
40484
40485 duk_dup(thr, idx_value);
40486
40487 /* Must prevent finalizers which may have arbitrary side effects. */
40488 prev_ms_base_flags = thr->heap->ms_base_flags;
40489 thr->heap->ms_base_flags |= DUK_MS_FLAG_NO_OBJECT_COMPACTION; /* Avoid attempt to compact any objects. */
40490 thr->heap->pf_prevent_count++; /* Prevent finalizers. */
40491 DUK_ASSERT(thr->heap->pf_prevent_count != 0); /* Wrap. */
40492
40493 pcall_rc = duk_safe_call(thr, duk__json_stringify_fast, (void *) js_ctx /*udata*/, 1 /*nargs*/, 0 /*nret*/);
40494
40495 DUK_ASSERT(thr->heap->pf_prevent_count > 0);
40496 thr->heap->pf_prevent_count--;
40497 thr->heap->ms_base_flags = prev_ms_base_flags;
40498
40499 if (pcall_rc == DUK_EXEC_SUCCESS) {
40500 DUK_DD(DUK_DDPRINT("fast path successful"));
40501 DUK_BW_PUSH_AS_STRING(thr, &js_ctx->bw);
40502 goto replace_finished;
40503 }
40504
40505 /* We come here for actual aborts (like encountering .toJSON())
40506 * but also for recursion/loop errors. Bufwriter size can be
40507 * kept because we'll probably need at least as much as we've
40508 * allocated so far.
40509 */
40510 DUK_D(DUK_DPRINT("fast path failed, serialize using slow path instead"));
40511 DUK_BW_RESET_SIZE(thr, &js_ctx->bw);
40512 js_ctx->recursion_depth = 0;
40513 }
40514#endif
40515
40516 /*
40517 * Create wrapper object and serialize
40518 */
40519
40520 idx_holder = duk_push_object(thr);
40521 duk_dup(thr, idx_value);
40523
40524 DUK_DDD(DUK_DDDPRINT("before: flags=0x%08lx, loop=%!T, replacer=%!O, "
40525 "proplist=%!T, gap=%!O, holder=%!T",
40526 (unsigned long) js_ctx->flags,
40527 (duk_tval *) duk_get_tval(thr, js_ctx->idx_loop),
40528 (duk_heaphdr *) js_ctx->h_replacer,
40529 (duk_tval *) (js_ctx->idx_proplist >= 0 ? duk_get_tval(thr, js_ctx->idx_proplist) : NULL),
40530 (duk_heaphdr *) js_ctx->h_gap,
40531 (duk_tval *) duk_get_tval(thr, -1)));
40532
40533 /* serialize the wrapper with empty string key */
40534
40536
40537 /* [ ... buf loop (proplist) (gap) holder "" ] */
40538
40540 DUK_ASSERT(js_ctx->recursion_depth == 0);
40541
40542 if (DUK_UNLIKELY(duk__json_enc_value(js_ctx, idx_holder) == 0)) { /* [ ... holder key ] -> [ ... holder ] */
40543 /* Result is undefined. */
40544 duk_push_undefined(thr);
40545 } else {
40546 /* Convert buffer to result string. */
40547 DUK_BW_PUSH_AS_STRING(thr, &js_ctx->bw);
40548 }
40549
40550 DUK_DDD(DUK_DDDPRINT("after: flags=0x%08lx, loop=%!T, replacer=%!O, "
40551 "proplist=%!T, gap=%!O, holder=%!T",
40552 (unsigned long) js_ctx->flags,
40553 (duk_tval *) duk_get_tval(thr, js_ctx->idx_loop),
40554 (duk_heaphdr *) js_ctx->h_replacer,
40555 (duk_tval *) (js_ctx->idx_proplist >= 0 ? duk_get_tval(thr, js_ctx->idx_proplist) : NULL),
40556 (duk_heaphdr *) js_ctx->h_gap,
40557 (duk_tval *) duk_get_tval(thr, idx_holder)));
40558
40559 /* The stack has a variable shape here, so force it to the
40560 * desired one explicitly.
40561 */
40562
40563#if defined(DUK_USE_JSON_STRINGIFY_FASTPATH)
40564replace_finished:
40565#endif
40566 duk_replace(thr, entry_top);
40567 duk_set_top(thr, entry_top + 1);
40568
40569 DUK_DDD(DUK_DDDPRINT("JSON stringify end: value=%!T, replacer=%!T, space=%!T, "
40570 "flags=0x%08lx, result=%!T, stack_top=%ld",
40571 (duk_tval *) duk_get_tval(thr, idx_value),
40572 (duk_tval *) duk_get_tval(thr, idx_replacer),
40573 (duk_tval *) duk_get_tval(thr, idx_space),
40574 (unsigned long) flags,
40576 (long) duk_get_top(thr)));
40577
40578 DUK_ASSERT(duk_get_top(thr) == entry_top + 1);
40579}
40581#if defined(DUK_USE_JSON_BUILTIN)
40582
40583/*
40584 * Entry points
40585 */
40586
40588 duk_bi_json_parse_helper(thr, 0 /*idx_value*/, 1 /*idx_replacer*/, 0 /*flags*/);
40589 return 1;
40590}
40591
40593 duk_bi_json_stringify_helper(thr, 0 /*idx_value*/, 1 /*idx_replacer*/, 2 /*idx_space*/, 0 /*flags*/);
40594 return 1;
40595}
40596
40597#endif /* DUK_USE_JSON_BUILTIN */
40598
40599#endif /* DUK_USE_JSON_SUPPORT */
40600
40601/* automatic undefs */
40602#undef DUK__EMIT_1
40603#undef DUK__EMIT_2
40604#undef DUK__EMIT_CSTR
40605#undef DUK__EMIT_HSTR
40606#undef DUK__EMIT_STRIDX
40607#undef DUK__JSON_DECSTR_BUFSIZE
40608#undef DUK__JSON_DECSTR_CHUNKSIZE
40609#undef DUK__JSON_ENCSTR_CHUNKSIZE
40610#undef DUK__JSON_MAX_ESC_LEN
40611#undef DUK__JSON_STRINGIFY_BUFSIZE
40612#undef DUK__MKESC
40613#undef DUK__UNEMIT_1
40614/*
40615 * Math built-ins
40616 */
40617
40618/* #include duk_internal.h -> already included */
40620#if defined(DUK_USE_MATH_BUILTIN)
40621
40623 * Use static helpers which can work with math.h functions matching
40624 * the following signatures. This is not portable if any of these math
40625 * functions is actually a macro.
40626 *
40627 * Typing here is intentionally 'double' wherever values interact with
40628 * the standard library APIs.
40629 */
40630
40631typedef double (*duk__one_arg_func)(double);
40632typedef double (*duk__two_arg_func)(double, double);
40633
40635 duk_idx_t n = duk_get_top(thr);
40636 duk_idx_t i;
40637 duk_double_t res = initial;
40638 duk_double_t t;
40639
40640 /*
40641 * Note: fmax() does not match the E5 semantics. E5 requires
40642 * that if -any- input to Math.max() is a NaN, the result is a
40643 * NaN. fmax() will return a NaN only if -both- inputs are NaN.
40644 * Same applies to fmin().
40645 *
40646 * Note: every input value must be coerced with ToNumber(), even
40647 * if we know the result will be a NaN anyway: ToNumber() may have
40648 * side effects for which even order of evaluation matters.
40649 */
40650
40651 for (i = 0; i < n; i++) {
40652 t = duk_to_number(thr, i);
40654 /* Note: not normalized, but duk_push_number() will normalize */
40656 } else {
40657 res = (duk_double_t) min_max(res, (double) t);
40658 }
40659 }
40660
40661 duk_push_number(thr, res);
40662 return 1;
40663}
40664
40665DUK_LOCAL double duk__fmin_fixed(double x, double y) {
40666 /* fmin() with args -0 and +0 is not guaranteed to return
40667 * -0 as ECMAScript requires.
40668 */
40669 if (duk_double_equals(x, 0.0) && duk_double_equals(y, 0.0)) {
40670 duk_double_union du1, du2;
40671 du1.d = x;
40672 du2.d = y;
40673
40674 /* Already checked to be zero so these must hold, and allow us
40675 * to check for "x is -0 or y is -0" by ORing the high parts
40676 * for comparison.
40677 */
40678 DUK_ASSERT(du1.ui[DUK_DBL_IDX_UI0] == 0 || du1.ui[DUK_DBL_IDX_UI0] == 0x80000000UL);
40679 DUK_ASSERT(du2.ui[DUK_DBL_IDX_UI0] == 0 || du2.ui[DUK_DBL_IDX_UI0] == 0x80000000UL);
40681 /* XXX: what's the safest way of creating a negative zero? */
40682 if ((du1.ui[DUK_DBL_IDX_UI0] | du2.ui[DUK_DBL_IDX_UI0]) != 0) {
40683 /* Enter here if either x or y (or both) is -0. */
40684 return -0.0;
40685 } else {
40686 return +0.0;
40687 }
40688 }
40689 return duk_double_fmin(x, y);
40690}
40691
40692DUK_LOCAL double duk__fmax_fixed(double x, double y) {
40693 /* fmax() with args -0 and +0 is not guaranteed to return
40694 * +0 as ECMAScript requires.
40696 if (duk_double_equals(x, 0.0) && duk_double_equals(y, 0.0)) {
40697 if (DUK_SIGNBIT(x) == 0 || DUK_SIGNBIT(y) == 0) {
40698 return +0.0;
40699 } else {
40700 return -0.0;
40701 }
40702 }
40703 return duk_double_fmax(x, y);
40704}
40705
40706#if defined(DUK_USE_ES6)
40707DUK_LOCAL double duk__cbrt(double x) {
40708 /* cbrt() is C99. To avoid hassling embedders with the need to provide a
40709 * cube root function, we can get by with pow(). The result is not
40710 * identical, but that's OK: ES2015 says it's implementation-dependent.
40711 */
40712
40713#if defined(DUK_CBRT)
40714 /* cbrt() matches ES2015 requirements. */
40715 return DUK_CBRT(x);
40716#else
40718
40719 /* pow() does not, however. */
40720 if (c == DUK_FP_NAN || c == DUK_FP_INFINITE || c == DUK_FP_ZERO) {
40721 return x;
40722 }
40723 if (DUK_SIGNBIT(x)) {
40724 return -DUK_POW(-x, 1.0 / 3.0);
40725 } else {
40726 return DUK_POW(x, 1.0 / 3.0);
40728#endif
40729}
40730
40731DUK_LOCAL double duk__log2(double x) {
40732#if defined(DUK_LOG2)
40733 return DUK_LOG2(x);
40734#else
40736#endif
40737}
40738
40739DUK_LOCAL double duk__log10(double x) {
40740#if defined(DUK_LOG10)
40741 return DUK_LOG10(x);
40742#else
40743 return DUK_LOG(x) * DUK_DOUBLE_LOG10E;
40744#endif
40745}
40746
40747DUK_LOCAL double duk__trunc(double x) {
40748#if defined(DUK_TRUNC)
40749 return DUK_TRUNC(x);
40750#else
40751 /* Handles -0 correctly: -0.0 matches 'x >= 0.0' but floor()
40752 * is required to return -0 when the argument is -0.
40753 */
40754 return x >= 0.0 ? DUK_FLOOR(x) : DUK_CEIL(x);
40755#endif
40756}
40757#endif /* DUK_USE_ES6 */
40758
40759DUK_LOCAL double duk__round_fixed(double x) {
40760 /* Numbers half-way between integers must be rounded towards +Infinity,
40761 * e.g. -3.5 must be rounded to -3 (not -4). When rounded to zero, zero
40762 * sign must be set appropriately. E5.1 Section 15.8.2.15.
40763 *
40764 * Note that ANSI C round() is "round to nearest integer, away from zero",
40765 * which is incorrect for negative values. Here we make do with floor().
40766 */
40767
40769 if (c == DUK_FP_NAN || c == DUK_FP_INFINITE || c == DUK_FP_ZERO) {
40770 return x;
40771 }
40772
40773 /*
40774 * x is finite and non-zero
40775 *
40776 * -1.6 -> floor(-1.1) -> -2
40777 * -1.5 -> floor(-1.0) -> -1 (towards +Inf)
40778 * -1.4 -> floor(-0.9) -> -1
40779 * -0.5 -> -0.0 (special case)
40780 * -0.1 -> -0.0 (special case)
40781 * +0.1 -> +0.0 (special case)
40782 * +0.5 -> floor(+1.0) -> 1 (towards +Inf)
40783 * +1.4 -> floor(+1.9) -> 1
40784 * +1.5 -> floor(+2.0) -> 2 (towards +Inf)
40785 * +1.6 -> floor(+2.1) -> 2
40786 */
40787
40788 if (x >= -0.5 && x < 0.5) {
40789 /* +0.5 is handled by floor, this is on purpose */
40790 if (x < 0.0) {
40791 return -0.0;
40792 } else {
40793 return +0.0;
40794 }
40795 }
40797 return DUK_FLOOR(x + 0.5);
40798}
40800/* Wrappers for calling standard math library methods. These may be required
40801 * on platforms where one or more of the math built-ins are defined as macros
40802 * or inline functions and are thus not suitable to be used as function pointers.
40803 */
40804#if defined(DUK_USE_AVOID_PLATFORM_FUNCPTRS)
40805DUK_LOCAL double duk__fabs(double x) {
40806 return DUK_FABS(x);
40807}
40808DUK_LOCAL double duk__acos(double x) {
40809 return DUK_ACOS(x);
40810}
40811DUK_LOCAL double duk__asin(double x) {
40812 return DUK_ASIN(x);
40813}
40814DUK_LOCAL double duk__atan(double x) {
40815 return DUK_ATAN(x);
40816}
40817DUK_LOCAL double duk__ceil(double x) {
40818 return DUK_CEIL(x);
40819}
40820DUK_LOCAL double duk__cos(double x) {
40821 return DUK_COS(x);
40822}
40823DUK_LOCAL double duk__exp(double x) {
40824 return DUK_EXP(x);
40825}
40826DUK_LOCAL double duk__floor(double x) {
40827 return DUK_FLOOR(x);
40828}
40829DUK_LOCAL double duk__log(double x) {
40830 return DUK_LOG(x);
40831}
40832DUK_LOCAL double duk__sin(double x) {
40833 return DUK_SIN(x);
40834}
40835DUK_LOCAL double duk__sqrt(double x) {
40836 return DUK_SQRT(x);
40837}
40838DUK_LOCAL double duk__tan(double x) {
40839 return DUK_TAN(x);
40840}
40841DUK_LOCAL double duk__atan2_fixed(double x, double y) {
40842#if defined(DUK_USE_ATAN2_WORKAROUNDS)
40843 /* Specific fixes to common atan2() implementation issues:
40844 * - test-bug-mingw-math-issues.js
40845 */
40846 if (DUK_ISINF(x) && DUK_ISINF(y)) {
40847 if (DUK_SIGNBIT(x)) {
40848 if (DUK_SIGNBIT(y)) {
40849 return -2.356194490192345;
40850 } else {
40851 return -0.7853981633974483;
40852 }
40853 } else {
40854 if (DUK_SIGNBIT(y)) {
40855 return 2.356194490192345;
40856 } else {
40857 return 0.7853981633974483;
40858 }
40859 }
40860 }
40861#else
40862 /* Some ISO C assumptions. */
40868#endif
40869
40870 return DUK_ATAN2(x, y);
40871}
40872#endif /* DUK_USE_AVOID_PLATFORM_FUNCPTRS */
40873
40874/* order must match constants in genbuiltins.py */
40876#if defined(DUK_USE_AVOID_PLATFORM_FUNCPTRS)
40879#if defined(DUK_USE_ES6)
40881#endif
40882#else /* DUK_USE_AVOID_PLATFORM_FUNCPTRS */
40885#if defined(DUK_USE_ES6)
40887#endif
40888#endif /* DUK_USE_AVOID_PLATFORM_FUNCPTRS */
40889};
40891/* order must match constants in genbuiltins.py */
40893#if defined(DUK_USE_AVOID_PLATFORM_FUNCPTRS)
40896#else
40899#endif
40900};
40901
40905 duk_double_t arg1;
40906
40907 DUK_ASSERT(fun_idx >= 0);
40908 DUK_ASSERT(fun_idx < (duk_small_int_t) (sizeof(duk__one_arg_funcs) / sizeof(duk__one_arg_func)));
40909 arg1 = duk_to_number(thr, 0);
40910 fun = duk__one_arg_funcs[fun_idx];
40911 duk_push_number(thr, (duk_double_t) fun((double) arg1));
40912 return 1;
40913}
40914
40919 duk_double_t arg2;
40920
40921 DUK_ASSERT(fun_idx >= 0);
40923 arg1 = duk_to_number(thr, 0); /* explicit ordered evaluation to match coercion semantics */
40924 arg2 = duk_to_number(thr, 1);
40925 fun = duk__two_arg_funcs[fun_idx];
40926 duk_push_number(thr, (duk_double_t) fun((double) arg1, (double) arg2));
40927 return 1;
40928}
40929
40933
40936}
40937
40940 return 1;
40941}
40942
40943#if defined(DUK_USE_ES6)
40945 /*
40946 * E6 Section 20.2.2.18: Math.hypot
40947 *
40948 * - If no arguments are passed, the result is +0.
40949 * - If any argument is +inf, the result is +inf.
40950 * - If any argument is -inf, the result is +inf.
40951 * - If no argument is +inf or -inf, and any argument is NaN, the result is
40952 * NaN.
40953 * - If all arguments are either +0 or -0, the result is +0.
40954 */
40955
40956 duk_idx_t nargs;
40957 duk_idx_t i;
40958 duk_bool_t found_nan;
40960 duk_double_t sum, summand;
40961 duk_double_t comp, prelim;
40962 duk_double_t t;
40963
40964 nargs = duk_get_top(thr);
40965
40966 /* Find the highest value. Also ToNumber() coerces. */
40967 max = 0.0;
40968 found_nan = 0;
40969 for (i = 0; i < nargs; i++) {
40970 t = DUK_FABS(duk_to_number(thr, i));
40971 if (DUK_FPCLASSIFY(t) == DUK_FP_NAN) {
40972 found_nan = 1;
40973 } else {
40974 max = duk_double_fmax(max, t);
40975 }
40976 }
40977
40978 /* Early return cases. */
40981 return 1;
40982 } else if (found_nan) {
40984 return 1;
40985 } else if (duk_double_equals(max, 0.0)) {
40986 duk_push_number(thr, 0.0);
40987 /* Otherwise we'd divide by zero. */
40988 return 1;
40989 }
40990
40991 /* Use Kahan summation and normalize to the highest value to minimize
40992 * floating point rounding error and avoid overflow.
40993 *
40994 * https://en.wikipedia.org/wiki/Kahan_summation_algorithm
40995 */
40996 sum = 0.0;
40997 comp = 0.0;
40998 for (i = 0; i < nargs; i++) {
40999 t = DUK_FABS(duk_get_number(thr, i)) / max;
41000 summand = (t * t) - comp;
41001 prelim = sum + summand;
41002 comp = (prelim - sum) - summand;
41003 sum = prelim;
41004 }
41005
41007 return 1;
41008}
41009#endif /* DUK_USE_ES6 */
41010
41011#if defined(DUK_USE_ES6)
41013 duk_double_t d;
41014
41015 d = duk_to_number(thr, 0);
41016 if (duk_double_is_nan(d)) {
41017 DUK_ASSERT(duk_is_nan(thr, -1));
41018 return 1; /* NaN input -> return NaN */
41019 }
41020 if (duk_double_equals(d, 0.0)) {
41021 /* Zero sign kept, i.e. -0 -> -0, +0 -> +0. */
41022 return 1;
41023 }
41024 duk_push_int(thr, (d > 0.0 ? 1 : -1));
41025 return 1;
41026}
41027#endif /* DUK_USE_ES6 */
41028
41029#if defined(DUK_USE_ES6)
41031 duk_uint32_t x;
41033
41034#if defined(DUK_USE_PREFER_SIZE)
41035 duk_uint32_t mask;
41036
41037 x = duk_to_uint32(thr, 0);
41038 for (i = 0, mask = 0x80000000UL; mask != 0; mask >>= 1) {
41039 if (x & mask) {
41040 break;
41041 }
41042 i++;
41043 }
41044 DUK_ASSERT(i <= 32);
41045 duk_push_uint(thr, i);
41046 return 1;
41047#else /* DUK_USE_PREFER_SIZE */
41048 i = 0;
41049 x = duk_to_uint32(thr, 0);
41050 if (x & 0xffff0000UL) {
41051 x >>= 16;
41052 } else {
41053 i += 16;
41054 }
41055 if (x & 0x0000ff00UL) {
41056 x >>= 8;
41057 } else {
41058 i += 8;
41059 }
41060 if (x & 0x000000f0UL) {
41061 x >>= 4;
41062 } else {
41063 i += 4;
41064 }
41065 if (x & 0x0000000cUL) {
41066 x >>= 2;
41067 } else {
41068 i += 2;
41069 }
41070 if (x & 0x00000002UL) {
41071 x >>= 1;
41072 } else {
41073 i += 1;
41074 }
41075 if (x & 0x00000001UL) {
41077 } else {
41078 i += 1;
41079 }
41080 DUK_ASSERT(i <= 32);
41081 duk_push_uint(thr, i);
41082 return 1;
41083#endif /* DUK_USE_PREFER_SIZE */
41084}
41085#endif /* DUK_USE_ES6 */
41086
41087#if defined(DUK_USE_ES6)
41089 duk_uint32_t x, y, z;
41090
41091 x = duk_to_uint32(thr, 0);
41092 y = duk_to_uint32(thr, 1);
41093 z = x * y;
41094
41095 /* While arguments are ToUint32() coerced and the multiplication
41096 * is unsigned as such, the final result is curiously interpreted
41097 * as a signed 32-bit value.
41098 */
41099 duk_push_i32(thr, (duk_int32_t) z);
41100 return 1;
41102#endif /* DUK_USE_ES6 */
41103
41104#endif /* DUK_USE_MATH_BUILTIN */
41105/*
41106 * Number built-ins
41107 */
41108
41109/* #include duk_internal.h -> already included */
41110
41111#if defined(DUK_USE_NUMBER_BUILTIN)
41112
41114 duk_hobject *h;
41115
41116 /* Number built-in accepts a plain number or a Number object (whose
41117 * internal value is operated on). Other types cause TypeError.
41118 */
41119
41120 duk_push_this(thr);
41121 if (duk_is_number(thr, -1)) {
41122 DUK_DDD(DUK_DDDPRINT("plain number value: %!T", (duk_tval *) duk_get_tval(thr, -1)));
41123 goto done;
41124 }
41125 h = duk_get_hobject(thr, -1);
41127 DUK_DDD(DUK_DDDPRINT("unacceptable this value: %!T", (duk_tval *) duk_get_tval(thr, -1)));
41128 DUK_ERROR_TYPE(thr, "number expected");
41129 DUK_WO_NORETURN(return 0.0;);
41132 DUK_ASSERT(duk_is_number(thr, -1));
41133 DUK_DDD(DUK_DDDPRINT("number object: %!T, internal value: %!T",
41134 (duk_tval *) duk_get_tval(thr, -2),
41135 (duk_tval *) duk_get_tval(thr, -1)));
41136 duk_remove_m2(thr);
41137
41138done:
41139 return duk_get_number(thr, -1);
41140}
41141
41143 duk_idx_t nargs;
41144 duk_hobject *h_this;
41145
41146 /*
41147 * The Number constructor uses ToNumber(arg) for number coercion
41148 * (coercing an undefined argument to NaN). However, if the
41149 * argument is not given at all, +0 must be used instead. To do
41150 * this, a vararg function is used.
41151 */
41152
41153 nargs = duk_get_top(thr);
41154 if (nargs == 0) {
41155 duk_push_int(thr, 0);
41156 }
41157 duk_to_number(thr, 0);
41158 duk_set_top(thr, 1);
41159 DUK_ASSERT_TOP(thr, 1);
41160
41161 if (!duk_is_constructor_call(thr)) {
41162 return 1;
41163 }
41164
41165 /*
41166 * E5 Section 15.7.2.1 requires that the constructed object
41167 * must have the original Number.prototype as its internal
41168 * prototype. However, since Number.prototype is non-writable
41169 * and non-configurable, this doesn't have to be enforced here:
41170 * The default object (bound to 'this') is OK, though we have
41171 * to change its class.
41172 *
41173 * Internal value set to ToNumber(arg) or +0; if no arg given,
41174 * ToNumber(undefined) = NaN, so special treatment is needed
41175 * (above). String internal value is immutable.
41176 */
41177
41178 /* XXX: helper */
41179 duk_push_this(thr);
41180 h_this = duk_known_hobject(thr, -1);
41182
41186
41187 duk_dup_0(thr); /* -> [ val obj val ] */
41189 return 0; /* no return value -> don't replace created value */
41190}
41191
41193 (void) duk__push_this_number_plain(thr);
41194 return 1;
41195}
41196
41198 duk_small_int_t radix;
41199 duk_small_uint_t n2s_flags;
41200
41201 (void) duk__push_this_number_plain(thr);
41202 if (duk_is_undefined(thr, 0)) {
41203 radix = 10;
41204 } else {
41205 radix = (duk_small_int_t) duk_to_int_check_range(thr, 0, 2, 36);
41206 }
41207 DUK_DDD(DUK_DDDPRINT("radix=%ld", (long) radix));
41208
41209 n2s_flags = 0;
41210
41211 duk_numconv_stringify(thr, radix /*radix*/, 0 /*digits*/, n2s_flags /*flags*/);
41212 return 1;
41213}
41214
41216 /* XXX: just use toString() for now; permitted although not recommended.
41217 * nargs==1, so radix is passed to toString().
41218 */
41220}
41221
41222/*
41223 * toFixed(), toExponential(), toPrecision()
41224 */
41225
41226/* XXX: shared helper for toFixed(), toExponential(), toPrecision()? */
41227
41229 duk_small_int_t frac_digits;
41230 duk_double_t d;
41232 duk_small_uint_t n2s_flags;
41233
41234 /* In ES5.1 frac_digits is coerced first; in ES2015 the 'this number
41235 * value' check is done first.
41236 */
41238 frac_digits = (duk_small_int_t) duk_to_int_check_range(thr, 0, 0, 20);
41239
41241 if (c == DUK_FP_NAN || c == DUK_FP_INFINITE) {
41242 goto use_to_string;
41243 }
41244
41245 if (d >= 1.0e21 || d <= -1.0e21) {
41246 goto use_to_string;
41247 }
41250
41251 duk_numconv_stringify(thr, 10 /*radix*/, frac_digits /*digits*/, n2s_flags /*flags*/);
41252 return 1;
41253
41254use_to_string:
41255 DUK_ASSERT_TOP(thr, 2);
41256 duk_to_string(thr, -1);
41257 return 1;
41258}
41259
41261 duk_bool_t frac_undefined;
41262 duk_small_int_t frac_digits;
41263 duk_double_t d;
41265 duk_small_uint_t n2s_flags;
41266
41268
41269 frac_undefined = duk_is_undefined(thr, 0);
41270 duk_to_int(thr, 0); /* for side effects */
41271
41273 if (c == DUK_FP_NAN || c == DUK_FP_INFINITE) {
41274 goto use_to_string;
41275 }
41276
41277 frac_digits = (duk_small_int_t) duk_to_int_check_range(thr, 0, 0, 20);
41279 n2s_flags = DUK_N2S_FLAG_FORCE_EXP | (frac_undefined ? 0 : DUK_N2S_FLAG_FIXED_FORMAT);
41280
41281 duk_numconv_stringify(thr, 10 /*radix*/, frac_digits + 1 /*leading digit + fractions*/, n2s_flags /*flags*/);
41282 return 1;
41283
41284use_to_string:
41285 DUK_ASSERT_TOP(thr, 2);
41286 duk_to_string(thr, -1);
41287 return 1;
41288}
41289
41291 /* The specification has quite awkward order of coercion and
41292 * checks for toPrecision(). The operations below are a bit
41293 * reordered, within constraints of observable side effects.
41294 */
41295
41296 duk_double_t d;
41297 duk_small_int_t prec;
41299 duk_small_uint_t n2s_flags;
41300
41301 DUK_ASSERT_TOP(thr, 1);
41302
41304 if (duk_is_undefined(thr, 0)) {
41305 goto use_to_string;
41306 }
41307 DUK_ASSERT_TOP(thr, 2);
41308
41309 duk_to_int(thr, 0); /* for side effects */
41310
41312 if (c == DUK_FP_NAN || c == DUK_FP_INFINITE) {
41313 goto use_to_string;
41314 }
41315
41316 prec = (duk_small_int_t) duk_to_int_check_range(thr, 0, 1, 21);
41317
41319
41320 duk_numconv_stringify(thr, 10 /*radix*/, prec /*digits*/, n2s_flags /*flags*/);
41321 return 1;
41322
41323use_to_string:
41324 /* Used when precision is undefined; also used for NaN (-> "NaN"),
41325 * and +/- infinity (-> "Infinity", "-Infinity").
41327
41328 DUK_ASSERT_TOP(thr, 2);
41329 duk_to_string(thr, -1);
41330 return 1;
41331}
41332
41333/*
41334 * ES2015 isFinite() etc
41335 */
41336
41337#if defined(DUK_USE_ES6)
41339 duk_int_t magic;
41340 duk_bool_t ret = 0;
41341
41342 if (duk_is_number(thr, 0)) {
41343 duk_double_t d;
41344
41345 magic = duk_get_current_magic(thr);
41346 d = duk_get_number(thr, 0);
41347
41348 switch (magic) {
41349 case 0: /* isFinite() */
41350 ret = duk_double_is_finite(d);
41351 break;
41352 case 1: /* isInteger() */
41353 ret = duk_double_is_integer(d);
41354 break;
41355 case 2: /* isNaN() */
41356 ret = duk_double_is_nan(d);
41357 break;
41358 default: /* isSafeInteger() */
41359 DUK_ASSERT(magic == 3);
41361 }
41362 }
41363
41364 duk_push_boolean(thr, ret);
41365 return 1;
41366}
41367#endif /* DUK_USE_ES6 */
41368
41369#endif /* DUK_USE_NUMBER_BUILTIN */
41370/*
41371 * Object built-ins
41372 */
41373
41374/* #include duk_internal.h -> already included */
41375
41376/* Needed even when Object built-in disabled. */
41378 duk_tval *tv;
41379
41380 tv = DUK_HTHREAD_THIS_PTR(thr);
41381 duk_push_class_string_tval(thr, tv, 0 /*avoid_side_effects*/);
41382 return 1;
41383}
41384
41385#if defined(DUK_USE_OBJECT_BUILTIN)
41387 duk_uint_t arg_mask;
41388
41389 arg_mask = duk_get_type_mask(thr, 0);
41390
41391 if (!duk_is_constructor_call(thr) && /* not a constructor call */
41392 ((arg_mask & (DUK_TYPE_MASK_NULL | DUK_TYPE_MASK_UNDEFINED)) == 0)) { /* and argument not null or undefined */
41393 duk_to_object(thr, 0);
41394 return 1;
41395 }
41396
41397 /* Pointer and buffer primitive values are treated like other
41398 * primitives values which have a fully fledged object counterpart:
41399 * promote to an object value. Lightfuncs and plain buffers are
41400 * coerced with ToObject() even they could also be returned as is.
41401 */
41404 /* For DUK_TYPE_OBJECT the coercion is a no-op and could
41405 * be checked for explicitly, but Object(obj) calls are
41406 * not very common so opt for minimal footprint.
41407 */
41408 duk_to_object(thr, 0);
41409 return 1;
41410 }
41411
41412 (void) duk_push_object_helper(thr,
41416 return 1;
41417}
41418#endif /* DUK_USE_OBJECT_BUILTIN */
41419
41420#if defined(DUK_USE_OBJECT_BUILTIN) && defined(DUK_USE_ES6)
41422 duk_idx_t nargs;
41423 duk_int_t idx;
41424
41425 nargs = duk_get_top_require_min(thr, 1 /*min_top*/);
41426
41427 duk_to_object(thr, 0);
41428 for (idx = 1; idx < nargs; idx++) {
41429 /* E7 19.1.2.1 (step 4a) */
41430 if (duk_is_null_or_undefined(thr, idx)) {
41431 continue;
41432 }
41433
41434 /* duk_enum() respects ES2015+ [[OwnPropertyKeys]] ordering, which is
41435 * convenient here.
41436 */
41437 duk_to_object(thr, idx);
41439 while (duk_next(thr, -1, 1 /*get_value*/)) {
41440 /* [ target ... enum key value ] */
41441 duk_put_prop(thr, 0);
41442 /* [ target ... enum ] */
41444 /* Could pop enumerator, but unnecessary because of duk_set_top()
41445 * below.
41446 */
41447 }
41448
41449 duk_set_top(thr, 1);
41450 return 1;
41452#endif
41453
41454#if defined(DUK_USE_OBJECT_BUILTIN) && defined(DUK_USE_ES6)
41456 DUK_ASSERT_TOP(thr, 2);
41457 duk_push_boolean(thr, duk_samevalue(thr, 0, 1));
41458 return 1;
41459}
41460#endif
41461
41462#if defined(DUK_USE_OBJECT_BUILTIN)
41464 duk_hobject *proto;
41465
41466 DUK_ASSERT_TOP(thr, 2);
41467
41468#if defined(DUK_USE_BUFFEROBJECT_SUPPORT)
41470#endif
41472 DUK_ASSERT(proto != NULL || duk_is_null(thr, 0));
41473
41477 proto);
41478
41479 if (!duk_is_undefined(thr, 1)) {
41480 /* [ O Properties obj ] */
41481
41482 duk_replace(thr, 0);
41483
41484 /* [ obj Properties ] */
41485
41486 /* Just call the "original" Object.defineProperties() to
41487 * finish up.
41489
41491 }
41492
41493 /* [ O Properties obj ] */
41494
41495 return 1;
41496}
41497#endif /* DUK_USE_OBJECT_BUILTIN */
41498
41499#if defined(DUK_USE_OBJECT_BUILTIN)
41501 duk_small_uint_t pass;
41502 duk_uint_t defprop_flags;
41503 duk_hobject *obj;
41504 duk_idx_t idx_value;
41505 duk_hobject *get;
41506 duk_hobject *set;
41507
41508 /* Lightfunc and plain buffer handling by ToObject() coercion. */
41510 DUK_ASSERT(obj != NULL);
41511
41512 duk_to_object(thr, 1); /* properties object */
41513
41514 DUK_DDD(DUK_DDDPRINT("target=%!iT, properties=%!iT", (duk_tval *) duk_get_tval(thr, 0), (duk_tval *) duk_get_tval(thr, 1)));
41515
41516 /*
41517 * Two pass approach to processing the property descriptors.
41518 * On first pass validate and normalize all descriptors before
41519 * any changes are made to the target object. On second pass
41520 * make the actual modifications to the target object.
41521 *
41522 * Right now we'll just use the same normalize/validate helper
41523 * on both passes, ignoring its outputs on the first pass.
41524 */
41525
41526 for (pass = 0; pass < 2; pass++) {
41527 duk_set_top(thr, 2); /* -> [ hobject props ] */
41529
41530 for (;;) {
41531 duk_hstring *key;
41532
41533 /* [ hobject props enum(props) ] */
41534
41535 duk_set_top(thr, 3);
41536
41537 if (!duk_next(thr, 2, 1 /*get_value*/)) {
41538 break;
41539 }
41540
41541 DUK_DDD(DUK_DDDPRINT("-> key=%!iT, desc=%!iT",
41542 (duk_tval *) duk_get_tval(thr, -2),
41543 (duk_tval *) duk_get_tval(thr, -1)));
41544
41545 /* [ hobject props enum(props) key desc ] */
41546
41547 duk_hobject_prepare_property_descriptor(thr, 4 /*idx_desc*/, &defprop_flags, &idx_value, &get, &set);
41548
41549 /* [ hobject props enum(props) key desc [multiple values] ] */
41550
41551 if (pass == 0) {
41552 continue;
41553 }
41554
41555 /* This allows symbols on purpose. */
41556 key = duk_known_hstring(thr, 3);
41557 DUK_ASSERT(key != NULL);
41558
41559 duk_hobject_define_property_helper(thr, defprop_flags, obj, key, idx_value, get, set, 1 /*throw_flag*/);
41560 }
41562
41563 /*
41564 * Return target object
41565 */
41566
41567 duk_dup_0(thr);
41568 return 1;
41569}
41570#endif /* DUK_USE_OBJECT_BUILTIN */
41571
41572#if defined(DUK_USE_OBJECT_BUILTIN)
41574 DUK_ASSERT_TOP(thr, 1);
41575
41576 duk_seal_freeze_raw(thr, 0, (duk_bool_t) duk_get_current_magic(thr) /*is_freeze*/);
41577 return 1;
41578}
41579#endif /* DUK_USE_OBJECT_BUILTIN */
41580
41581#if defined(DUK_USE_OBJECT_BUILTIN)
41583 duk_hobject *h;
41584 duk_bool_t is_frozen;
41585 duk_uint_t mask;
41586
41587 is_frozen = (duk_bool_t) duk_get_current_magic(thr);
41588 mask = duk_get_type_mask(thr, 0);
41590 DUK_ASSERT(is_frozen == 0 || is_frozen == 1);
41591 duk_push_boolean(thr,
41592 (mask & DUK_TYPE_MASK_LIGHTFUNC) ? 1 : /* lightfunc always frozen and sealed */
41593 (is_frozen ^ 1)); /* buffer sealed but not frozen (index props writable) */
41594 } else {
41595 /* ES2015 Sections 19.1.2.12, 19.1.2.13: anything other than an object
41596 * is considered to be already sealed and frozen.
41597 */
41598 h = duk_get_hobject(thr, 0);
41599 duk_push_boolean(thr, (h == NULL) || duk_hobject_object_is_sealed_frozen_helper(thr, h, is_frozen /*is_frozen*/));
41600 }
41601 return 1;
41602}
41603#endif /* DUK_USE_OBJECT_BUILTIN */
41604
41605#if defined(DUK_USE_OBJECT_BUILTIN)
41607 DUK_ASSERT_TOP(thr, 0);
41610#if 0 /* This is mentioned explicitly in the E5.1 spec, but duk_call_method() checks for it in practice. */
41611 duk_require_callable(thr, 1);
41612#endif
41613 duk_dup_0(thr); /* -> [ O toString O ] */
41614 duk_call_method(thr, 0); /* XXX: call method tail call? */
41615 return 1;
41617#endif /* DUK_USE_OBJECT_BUILTIN */
41618
41619#if defined(DUK_USE_OBJECT_BUILTIN)
41621 /* For lightfuncs and plain buffers, returns Object() coerced. */
41623 return 1;
41624}
41625#endif /* DUK_USE_OBJECT_BUILTIN */
41626
41627#if defined(DUK_USE_OBJECT_BUILTIN)
41629 duk_hobject *h_v;
41630 duk_hobject *h_obj;
41631
41632 DUK_ASSERT_TOP(thr, 1);
41633
41634 h_v = duk_get_hobject(thr, 0);
41635 if (!h_v) {
41636 duk_push_false(thr); /* XXX: tail call: return duk_push_false(thr) */
41637 return 1;
41638 }
41639
41641 DUK_ASSERT(h_obj != NULL);
41643 /* E5.1 Section 15.2.4.6, step 3.a, lookup proto once before compare.
41644 * Prototype loops should cause an error to be thrown.
41645 */
41647 thr,
41648 duk_hobject_prototype_chain_contains(thr, DUK_HOBJECT_GET_PROTOTYPE(thr->heap, h_v), h_obj, 0 /*ignore_loop*/));
41649 return 1;
41650}
41651#endif /* DUK_USE_OBJECT_BUILTIN */
41652
41653#if defined(DUK_USE_OBJECT_BUILTIN)
41655 return (duk_ret_t) duk_hobject_object_ownprop_helper(thr, 0 /*required_desc_flags*/);
41656}
41657#endif /* DUK_USE_OBJECT_BUILTIN */
41658
41659#if defined(DUK_USE_OBJECT_BUILTIN)
41661 return (duk_ret_t) duk_hobject_object_ownprop_helper(thr, DUK_PROPDESC_FLAG_ENUMERABLE /*required_desc_flags*/);
41662}
41663#endif /* DUK_USE_OBJECT_BUILTIN */
41664
41665#if defined(DUK_USE_OBJECT_BUILTIN) || defined(DUK_USE_REFLECT_BUILTIN)
41666/* Shared helper to implement Object.getPrototypeOf,
41667 * Object.prototype.__proto__ getter, and Reflect.getPrototypeOf.
41668 *
41669 * http://www.ecma-international.org/ecma-262/6.0/index.html#sec-get-object.prototype.__proto__
41670 */
41672 /*
41673 * magic = 0: __proto__ getter
41674 * magic = 1: Object.getPrototypeOf()
41675 * magic = 2: Reflect.getPrototypeOf()
41676 */
41677
41678 duk_hobject *h;
41679 duk_hobject *proto;
41680 duk_tval *tv;
41681 duk_int_t magic;
41682
41683 magic = duk_get_current_magic(thr);
41684
41685 if (magic == 0) {
41686 DUK_ASSERT_TOP(thr, 0);
41688 }
41689 DUK_ASSERT(duk_get_top(thr) >= 1);
41690 if (magic < 2) {
41691 /* ES2015 Section 19.1.2.9, step 1 */
41692 duk_to_object(thr, 0);
41693 }
41694 tv = DUK_GET_TVAL_POSIDX(thr, 0);
41695
41696 switch (DUK_TVAL_GET_TAG(tv)) {
41697 case DUK_TAG_BUFFER:
41699 break;
41700 case DUK_TAG_LIGHTFUNC:
41702 break;
41703 case DUK_TAG_OBJECT:
41704 h = DUK_TVAL_GET_OBJECT(tv);
41705 proto = DUK_HOBJECT_GET_PROTOTYPE(thr->heap, h);
41706 break;
41707 default:
41708 /* This implicitly handles CheckObjectCoercible() caused
41709 * TypeError.
41710 */
41712 }
41713 if (proto != NULL) {
41714 duk_push_hobject(thr, proto);
41715 } else {
41716 duk_push_null(thr);
41718 return 1;
41719}
41720#endif /* DUK_USE_OBJECT_BUILTIN || DUK_USE_REFLECT_BUILTIN */
41721
41722#if defined(DUK_USE_OBJECT_BUILTIN) || defined(DUK_USE_REFLECT_BUILTIN)
41723/* Shared helper to implement ES2015 Object.setPrototypeOf,
41724 * Object.prototype.__proto__ setter, and Reflect.setPrototypeOf.
41725 *
41726 * http://www.ecma-international.org/ecma-262/6.0/index.html#sec-get-object.prototype.__proto__
41727 * http://www.ecma-international.org/ecma-262/6.0/index.html#sec-object.setprototypeof
41728 */
41730 /*
41731 * magic = 0: __proto__ setter
41732 * magic = 1: Object.setPrototypeOf()
41733 * magic = 2: Reflect.setPrototypeOf()
41734 */
41735
41736 duk_hobject *h_obj;
41737 duk_hobject *h_new_proto;
41738 duk_hobject *h_curr;
41739 duk_ret_t ret_success = 1; /* retval for success path */
41740 duk_uint_t mask;
41741 duk_int_t magic;
41742
41743 /* Preliminaries for __proto__ and setPrototypeOf (E6 19.1.2.18 steps 1-4). */
41744 magic = duk_get_current_magic(thr);
41745 if (magic == 0) {
41747 duk_insert(thr, 0);
41749 return 0;
41750 }
41751
41752 /* __proto__ setter returns 'undefined' on success unlike the
41753 * setPrototypeOf() call which returns the target object.
41754 */
41755 ret_success = 0;
41756 } else {
41757 if (magic == 1) {
41759 } else {
41761 }
41763 }
41764
41765 h_new_proto = duk_get_hobject(thr, 1);
41766 /* h_new_proto may be NULL */
41767
41768 mask = duk_get_type_mask(thr, 0);
41770 duk_hobject *curr_proto;
41771 curr_proto =
41773 if (h_new_proto == curr_proto) {
41774 goto skip;
41775 }
41776 goto fail_nonextensible;
41777 }
41778 h_obj = duk_get_hobject(thr, 0);
41779 if (h_obj == NULL) {
41780 goto skip;
41781 }
41782 DUK_ASSERT(h_obj != NULL);
41783
41784 /* [[SetPrototypeOf]] standard behavior, E6 9.1.2. */
41785 /* TODO: implement Proxy object support here */
41786
41787 if (h_new_proto == DUK_HOBJECT_GET_PROTOTYPE(thr->heap, h_obj)) {
41788 goto skip;
41789 }
41790 if (!DUK_HOBJECT_HAS_EXTENSIBLE(h_obj)) {
41791 goto fail_nonextensible;
41792 }
41793 for (h_curr = h_new_proto; h_curr != NULL; h_curr = DUK_HOBJECT_GET_PROTOTYPE(thr->heap, h_curr)) {
41794 /* Loop prevention. */
41795 if (h_curr == h_obj) {
41796 goto fail_loop;
41797 }
41798 }
41799 DUK_HOBJECT_SET_PROTOTYPE_UPDREF(thr, h_obj, h_new_proto);
41800 /* fall thru */
41801
41802skip:
41803 duk_set_top(thr, 1);
41804 if (magic == 2) {
41805 duk_push_true(thr);
41806 }
41807 return ret_success;
41808
41809fail_nonextensible:
41810fail_loop:
41811 if (magic != 2) {
41813 } else {
41814 duk_push_false(thr);
41815 return 1;
41816 }
41817}
41818#endif /* DUK_USE_OBJECT_BUILTIN || DUK_USE_REFLECT_BUILTIN */
41819
41820#if defined(DUK_USE_OBJECT_BUILTIN) || defined(DUK_USE_REFLECT_BUILTIN)
41822 /*
41823 * magic = 0: Object.defineProperty()
41824 * magic = 1: Reflect.defineProperty()
41825 */
41826
41827 duk_hobject *obj;
41828 duk_hstring *key;
41829 duk_hobject *get;
41830 duk_hobject *set;
41831 duk_idx_t idx_value;
41832 duk_uint_t defprop_flags;
41833 duk_small_uint_t magic;
41834 duk_bool_t throw_flag;
41835 duk_bool_t ret;
41836
41837 DUK_ASSERT(thr != NULL);
41838
41839 DUK_DDD(DUK_DDDPRINT("Object.defineProperty(): ctx=%p obj=%!T key=%!T desc=%!T",
41840 (void *) thr,
41841 (duk_tval *) duk_get_tval(thr, 0),
41842 (duk_tval *) duk_get_tval(thr, 1),
41843 (duk_tval *) duk_get_tval(thr, 2)));
41844
41845 /* [ obj key desc ] */
41846
41848
41849 /* Lightfuncs are currently supported by coercing to a temporary
41850 * Function object; changes will be allowed (the coerced value is
41851 * extensible) but will be lost. Same for plain buffers.
41852 */
41854 DUK_ASSERT(obj != NULL);
41855 key = duk_to_property_key_hstring(thr, 1);
41856 (void) duk_require_hobject(thr, 2);
41857
41858 DUK_ASSERT(obj != NULL);
41859 DUK_ASSERT(key != NULL);
41860 DUK_ASSERT(duk_get_hobject(thr, 2) != NULL);
41861
41862 /*
41863 * Validate and convert argument property descriptor (an ECMAScript
41864 * object) into a set of defprop_flags and possibly property value,
41865 * getter, and/or setter values on the value stack.
41866 *
41867 * Lightfunc set/get values are coerced to full Functions.
41868 */
41869
41870 duk_hobject_prepare_property_descriptor(thr, 2 /*idx_desc*/, &defprop_flags, &idx_value, &get, &set);
41871
41872 /*
41873 * Use Object.defineProperty() helper for the actual operation.
41874 */
41875
41876 DUK_ASSERT(magic == 0U || magic == 1U);
41877 throw_flag = magic ^ 1U;
41878 ret = duk_hobject_define_property_helper(thr, defprop_flags, obj, key, idx_value, get, set, throw_flag);
41879
41880 /* Ignore the normalize/validate helper outputs on the value stack,
41881 * they're popped automatically.
41882 */
41883
41884 if (magic == 0U) {
41885 /* Object.defineProperty(): return target object. */
41886 duk_push_hobject(thr, obj);
41887 } else {
41888 /* Reflect.defineProperty(): return success/fail. */
41889 duk_push_boolean(thr, ret);
41890 }
41891 return 1;
41892}
41893#endif /* DUK_USE_OBJECT_BUILTIN || DUK_USE_REFLECT_BUILTIN */
41894
41895#if defined(DUK_USE_OBJECT_BUILTIN) || defined(DUK_USE_REFLECT_BUILTIN)
41897 DUK_ASSERT_TOP(thr, 2);
41898
41899 /* ES2015 Section 19.1.2.6, step 1 */
41900 if (duk_get_current_magic(thr) == 0) {
41901 duk_to_object(thr, 0);
41902 }
41903
41904 /* [ obj key ] */
41905
41907 return 1;
41908}
41909#endif /* DUK_USE_OBJECT_BUILTIN || DUK_USE_REFLECT_BUILTIN */
41910
41911#if defined(DUK_USE_OBJECT_BUILTIN) || defined(DUK_USE_REFLECT_BUILTIN)
41913 /*
41914 * magic = 0: Object.isExtensible()
41915 * magic = 1: Reflect.isExtensible()
41916 */
41917
41918 duk_hobject *h;
41919
41920 if (duk_get_current_magic(thr) == 0) {
41921 h = duk_get_hobject(thr, 0);
41922 } else {
41923 /* Reflect.isExtensible(): throw if non-object, but we accept lightfuncs
41924 * and plain buffers here because they pretend to be objects.
41925 */
41927 }
41928
41930 return 1;
41931}
41932#endif /* DUK_USE_OBJECT_BUILTIN || DUK_USE_REFLECT_BUILTIN */
41933
41934#if defined(DUK_USE_OBJECT_BUILTIN) || defined(DUK_USE_REFLECT_BUILTIN)
41935/* Shared helper for various key/symbol listings, magic:
41936 * 0=Object.keys()
41937 * 1=Object.getOwnPropertyNames(),
41938 * 2=Object.getOwnPropertySymbols(),
41939 * 3=Reflect.ownKeys()
41940 */
41942 /* Object.keys() */
41945 /* Object.getOwnPropertyNames() */
41947
41948 /* Object.getOwnPropertySymbols() */
41951
41952 /* Reflect.ownKeys() */
41954};
41955
41957 duk_hobject *obj;
41958#if defined(DUK_USE_ES6_PROXY)
41959 duk_hobject *h_proxy_target;
41960 duk_hobject *h_proxy_handler;
41961 duk_hobject *h_trap_result;
41962#endif
41963 duk_small_uint_t enum_flags;
41964 duk_int_t magic;
41965
41966 DUK_ASSERT_TOP(thr, 1);
41967
41968 magic = duk_get_current_magic(thr);
41969 if (magic == 3) {
41970 /* ES2015 Section 26.1.11 requires a TypeError for non-objects. Lightfuncs
41971 * and plain buffers pretend to be objects, so accept those too.
41972 */
41974 } else {
41975 /* ES2015: ToObject coerce. */
41976 obj = duk_to_hobject(thr, 0);
41977 }
41978 DUK_ASSERT(obj != NULL);
41979 DUK_UNREF(obj);
41980
41981 /* XXX: proxy chains */
41982
41983#if defined(DUK_USE_ES6_PROXY)
41984 /* XXX: better sharing of code between proxy target call sites */
41985 if (DUK_LIKELY(!duk_hobject_proxy_check(obj, &h_proxy_target, &h_proxy_handler))) {
41986 goto skip_proxy;
41987 }
41988
41989 duk_push_hobject(thr, h_proxy_handler);
41991 /* Careful with reachability here: don't pop 'obj' before pushing
41992 * proxy target.
41993 */
41994 DUK_DDD(DUK_DDDPRINT("no ownKeys trap, get keys of target instead"));
41995 duk_pop_2(thr);
41996 duk_push_hobject(thr, h_proxy_target);
41997 duk_replace(thr, 0);
41998 DUK_ASSERT_TOP(thr, 1);
41999 goto skip_proxy;
42000 }
42001
42002 /* [ obj handler trap ] */
42003 duk_insert(thr, -2);
42004 duk_push_hobject(thr, h_proxy_target); /* -> [ obj trap handler target ] */
42005 duk_call_method(thr, 1 /*nargs*/); /* -> [ obj trap_result ] */
42006 h_trap_result = duk_require_hobject(thr, -1);
42007 DUK_UNREF(h_trap_result);
42008
42009 magic = duk_get_current_magic(thr);
42010 DUK_ASSERT(magic >= 0 && magic < (duk_int_t) (sizeof(duk__object_keys_enum_flags) / sizeof(duk_small_uint_t)));
42011 enum_flags = duk__object_keys_enum_flags[magic];
42012
42013 duk_proxy_ownkeys_postprocess(thr, h_proxy_target, enum_flags);
42014 return 1;
42015
42016skip_proxy:
42017#endif /* DUK_USE_ES6_PROXY */
42018
42019 DUK_ASSERT_TOP(thr, 1);
42020 magic = duk_get_current_magic(thr);
42021 DUK_ASSERT(magic >= 0 && magic < (duk_int_t) (sizeof(duk__object_keys_enum_flags) / sizeof(duk_small_uint_t)));
42022 enum_flags = duk__object_keys_enum_flags[magic];
42023 return duk_hobject_get_enumerated_keys(thr, enum_flags);
42024}
42025#endif /* DUK_USE_OBJECT_BUILTIN || DUK_USE_REFLECT_BUILTIN */
42026
42027#if defined(DUK_USE_OBJECT_BUILTIN) || defined(DUK_USE_REFLECT_BUILTIN)
42029 /*
42030 * magic = 0: Object.preventExtensions()
42031 * magic = 1: Reflect.preventExtensions()
42032 */
42033
42034 duk_hobject *h;
42035 duk_uint_t mask;
42036 duk_int_t magic;
42037
42038 magic = duk_get_current_magic(thr);
42039
42040 /* Silent success for lightfuncs and plain buffers always. */
42042
42043 /* Object.preventExtensions() silent success for non-object. */
42044 if (magic == 0) {
42047 }
42048
42049 if (duk_check_type_mask(thr, 0, mask)) {
42050 /* Not an object, already non-extensible so always success. */
42051 goto done;
42052 }
42053 h = duk_require_hobject(thr, 0);
42054 DUK_ASSERT(h != NULL);
42055
42057
42058 /* A non-extensible object cannot gain any more properties,
42059 * so this is a good time to compact.
42060 */
42062
42063done:
42064 if (magic == 1) {
42065 duk_push_true(thr);
42066 }
42067 return 1;
42068}
42069#endif /* DUK_USE_OBJECT_BUILTIN || DUK_USE_REFLECT_BUILTIN */
42070
42071/*
42072 * __defineGetter__, __defineSetter__, __lookupGetter__, __lookupSetter__
42073 */
42074
42075#if defined(DUK_USE_ES8)
42077 duk_push_this(thr);
42078 duk_insert(thr, 0);
42080 duk_require_callable(thr, 2);
42081
42082 /* [ ToObject(this) key getter/setter ] */
42083
42084 /* ToPropertyKey() coercion is not needed, duk_def_prop() does it. */
42085 duk_def_prop(thr,
42086 0,
42089 return 0;
42090}
42092 duk_uint_t sanity;
42093
42094 duk_push_this(thr);
42095 duk_to_object(thr, -1);
42096
42097 /* XXX: Prototype walk (with sanity) should be a core property
42098 * operation, could add a flag to e.g. duk_get_prop_desc().
42099 */
42100
42101 /* ToPropertyKey() coercion is not needed, duk_get_prop_desc() does it. */
42103 while (!duk_is_undefined(thr, -1)) {
42104 /* [ key obj ] */
42105 duk_dup(thr, 0);
42106 duk_get_prop_desc(thr, 1, 0 /*flags*/);
42107 if (!duk_is_undefined(thr, -1)) {
42109 return 1;
42110 }
42111 duk_pop(thr);
42112
42113 if (DUK_UNLIKELY(sanity-- == 0)) {
42115 DUK_WO_NORETURN(return 0;);
42116 }
42117
42118 duk_get_prototype(thr, -1);
42119 duk_remove(thr, -2);
42120 }
42121 return 1;
42122}
42123#endif /* DUK_USE_ES8 */
42124/*
42125 * High resolution time API (performance.now() et al)
42126 *
42127 * API specification: https://encoding.spec.whatwg.org/#ap://www.w3.org/TR/hr-time/
42128 */
42129
42130/* #include duk_internal.h -> already included */
42131
42132#if defined(DUK_USE_PERFORMANCE_BUILTIN)
42134 /* From API spec:
42135 * The DOMHighResTimeStamp type is used to store a time value in
42136 * milliseconds, measured relative from the time origin, global
42137 * monotonic clock, or a time value that represents a duration
42138 * between two DOMHighResTimeStamp's.
42139 */
42141 return 1;
42142}
42143
42144#if 0 /* Missing until semantics decided. */
42145DUK_INTERNAL duk_ret_t duk_bi_performance_timeorigin_getter(duk_hthread *thr) {
42146 /* No decision yet how to handle timeOrigins, e.g. should one be
42147 * initialized per heap, or per global object set. See
42148 * https://www.w3.org/TR/hr-time/#time-origin.
42149 */
42150 duk_push_uint(thr, 0);
42151 return 1;
42152}
42153#endif /* 0 */
42154#endif /* DUK_USE_PERFORMANCE_BUILTIN */
42155/*
42156 * Pointer built-ins
42157 */
42158
42159/* #include duk_internal.h -> already included */
42160
42161/*
42162 * Constructor
42163 */
42164
42166 /* XXX: this behavior is quite useless now; it would be nice to be able
42167 * to create pointer values from e.g. numbers or strings. Numbers are
42168 * problematic on 64-bit platforms though. Hex encoded strings?
42169 */
42170 if (duk_get_top(thr) == 0) {
42171 duk_push_pointer(thr, NULL);
42172 } else {
42173 duk_to_pointer(thr, 0);
42174 }
42175 DUK_ASSERT(duk_is_pointer(thr, 0));
42176 duk_set_top(thr, 1);
42177
42178 if (duk_is_constructor_call(thr)) {
42179 (void) duk_push_object_helper(thr,
42183
42184 /* Pointer object internal value is immutable. */
42187 }
42188 /* Note: unbalanced stack on purpose */
42189
42190 return 1;
42191}
42192
42193/*
42194 * toString(), valueOf()
42195 */
42196
42198 duk_tval *tv;
42199 duk_small_int_t to_string = duk_get_current_magic(thr);
42200
42201 duk_push_this(thr);
42202 tv = duk_require_tval(thr, -1);
42203 DUK_ASSERT(tv != NULL);
42204
42205 if (DUK_TVAL_IS_POINTER(tv)) {
42206 /* nop */
42207 } else if (DUK_TVAL_IS_OBJECT(tv)) {
42209 DUK_ASSERT(h != NULL);
42210
42211 /* Must be a "pointer object", i.e. class "Pointer" */
42213 goto type_error;
42214 }
42215
42217 } else {
42218 goto type_error;
42219 }
42220
42221 if (to_string) {
42222 duk_to_string(thr, -1);
42223 }
42224 return 1;
42225
42226type_error:
42228}
42229/*
42230 * Promise built-in
42231 */
42232
42233/* #include duk_internal.h -> already included */
42234
42235#if defined(DUK_USE_PROMISE_BUILTIN)
42236
42237DUK_INTERNAL duk_ret_t duk_bi_promise_constructor(duk_hthread *thr) {
42238 DUK_ERROR_TYPE(thr, "unimplemented");
42239 DUK_WO_NORETURN(return 0;);
42240}
42241
42242DUK_INTERNAL duk_ret_t duk_bi_promise_all(duk_hthread *thr) {
42243 DUK_ERROR_TYPE(thr, "unimplemented");
42244 DUK_WO_NORETURN(return 0;);
42245}
42246
42247DUK_INTERNAL duk_ret_t duk_bi_promise_race(duk_hthread *thr) {
42248 DUK_ERROR_TYPE(thr, "unimplemented");
42249 DUK_WO_NORETURN(return 0;);
42250}
42251
42252DUK_INTERNAL duk_ret_t duk_bi_promise_reject(duk_hthread *thr) {
42253 DUK_ERROR_TYPE(thr, "unimplemented");
42254 DUK_WO_NORETURN(return 0;);
42255}
42256
42257DUK_INTERNAL duk_ret_t duk_bi_promise_resolve(duk_hthread *thr) {
42258 DUK_ERROR_TYPE(thr, "unimplemented");
42259 DUK_WO_NORETURN(return 0;);
42260}
42261
42262DUK_INTERNAL duk_ret_t duk_bi_promise_catch(duk_hthread *thr) {
42263 DUK_ERROR_TYPE(thr, "unimplemented");
42264 DUK_WO_NORETURN(return 0;);
42265}
42266
42267DUK_INTERNAL duk_ret_t duk_bi_promise_then(duk_hthread *thr) {
42268 DUK_ERROR_TYPE(thr, "unimplemented");
42269 DUK_WO_NORETURN(return 0;);
42270}
42271
42272#endif /* DUK_USE_PROMISE_BUILTIN */
42273/*
42274 * Proxy built-in (ES2015)
42275 */
42276
42277/* #include duk_internal.h -> already included */
42278
42279#if defined(DUK_USE_ES6_PROXY)
42280/* Post-process a Proxy ownKeys() result at stack top. Push a cleaned up
42281 * array of valid result keys (strings or symbols). TypeError for invalid
42282 * values. Flags are shared with duk_enum().
42283 */
42285 duk_uarridx_t i, len, idx;
42286 duk_propdesc desc;
42287
42289 DUK_ASSERT(h_proxy_target != NULL);
42290
42291 len = (duk_uarridx_t) duk_get_length(thr, -1);
42292 idx = 0;
42293 duk_push_array(thr);
42294 /* XXX: preallocated dense array, fill in directly */
42295 for (i = 0; i < len; i++) {
42296 duk_hstring *h;
42297
42298 /* [ obj trap_result res_arr ] */
42299 (void) duk_get_prop_index(thr, -2, i);
42300 h = duk_get_hstring(thr, -1);
42301 if (h == NULL) {
42303 DUK_WO_NORETURN(return;);
42304 }
42305
42306 if (!(flags & DUK_ENUM_INCLUDE_NONENUMERABLE)) {
42307 /* No support for 'getOwnPropertyDescriptor' trap yet,
42308 * so check enumerability always from target object
42309 * descriptor.
42310 */
42311 if (duk_hobject_get_own_propdesc(thr, h_proxy_target, duk_known_hstring(thr, -1), &desc, 0 /*flags*/)) {
42312 if ((desc.flags & DUK_PROPDESC_FLAG_ENUMERABLE) == 0) {
42313 DUK_DDD(DUK_DDDPRINT("ignore non-enumerable property: %!T", duk_get_tval(thr, -1)));
42314 goto skip_key;
42315 }
42316 } else {
42317 DUK_DDD(DUK_DDDPRINT("ignore non-existent property: %!T", duk_get_tval(thr, -1)));
42318 goto skip_key;
42319 }
42320 }
42322 if (!(flags & DUK_ENUM_INCLUDE_SYMBOLS)) {
42323 DUK_DDD(DUK_DDDPRINT("ignore symbol property: %!T", duk_get_tval(thr, -1)));
42324 goto skip_key;
42325 }
42326 if (DUK_HSTRING_HAS_HIDDEN(h) && !(flags & DUK_ENUM_INCLUDE_HIDDEN)) {
42327 DUK_DDD(DUK_DDDPRINT("ignore hidden symbol property: %!T", duk_get_tval(thr, -1)));
42328 goto skip_key;
42329 }
42330 } else {
42331 if (flags & DUK_ENUM_EXCLUDE_STRINGS) {
42332 DUK_DDD(DUK_DDDPRINT("ignore string property: %!T", duk_get_tval(thr, -1)));
42333 goto skip_key;
42334 }
42335 }
42336
42337 /* [ obj trap_result res_arr propname ] */
42338 duk_push_uarridx(thr, idx++);
42339 duk_insert(thr, -2);
42341 continue;
42342
42343 skip_key:
42344 duk_pop(thr);
42345 continue;
42346 }
42347
42348 /* XXX: Missing trap result validation for non-configurable target keys
42349 * (must be present), for non-extensible target all target keys must be
42350 * present and no extra keys can be present.
42351 * http://www.ecma-international.org/ecma-262/6.0/#sec-proxy-object-internal-methods-and-internal-slots-ownpropertykeys
42352 */
42353
42354 /* XXX: The key enumerability check should trigger the "getOwnPropertyDescriptor"
42355 * trap which has not yet been implemented. In the absence of such a trap,
42356 * the enumerability should be checked from the target object; this is
42357 * handled above.
42358 */
42359}
42360#endif /* DUK_USE_ES6_PROXY */
42361
42362#if defined(DUK_USE_ES6_PROXY)
42364 DUK_ASSERT_TOP(thr, 2); /* [ target handler ] */
42365
42367 duk_push_proxy(thr, 0 /*flags*/); /* [ target handler ] -> [ proxy ] */
42368 return 1; /* replacement */
42369}
42370#endif /* DUK_USE_ES6_PROXY */
42371/*
42372 * 'Reflect' built-in (ES2016 Section 26.1)
42373 * http://www.ecma-international.org/ecma-262/7.0/#sec-reflect-object
42374 *
42375 * Many Reflect built-in functions are provided by shared helpers in
42376 * duk_bi_object.c or duk_bi_function.c.
42377 */
42378
42379/* #include duk_internal.h -> already included */
42380
42381#if defined(DUK_USE_REFLECT_BUILTIN)
42383 duk_tval *tv_obj;
42384 duk_tval *tv_key;
42385 duk_bool_t ret;
42386
42387 DUK_ASSERT_TOP(thr, 2);
42388 (void) duk_require_hobject(thr, 0);
42389 (void) duk_to_string(thr, 1);
42390
42391 /* [ target key ] */
42392
42393 DUK_ASSERT(thr != NULL);
42394 tv_obj = DUK_GET_TVAL_POSIDX(thr, 0);
42395 tv_key = DUK_GET_TVAL_POSIDX(thr, 1);
42396 ret = duk_hobject_delprop(thr, tv_obj, tv_key, 0 /*throw_flag*/);
42397 duk_push_boolean(thr, ret);
42398 return 1;
42399}
42400
42402 duk_tval *tv_obj;
42403 duk_tval *tv_key;
42404 duk_idx_t nargs;
42405
42406 DUK_ASSERT(thr != NULL);
42407 nargs = duk_get_top_require_min(thr, 2 /*min_top*/);
42408 (void) duk_require_hobject(thr, 0);
42409 (void) duk_to_string(thr, 1);
42410 if (nargs >= 3 && !duk_strict_equals(thr, 0, 2)) {
42411 /* XXX: [[Get]] receiver currently unsupported */
42413 DUK_WO_NORETURN(return 0;);
42414 }
42415
42416 /* [ target key receiver? ...? ] */
42417
42418 tv_obj = DUK_GET_TVAL_POSIDX(thr, 0);
42419 tv_key = DUK_GET_TVAL_POSIDX(thr, 1);
42420 (void) duk_hobject_getprop(thr, tv_obj, tv_key); /* This could also be a duk_get_prop(). */
42421 return 1;
42422}
42423
42425 duk_tval *tv_obj;
42426 duk_tval *tv_key;
42427 duk_bool_t ret;
42428
42429 DUK_ASSERT(thr != NULL);
42430 DUK_ASSERT_TOP(thr, 2);
42431 (void) duk_require_hobject(thr, 0);
42432 (void) duk_to_string(thr, 1);
42433
42434 /* [ target key ] */
42435
42436 tv_obj = DUK_GET_TVAL_POSIDX(thr, 0);
42437 tv_key = DUK_GET_TVAL_POSIDX(thr, 1);
42438 ret = duk_hobject_hasprop(thr, tv_obj, tv_key);
42439 duk_push_boolean(thr, ret);
42440 return 1;
42441}
42442
42444 duk_tval *tv_obj;
42445 duk_tval *tv_key;
42446 duk_tval *tv_val;
42447 duk_idx_t nargs;
42448 duk_bool_t ret;
42449
42450 DUK_ASSERT(thr != NULL);
42451 nargs = duk_get_top_require_min(thr, 3 /*min_top*/);
42452 (void) duk_require_hobject(thr, 0);
42453 (void) duk_to_string(thr, 1);
42454 if (nargs >= 4 && !duk_strict_equals(thr, 0, 3)) {
42455 /* XXX: [[Set]] receiver currently unsupported */
42457 DUK_WO_NORETURN(return 0;);
42458 }
42459
42460 /* [ target key value receiver? ...? ] */
42461
42462 tv_obj = DUK_GET_TVAL_POSIDX(thr, 0);
42463 tv_key = DUK_GET_TVAL_POSIDX(thr, 1);
42464 tv_val = DUK_GET_TVAL_POSIDX(thr, 2);
42465 ret = duk_hobject_putprop(thr, tv_obj, tv_key, tv_val, 0 /*throw_flag*/);
42467 return 1;
42468}
42469#endif /* DUK_USE_REFLECT_BUILTIN */
42470/*
42471 * RegExp built-ins
42472 */
42473
42474/* #include duk_internal.h -> already included */
42475
42476#if defined(DUK_USE_REGEXP_SUPPORT)
42479 duk_hobject *h;
42480
42481 duk_push_this(thr);
42483 DUK_ASSERT(h != NULL);
42484 DUK_UNREF(h);
42485 duk_insert(thr, 0); /* prepend regexp to valstack 0 index */
42486}
42487
42488/* XXX: much to improve (code size) */
42490 duk_hobject *h_pattern;
42491
42492 DUK_ASSERT_TOP(thr, 2);
42493 h_pattern = duk_get_hobject(thr, 0);
42494
42495 if (!duk_is_constructor_call(thr) && h_pattern != NULL &&
42497 /* Called as a function, pattern has [[Class]] "RegExp" and
42498 * flags is undefined -> return object as is.
42499 */
42500 /* XXX: ES2015 has a NewTarget SameValue() check which is not
42501 * yet implemented.
42502 */
42503 duk_dup_0(thr);
42504 return 1;
42505 }
42506
42507 /* Else functionality is identical for function call and constructor
42508 * call.
42509 */
42510
42511 if (h_pattern != NULL && DUK_HOBJECT_GET_CLASS_NUMBER(h_pattern) == DUK_HOBJECT_CLASS_REGEXP) {
42513 if (duk_is_undefined(thr, 1)) {
42514 /* In ES5 one would need to read the flags individually;
42515 * in ES2015 just read .flags.
42516 */
42518 } else {
42519 /* In ES2015 allowed; overrides argument RegExp flags. */
42520 duk_dup_1(thr);
42521 }
42522 } else {
42523 if (duk_is_undefined(thr, 0)) {
42525 } else {
42526 duk_dup_0(thr);
42527 duk_to_string(thr, -1); /* Rejects Symbols. */
42528 }
42529 if (duk_is_undefined(thr, 1)) {
42531 } else {
42532 duk_dup_1(thr);
42533 duk_to_string(thr, -1); /* Rejects Symbols. */
42534 }
42535
42536 /* [ ... pattern flags ] */
42537 }
42538
42539 DUK_DDD(DUK_DDDPRINT("RegExp constructor/function call, pattern=%!T, flags=%!T",
42540 (duk_tval *) duk_get_tval(thr, -2),
42541 (duk_tval *) duk_get_tval(thr, -1)));
42542
42543 /* [ ... pattern flags ] (both uncoerced) */
42544
42545 duk_to_string(thr, -2);
42547 duk_regexp_compile(thr);
42548
42549 /* [ ... bytecode escaped_source ] */
42550
42552
42553 /* [ ... RegExp ] */
42554
42555 return 1;
42556}
42557
42560
42561 /* [ regexp input ] */
42562
42563 duk_regexp_match(thr);
42564
42565 /* [ result ] */
42566
42567 return 1;
42568}
42569
42572
42573 /* [ regexp input ] */
42574
42575 /* result object is created and discarded; wasteful but saves code space */
42576 duk_regexp_match(thr);
42577
42578 /* [ result ] */
42579
42580 duk_push_boolean(thr, (duk_is_null(thr, -1) ? 0 : 1));
42581
42582 return 1;
42583}
42584
42586 /* This must be generic in ES2015 and later. */
42587 DUK_ASSERT_TOP(thr, 0);
42588 duk_push_this(thr);
42589 duk_push_literal(thr, "/");
42591 duk_dup_m2(thr); /* another "/" */
42593 duk_concat(thr, 4);
42594 return 1;
42595}
42596
42598 /* .flags is ES2015 but present even when ES2015 bindings are
42599 * disabled because the constructor relies on it.
42600 */
42601 duk_uint8_t buf[8]; /* enough for all flags + NUL */
42602 duk_uint8_t *p = buf;
42603
42604 /* .flags is generic and works on any object. */
42605 duk_push_this(thr);
42606 (void) duk_require_hobject(thr, -1);
42608 *p++ = DUK_ASC_LC_G;
42609 }
42611 *p++ = DUK_ASC_LC_I;
42612 }
42615 }
42616 /* .unicode: to be added */
42617 /* .sticky: to be added */
42618 *p++ = DUK_ASC_NUL;
42619 DUK_ASSERT((duk_size_t) (p - buf) <= sizeof(buf));
42620
42621 duk_push_string(thr, (const char *) buf);
42622 return 1;
42623}
42624
42625/* Shared helper for providing .source, .global, .multiline, etc getters. */
42627 duk_hstring *h_bc;
42628 duk_small_uint_t re_flags;
42629 duk_hobject *h;
42630 duk_int_t magic;
42631
42632 DUK_ASSERT_TOP(thr, 0);
42633
42634 duk_push_this(thr);
42635 h = duk_require_hobject(thr, -1);
42636 magic = duk_get_current_magic(thr);
42637
42641 h_bc = duk_require_hstring(thr, -1);
42642 re_flags = (duk_small_uint_t) DUK_HSTRING_GET_DATA(h_bc)[0]; /* Safe even if h_bc length is 0 (= NUL) */
42643 duk_pop(thr);
42644 } else if (h == thr->builtins[DUK_BIDX_REGEXP_PROTOTYPE]) {
42645 /* In ES2015 and ES2016 a TypeError would be thrown here.
42646 * However, this had real world issues so ES2017 draft
42647 * allows RegExp.prototype specifically, returning '(?:)'
42648 * for .source and undefined for all flags.
42649 */
42650 if (magic != 16 /* .source */) {
42651 return 0;
42652 }
42653 duk_push_literal(thr, "(?:)"); /* .source handled by switch-case */
42654 re_flags = 0;
42655 } else {
42657 }
42658
42659 /* [ regexp source ] */
42660
42661 switch (magic) {
42662 case 0: { /* global */
42663 duk_push_boolean(thr, (re_flags & DUK_RE_FLAG_GLOBAL));
42664 break;
42665 }
42666 case 1: { /* ignoreCase */
42667 duk_push_boolean(thr, (re_flags & DUK_RE_FLAG_IGNORE_CASE));
42668 break;
42669 }
42670 case 2: { /* multiline */
42671 duk_push_boolean(thr, (re_flags & DUK_RE_FLAG_MULTILINE));
42672 break;
42673 }
42674#if 0
42675 /* Don't provide until implemented to avoid interfering with feature
42676 * detection in user code.
42677 */
42678 case 3: /* sticky */
42679 case 4: { /* unicode */
42680 duk_push_false(thr);
42681 break;
42682 }
42683#endif
42684 default: { /* source */
42685 /* leave 'source' on top */
42686 break;
42687 }
42688 }
42689
42690 return 1;
42691}
42692
42693#endif /* DUK_USE_REGEXP_SUPPORT */
42694/*
42695 * String built-ins
42696 *
42697 * Most String built-ins must only accept strings (or String objects).
42698 * Symbols, represented internally as strings, must be generally rejected.
42699 * The duk_push_this_coercible_to_string() helper does this automatically.
42700 */
42701
42702/* XXX: There are several limitations in the current implementation for
42703 * strings with >= 0x80000000UL characters. In some cases one would need
42704 * to be able to represent the range [-0xffffffff,0xffffffff] and so on.
42705 * Generally character and byte length are assumed to fit into signed 32
42706 * bits (< 0x80000000UL). Places with issues are not marked explicitly
42707 * below in all cases, look for signed type usage (duk_int_t etc) for
42708 * offsets/lengths.
42709 */
42710
42711/* #include duk_internal.h -> already included */
42712
42713#if defined(DUK_USE_STRING_BUILTIN)
42714
42715/*
42716 * Helpers
42717 */
42718
42720 duk_hstring *h;
42724 DUK_WO_NORETURN(return NULL;);
42725 }
42726 h = duk_to_hstring(thr, idx);
42727 DUK_ASSERT(h != NULL);
42728
42729 return h;
42730}
42731
42733duk__str_search_shared(duk_hthread *thr, duk_hstring *h_this, duk_hstring *h_search, duk_int_t start_cpos, duk_bool_t backwards) {
42734 duk_int_t cpos;
42735 duk_int_t bpos;
42736 const duk_uint8_t *p_start, *p_end, *p;
42737 const duk_uint8_t *q_start;
42738 duk_int_t q_blen;
42739 duk_uint8_t firstbyte;
42740 duk_uint8_t t;
42741
42742 cpos = start_cpos;
42743
42744 /* Empty searchstring always matches; cpos must be clamped here.
42745 * (If q_blen were < 0 due to clamped coercion, it would also be
42746 * caught here.)
42747 */
42748 q_start = DUK_HSTRING_GET_DATA(h_search);
42749 q_blen = (duk_int_t) DUK_HSTRING_GET_BYTELEN(h_search);
42750 if (q_blen <= 0) {
42751 return cpos;
42752 }
42753 DUK_ASSERT(q_blen > 0);
42754
42755 bpos = (duk_int_t) duk_heap_strcache_offset_char2byte(thr, h_this, (duk_uint32_t) cpos);
42756
42757 p_start = DUK_HSTRING_GET_DATA(h_this);
42758 p_end = p_start + DUK_HSTRING_GET_BYTELEN(h_this);
42759 p = p_start + bpos;
42760
42761 /* This loop is optimized for size. For speed, there should be
42762 * two separate loops, and we should ensure that memcmp() can be
42763 * used without an extra "will searchstring fit" check. Doing
42764 * the preconditioning for 'p' and 'p_end' is easy but cpos
42765 * must be updated if 'p' is wound back (backward scanning).
42766 */
42767
42768 firstbyte = q_start[0]; /* leading byte of match string */
42769 while (p <= p_end && p >= p_start) {
42770 t = *p;
42771
42772 /* For ECMAScript strings, this check can only match for
42773 * initial UTF-8 bytes (not continuation bytes). For other
42774 * strings all bets are off.
42775 */
42776
42777 if ((t == firstbyte) && ((duk_size_t) (p_end - p) >= (duk_size_t) q_blen)) {
42778 DUK_ASSERT(q_blen > 0);
42779 if (duk_memcmp((const void *) p, (const void *) q_start, (size_t) q_blen) == 0) {
42780 return cpos;
42781 }
42782 }
42783
42784 /* track cpos while scanning */
42785 if (backwards) {
42786 /* when going backwards, we decrement cpos 'early';
42787 * 'p' may point to a continuation byte of the char
42788 * at offset 'cpos', but that's OK because we'll
42789 * backtrack all the way to the initial byte.
42790 */
42791 if ((t & 0xc0) != 0x80) {
42792 cpos--;
42793 }
42794 p--;
42795 } else {
42796 if ((t & 0xc0) != 0x80) {
42797 cpos++;
42798 }
42799 p++;
42800 }
42801 }
42802
42803 /* Not found. Empty string case is handled specially above. */
42804 return -1;
42805}
42806
42807/*
42808 * Constructor
42809 */
42810
42812 duk_hstring *h;
42813 duk_uint_t flags;
42814
42815 /* String constructor needs to distinguish between an argument not given at all
42816 * vs. given as 'undefined'. We're a vararg function to handle this properly.
42817 */
42818
42819 /* XXX: copy current activation flags to thr, including current magic,
42820 * is_constructor_call etc. This takes a few bytes in duk_hthread but
42821 * makes call sites smaller (there are >30 is_constructor_call and get
42822 * current magic call sites.
42823 */
42824
42825 if (duk_get_top(thr) == 0) {
42827 } else {
42828 h = duk_to_hstring_acceptsymbol(thr, 0);
42831 duk_replace(thr, 0);
42832 }
42833 }
42834 duk_to_string(thr, 0); /* catches symbol argument for constructor call */
42835 DUK_ASSERT(duk_is_string(thr, 0));
42836 duk_set_top(thr, 1); /* Top may be 1 or larger. */
42837
42838 if (duk_is_constructor_call(thr)) {
42839 /* String object internal value is immutable */
42843 duk_dup_0(thr);
42845 }
42846 /* Note: unbalanced stack on purpose */
42847
42848 return 1;
42849}
42850
42852 duk_bufwriter_ctx bw_alloc;
42854 duk_idx_t i, n;
42856
42857 /* XXX: It would be nice to build the string directly but ToUint16()
42858 * coercion is needed so a generic helper would not be very
42859 * helpful (perhaps coerce the value stack first here and then
42860 * build a string from a duk_tval number sequence in one go?).
42861 */
42862
42863 n = duk_get_top(thr);
42864
42865 bw = &bw_alloc;
42866 DUK_BW_INIT_PUSHBUF(thr, bw, (duk_size_t) n); /* initial estimate for ASCII only codepoints */
42867
42868 for (i = 0; i < n; i++) {
42869 /* XXX: could improve bufwriter handling to write multiple codepoints
42870 * with one ensure call but the relative benefit would be quite small.
42871 */
42872
42873 if (nonbmp) {
42874 /* ES2015 requires that (1) SameValue(cp, ToInteger(cp)) and
42875 * (2) cp >= 0 and cp <= 0x10ffff. This check does not
42876 * implement the steps exactly but the outcome should be
42877 * the same.
42878 */
42879 duk_int32_t i32 = 0;
42880 if (!duk_is_whole_get_int32(duk_to_number(thr, i), &i32) || i32 < 0 || i32 > 0x10ffffL) {
42882 }
42883 DUK_ASSERT(i32 >= 0 && i32 <= 0x10ffffL);
42884 cp = (duk_ucodepoint_t) i32;
42885 DUK_BW_WRITE_ENSURE_CESU8(thr, bw, cp);
42886 } else {
42887#if defined(DUK_USE_NONSTD_STRING_FROMCHARCODE_32BIT)
42888 /* ToUint16() coercion is mandatory in the E5.1 specification, but
42889 * this non-compliant behavior makes more sense because we support
42890 * non-BMP codepoints. Don't use CESU-8 because that'd create
42891 * surrogate pairs.
42892 */
42893 cp = (duk_ucodepoint_t) duk_to_uint32(thr, i);
42894 DUK_BW_WRITE_ENSURE_XUTF8(thr, bw, cp);
42895#else
42897 DUK_ASSERT(cp >= 0 && cp <= 0x10ffffL);
42898 DUK_BW_WRITE_ENSURE_CESU8(thr, bw, cp);
42899#endif
42900 }
42902
42903 DUK_BW_COMPACT(thr, bw);
42904 (void) duk_buffer_to_string(thr, -1); /* Safe, extended UTF-8 or CESU-8 encoded. */
42905 return 1;
42906}
42907
42909 return duk__construct_from_codepoints(thr, 0 /*nonbmp*/);
42911
42912#if defined(DUK_USE_ES6)
42914 return duk__construct_from_codepoints(thr, 1 /*nonbmp*/);
42915}
42916#endif
42917
42918/*
42919 * toString(), valueOf()
42920 */
42921
42923 duk_tval *tv;
42924
42925 duk_push_this(thr);
42926 tv = duk_require_tval(thr, -1);
42927 DUK_ASSERT(tv != NULL);
42928
42929 if (DUK_TVAL_IS_STRING(tv)) {
42930 /* return as is */
42931 } else if (DUK_TVAL_IS_OBJECT(tv)) {
42933 DUK_ASSERT(h != NULL);
42934
42935 /* Must be a "string object", i.e. class "String" */
42937 goto type_error;
42938 }
42939
42941 DUK_ASSERT(duk_is_string(thr, -1));
42942 } else {
42943 goto type_error;
42944 }
42946 (void) duk_require_hstring_notsymbol(thr, -1); /* Reject symbols (and wrapped symbols). */
42947 return 1;
42948
42949type_error:
42951}
42952
42953/*
42954 * Character and charcode access
42955 */
42956
42958 duk_hstring *h;
42959 duk_int_t pos;
42960
42961 /* XXX: faster implementation */
42962
42964 DUK_ASSERT(h != NULL);
42965
42966 pos = duk_to_int(thr, 0);
42967
42968 if (sizeof(duk_size_t) >= sizeof(duk_uint_t)) {
42969 /* Cast to duk_size_t works in this case:
42970 * - If pos < 0, (duk_size_t) pos will always be
42971 * >= max_charlen, and result will be the empty string
42972 * (see duk_substring()).
42973 * - If pos >= 0, pos + 1 cannot wrap.
42974 */
42977 duk_substring(thr, -1, (duk_size_t) pos, (duk_size_t) pos + 1U);
42978 } else {
42979 /* If size_t is smaller than int, explicit bounds checks
42980 * are needed because an int may wrap multiple times.
42982 if (DUK_UNLIKELY(pos < 0 || (duk_uint_t) pos >= (duk_uint_t) DUK_HSTRING_GET_CHARLEN(h))) {
42984 } else {
42985 duk_substring(thr, -1, (duk_size_t) pos, (duk_size_t) pos + 1U);
42986 }
42987 }
42988
42989 return 1;
42990}
42991
42992/* Magic: 0=charCodeAt, 1=codePointAt */
42994 duk_int_t pos;
42995 duk_hstring *h;
42996 duk_bool_t clamped;
42997 duk_uint32_t cp;
42998 duk_int_t magic;
42999
43000 /* XXX: faster implementation */
43001
43002 DUK_DDD(DUK_DDDPRINT("arg=%!T", (duk_tval *) duk_get_tval(thr, 0)));
43003
43005 DUK_ASSERT(h != NULL);
43006
43007 pos = duk_to_int_clamped_raw(thr,
43008 0 /*index*/,
43009 0 /*min(incl)*/,
43010 (duk_int_t) DUK_HSTRING_GET_CHARLEN(h) - 1 /*max(incl)*/,
43011 &clamped /*out_clamped*/);
43012#if defined(DUK_USE_ES6)
43013 magic = duk_get_current_magic(thr);
43014#else
43016 magic = 0;
43017#endif
43018 if (clamped) {
43019 /* For out-of-bounds indices .charCodeAt() returns NaN and
43020 * .codePointAt() returns undefined.
43021 */
43022 if (magic != 0) {
43023 return 0;
43024 }
43025 duk_push_nan(thr);
43026 } else {
43027 DUK_ASSERT(pos >= 0);
43028 cp = (duk_uint32_t) duk_hstring_char_code_at_raw(thr, h, (duk_uint_t) pos, (duk_bool_t) magic /*surrogate_aware*/);
43029 duk_push_u32(thr, cp);
43031 return 1;
43032}
43033
43034/*
43035 * substring(), substr(), slice()
43036 */
43037
43038/* XXX: any chance of merging these three similar but still slightly
43039 * different algorithms so that footprint would be reduced?
43040 */
43041
43043 duk_hstring *h;
43044 duk_int_t start_pos, end_pos;
43045 duk_int_t len;
43046
43048 DUK_ASSERT(h != NULL);
43050
43051 /* [ start end str ] */
43052
43053 start_pos = duk_to_int_clamped(thr, 0, 0, len);
43054 if (duk_is_undefined(thr, 1)) {
43055 end_pos = len;
43056 } else {
43057 end_pos = duk_to_int_clamped(thr, 1, 0, len);
43058 }
43059 DUK_ASSERT(start_pos >= 0 && start_pos <= len);
43060 DUK_ASSERT(end_pos >= 0 && end_pos <= len);
43061
43062 if (start_pos > end_pos) {
43063 duk_int_t tmp = start_pos;
43064 start_pos = end_pos;
43065 end_pos = tmp;
43066 }
43067
43068 DUK_ASSERT(end_pos >= start_pos);
43069
43070 duk_substring(thr, -1, (duk_size_t) start_pos, (duk_size_t) end_pos);
43071 return 1;
43072}
43073
43074#if defined(DUK_USE_SECTION_B)
43076 duk_hstring *h;
43077 duk_int_t start_pos, end_pos;
43078 duk_int_t len;
43079
43080 /* Unlike non-obsolete String calls, substr() algorithm in E5.1
43081 * specification will happily coerce undefined and null to strings
43082 * ("undefined" and "null").
43083 */
43084 duk_push_this(thr);
43085 h = duk_to_hstring_m1(thr); /* Reject Symbols. */
43086 DUK_ASSERT(h != NULL);
43088
43089 /* [ start length str ] */
43090
43091 /* The implementation for computing of start_pos and end_pos differs
43092 * from the standard algorithm, but is intended to result in the exactly
43093 * same behavior. This is not always obvious.
43094 */
43095
43096 /* combines steps 2 and 5; -len ensures max() not needed for step 5 */
43097 start_pos = duk_to_int_clamped(thr, 0, -len, len);
43098 if (start_pos < 0) {
43099 start_pos = len + start_pos;
43100 }
43101 DUK_ASSERT(start_pos >= 0 && start_pos <= len);
43102
43103 /* combines steps 3, 6; step 7 is not needed */
43104 if (duk_is_undefined(thr, 1)) {
43105 end_pos = len;
43106 } else {
43107 DUK_ASSERT(start_pos <= len);
43108 end_pos = start_pos + duk_to_int_clamped(thr, 1, 0, len - start_pos);
43109 }
43110 DUK_ASSERT(start_pos >= 0 && start_pos <= len);
43111 DUK_ASSERT(end_pos >= 0 && end_pos <= len);
43112 DUK_ASSERT(end_pos >= start_pos);
43113
43114 duk_substring(thr, -1, (duk_size_t) start_pos, (duk_size_t) end_pos);
43115 return 1;
43116}
43117#endif /* DUK_USE_SECTION_B */
43118
43120 duk_hstring *h;
43121 duk_int_t start_pos, end_pos;
43122 duk_int_t len;
43123
43125 DUK_ASSERT(h != NULL);
43127
43128 /* [ start end str ] */
43129
43130 start_pos = duk_to_int_clamped(thr, 0, -len, len);
43131 if (start_pos < 0) {
43132 start_pos = len + start_pos;
43133 }
43134 if (duk_is_undefined(thr, 1)) {
43135 end_pos = len;
43136 } else {
43137 end_pos = duk_to_int_clamped(thr, 1, -len, len);
43138 if (end_pos < 0) {
43139 end_pos = len + end_pos;
43140 }
43141 }
43142 DUK_ASSERT(start_pos >= 0 && start_pos <= len);
43143 DUK_ASSERT(end_pos >= 0 && end_pos <= len);
43144
43145 if (end_pos < start_pos) {
43146 end_pos = start_pos;
43148
43149 DUK_ASSERT(end_pos >= start_pos);
43150
43151 duk_substring(thr, -1, (duk_size_t) start_pos, (duk_size_t) end_pos);
43152 return 1;
43153}
43154
43155/*
43156 * Case conversion
43157 */
43158
43160 duk_small_int_t uppercase = duk_get_current_magic(thr);
43161
43164 return 1;
43165}
43166
43167/*
43168 * indexOf() and lastIndexOf()
43169 */
43170
43172 duk_hstring *h_this;
43173 duk_hstring *h_search;
43174 duk_int_t clen_this;
43175 duk_int_t cpos;
43176 duk_small_uint_t is_lastindexof = (duk_small_uint_t) duk_get_current_magic(thr); /* 0=indexOf, 1=lastIndexOf */
43177
43179 DUK_ASSERT(h_this != NULL);
43180 clen_this = (duk_int_t) DUK_HSTRING_GET_CHARLEN(h_this);
43181
43182 h_search = duk_to_hstring(thr, 0);
43183 DUK_ASSERT(h_search != NULL);
43184
43185 duk_to_number(thr, 1);
43186 if (duk_is_nan(thr, 1) && is_lastindexof) {
43187 /* indexOf: NaN should cause pos to be zero.
43188 * lastIndexOf: NaN should cause pos to be +Infinity
43189 * (and later be clamped to len).
43190 */
43191 cpos = clen_this;
43192 } else {
43193 cpos = duk_to_int_clamped(thr, 1, 0, clen_this);
43194 }
43195
43196 cpos = duk__str_search_shared(thr, h_this, h_search, cpos, is_lastindexof /*backwards*/);
43197 duk_push_int(thr, cpos);
43198 return 1;
43199}
43200
43201/*
43202 * replace()
43203 */
43205/* XXX: the current implementation works but is quite clunky; it compiles
43206 * to almost 1,4kB of x86 code so it needs to be simplified (better approach,
43207 * shared helpers, etc). Some ideas for refactoring:
43208 *
43209 * - a primitive to convert a string into a regexp matcher (reduces matching
43210 * code at the cost of making matching much slower)
43211 * - use replace() as a basic helper for match() and split(), which are both
43212 * much simpler
43213 * - API call to get_prop and to_boolean
43214 */
43215
43217 duk_hstring *h_input;
43218 duk_hstring *h_match;
43219 duk_hstring *h_search;
43220 duk_hobject *h_re;
43221 duk_bufwriter_ctx bw_alloc;
43223#if defined(DUK_USE_REGEXP_SUPPORT)
43224 duk_bool_t is_regexp;
43225 duk_bool_t is_global;
43226#endif
43227 duk_bool_t is_repl_func;
43228 duk_uint32_t match_start_coff, match_start_boff;
43229#if defined(DUK_USE_REGEXP_SUPPORT)
43230 duk_int_t match_caps;
43231#endif
43232 duk_uint32_t prev_match_end_boff;
43233 const duk_uint8_t *r_start, *r_end, *r; /* repl string scan */
43234 duk_size_t tmp_sz;
43235
43236 DUK_ASSERT_TOP(thr, 2);
43237 h_input = duk_push_this_coercible_to_string(thr);
43238 DUK_ASSERT(h_input != NULL);
43239
43240 bw = &bw_alloc;
43241 DUK_BW_INIT_PUSHBUF(thr, bw, DUK_HSTRING_GET_BYTELEN(h_input)); /* input size is good output starting point */
43242
43243 DUK_ASSERT_TOP(thr, 4);
43244
43245 /* stack[0] = search value
43246 * stack[1] = replace value
43247 * stack[2] = input string
43248 * stack[3] = result buffer
43249 */
43250
43252 if (h_re) {
43253#if defined(DUK_USE_REGEXP_SUPPORT)
43254 is_regexp = 1;
43255 is_global = duk_get_prop_stridx_boolean(thr, 0, DUK_STRIDX_GLOBAL, NULL);
43256
43257 if (is_global) {
43258 /* start match from beginning */
43259 duk_push_int(thr, 0);
43261 }
43262#else /* DUK_USE_REGEXP_SUPPORT */
43264#endif /* DUK_USE_REGEXP_SUPPORT */
43265 } else {
43266 duk_to_string(thr, 0); /* rejects symbols */
43267#if defined(DUK_USE_REGEXP_SUPPORT)
43268 is_regexp = 0;
43269 is_global = 0;
43270#endif
43271 }
43272
43273 if (duk_is_function(thr, 1)) {
43274 is_repl_func = 1;
43275 r_start = NULL;
43276 r_end = NULL;
43277 } else {
43278 duk_hstring *h_repl;
43279
43280 is_repl_func = 0;
43281 h_repl = duk_to_hstring(thr, 1); /* reject symbols */
43282 DUK_ASSERT(h_repl != NULL);
43283 r_start = DUK_HSTRING_GET_DATA(h_repl);
43284 r_end = r_start + DUK_HSTRING_GET_BYTELEN(h_repl);
43285 }
43286
43287 prev_match_end_boff = 0;
43288
43289 for (;;) {
43290 /*
43291 * If matching with a regexp:
43292 * - non-global RegExp: lastIndex not touched on a match, zeroed
43293 * on a non-match
43294 * - global RegExp: on match, lastIndex will be updated by regexp
43295 * executor to point to next char after the matching part (so that
43296 * characters in the matching part are not matched again)
43297 *
43298 * If matching with a string:
43299 * - always non-global match, find first occurrence
43300 *
43301 * We need:
43302 * - The character offset of start-of-match for the replacer function
43303 * - The byte offsets for start-of-match and end-of-match to implement
43304 * the replacement values $&, $`, and $', and to copy non-matching
43305 * input string portions (including header and trailer) verbatim.
43306 *
43307 * NOTE: the E5.1 specification is a bit vague how the RegExp should
43308 * behave in the replacement process; e.g. is matching done first for
43309 * all matches (in the global RegExp case) before any replacer calls
43310 * are made? See: test-bi-string-proto-replace.js for discussion.
43311 */
43312
43313 DUK_ASSERT_TOP(thr, 4);
43314
43315#if defined(DUK_USE_REGEXP_SUPPORT)
43316 if (is_regexp) {
43317 duk_dup_0(thr);
43318 duk_dup_2(thr);
43319 duk_regexp_match(thr); /* [ ... regexp input ] -> [ res_obj ] */
43320 if (!duk_is_object(thr, -1)) {
43321 duk_pop(thr);
43322 break;
43323 }
43324
43326 DUK_ASSERT(duk_is_number(thr, -1));
43327 match_start_coff = duk_get_uint(thr, -1);
43328 duk_pop(thr);
43329
43330 duk_get_prop_index(thr, -1, 0);
43331 DUK_ASSERT(duk_is_string(thr, -1));
43332 h_match = duk_known_hstring(thr, -1);
43333 duk_pop(thr); /* h_match is borrowed, remains reachable through match_obj */
43334
43335 if (DUK_HSTRING_GET_BYTELEN(h_match) == 0) {
43336 /* This should be equivalent to match() algorithm step 8.f.iii.2:
43337 * detect an empty match and allow it, but don't allow it twice.
43338 */
43339 duk_uint32_t last_index;
43340
43342 last_index = (duk_uint32_t) duk_get_uint(thr, -1);
43343 DUK_DDD(DUK_DDDPRINT("empty match, bump lastIndex: %ld -> %ld",
43344 (long) last_index,
43345 (long) (last_index + 1)));
43346 duk_pop(thr);
43347 duk_push_uint(thr, (duk_uint_t) (last_index + 1));
43349 }
43350
43351 DUK_ASSERT(duk_get_length(thr, -1) <= DUK_INT_MAX); /* string limits */
43352 match_caps = (duk_int_t) duk_get_length(thr, -1);
43353 } else {
43354#else /* DUK_USE_REGEXP_SUPPORT */
43355 { /* unconditionally */
43356#endif /* DUK_USE_REGEXP_SUPPORT */
43357 const duk_uint8_t *p_start, *p_end, *p; /* input string scan */
43358 const duk_uint8_t *q_start; /* match string */
43359 duk_size_t p_blen;
43360 duk_size_t q_blen;
43361
43362#if defined(DUK_USE_REGEXP_SUPPORT)
43363 DUK_ASSERT(!is_global); /* single match always */
43364#endif
43365
43366 p_start = DUK_HSTRING_GET_DATA(h_input);
43367 p_end = p_start + DUK_HSTRING_GET_BYTELEN(h_input);
43368 p_blen = (duk_size_t) DUK_HSTRING_GET_BYTELEN(h_input);
43369 p = p_start;
43370
43371 h_search = duk_known_hstring(thr, 0);
43372 q_start = DUK_HSTRING_GET_DATA(h_search);
43373 q_blen = (duk_size_t) DUK_HSTRING_GET_BYTELEN(h_search);
43374
43375 if (q_blen > p_blen) {
43376 break; /* no match */
43377 }
43378
43379 p_end -= q_blen; /* ensure full memcmp() fits in while */
43380 DUK_ASSERT(p_end >= p);
43381
43382 match_start_coff = 0;
43383
43384 while (p <= p_end) {
43385 DUK_ASSERT(p + q_blen <= DUK_HSTRING_GET_DATA(h_input) + DUK_HSTRING_GET_BYTELEN(h_input));
43386 if (duk_memcmp((const void *) p, (const void *) q_start, (size_t) q_blen) == 0) {
43387 duk_dup_0(thr);
43388 h_match = duk_known_hstring(thr, -1);
43389#if defined(DUK_USE_REGEXP_SUPPORT)
43390 match_caps = 0;
43391#endif
43392 goto found;
43393 }
43394
43395 /* track utf-8 non-continuation bytes */
43396 if ((p[0] & 0xc0) != 0x80) {
43397 match_start_coff++;
43398 }
43399 p++;
43400 }
43401
43402 /* not found */
43403 break;
43404 }
43405 found:
43406
43407 /* stack[0] = search value
43408 * stack[1] = replace value
43409 * stack[2] = input string
43410 * stack[3] = result buffer
43411 * stack[4] = regexp match OR match string
43412 */
43413
43414 match_start_boff = (duk_uint32_t) duk_heap_strcache_offset_char2byte(thr, h_input, match_start_coff);
43415
43416 tmp_sz = (duk_size_t) (match_start_boff - prev_match_end_boff);
43417 DUK_BW_WRITE_ENSURE_BYTES(thr, bw, DUK_HSTRING_GET_DATA(h_input) + prev_match_end_boff, tmp_sz);
43418
43419 prev_match_end_boff = match_start_boff + DUK_HSTRING_GET_BYTELEN(h_match);
43420
43421 if (is_repl_func) {
43422 duk_idx_t idx_args;
43423 duk_hstring *h_repl;
43424
43425 /* regexp res_obj is at index 4 */
43426
43427 duk_dup_1(thr);
43428 idx_args = duk_get_top(thr);
43429
43430#if defined(DUK_USE_REGEXP_SUPPORT)
43431 if (is_regexp) {
43432 duk_int_t idx;
43433 duk_require_stack(thr, match_caps + 2);
43434 for (idx = 0; idx < match_caps; idx++) {
43435 /* match followed by capture(s) */
43436 duk_get_prop_index(thr, 4, (duk_uarridx_t) idx);
43437 }
43438 } else {
43439#else /* DUK_USE_REGEXP_SUPPORT */
43440 { /* unconditionally */
43441#endif /* DUK_USE_REGEXP_SUPPORT */
43442 /* match == search string, by definition */
43443 duk_dup_0(thr);
43444 }
43445 duk_push_uint(thr, (duk_uint_t) match_start_coff);
43446 duk_dup_2(thr);
43447
43448 /* [ ... replacer match [captures] match_char_offset input ] */
43449
43450 duk_call(thr, duk_get_top(thr) - idx_args);
43451 h_repl = duk_to_hstring_m1(thr); /* -> [ ... repl_value ] */
43452 DUK_ASSERT(h_repl != NULL);
43453
43454 DUK_BW_WRITE_ENSURE_HSTRING(thr, bw, h_repl);
43455
43456 duk_pop(thr); /* repl_value */
43457 } else {
43458 r = r_start;
43459
43460 while (r < r_end) {
43461 duk_int_t ch1;
43462 duk_int_t ch2;
43463#if defined(DUK_USE_REGEXP_SUPPORT)
43464 duk_int_t ch3;
43465#endif
43466 duk_size_t left;
43467
43468 ch1 = *r++;
43469 if (ch1 != DUK_ASC_DOLLAR) {
43470 goto repl_write;
43471 }
43472 DUK_ASSERT(r <= r_end);
43473 left = (duk_size_t) (r_end - r);
43474
43475 if (left <= 0) {
43476 goto repl_write;
43477 }
43478
43479 ch2 = r[0];
43480 switch (ch2) {
43481 case DUK_ASC_DOLLAR: {
43482 ch1 = (1 << 8) + DUK_ASC_DOLLAR;
43483 goto repl_write;
43484 }
43485 case DUK_ASC_AMP: {
43486 DUK_BW_WRITE_ENSURE_HSTRING(thr, bw, h_match);
43487 r++;
43488 continue;
43489 }
43490 case DUK_ASC_GRAVE: {
43491 tmp_sz = (duk_size_t) match_start_boff;
43492 DUK_BW_WRITE_ENSURE_BYTES(thr, bw, DUK_HSTRING_GET_DATA(h_input), tmp_sz);
43493 r++;
43494 continue;
43495 }
43496 case DUK_ASC_SINGLEQUOTE: {
43497 duk_uint32_t match_end_boff;
43498
43499 /* Use match charlen instead of bytelen, just in case the input and
43500 * match codepoint encodings would have different lengths.
43501 */
43502 /* XXX: charlen computed here, and also in char2byte helper. */
43503 match_end_boff = (duk_uint32_t) duk_heap_strcache_offset_char2byte(
43504 thr,
43505 h_input,
43506 match_start_coff + (duk_uint_fast32_t) DUK_HSTRING_GET_CHARLEN(h_match));
43507
43508 tmp_sz = (duk_size_t) (DUK_HSTRING_GET_BYTELEN(h_input) - match_end_boff);
43509 DUK_BW_WRITE_ENSURE_BYTES(thr, bw, DUK_HSTRING_GET_DATA(h_input) + match_end_boff, tmp_sz);
43510 r++;
43511 continue;
43512 }
43513 default: {
43514#if defined(DUK_USE_REGEXP_SUPPORT)
43515 duk_int_t capnum, captmp, capadv;
43516 /* XXX: optional check, match_caps is zero if no regexp,
43517 * so dollar will be interpreted literally anyway.
43518 */
43519
43520 if (!is_regexp) {
43521 goto repl_write;
43522 }
43523
43524 if (!(ch2 >= DUK_ASC_0 && ch2 <= DUK_ASC_9)) {
43525 goto repl_write;
43526 }
43527 capnum = ch2 - DUK_ASC_0;
43528 capadv = 1;
43529
43530 if (left >= 2) {
43531 ch3 = r[1];
43532 if (ch3 >= DUK_ASC_0 && ch3 <= DUK_ASC_9) {
43533 captmp = capnum * 10 + (ch3 - DUK_ASC_0);
43534 if (captmp < match_caps) {
43535 capnum = captmp;
43536 capadv = 2;
43537 }
43538 }
43539 }
43540
43541 if (capnum > 0 && capnum < match_caps) {
43542 DUK_ASSERT(is_regexp != 0); /* match_caps == 0 without regexps */
43543
43544 /* regexp res_obj is at offset 4 */
43545 duk_get_prop_index(thr, 4, (duk_uarridx_t) capnum);
43546 if (duk_is_string(thr, -1)) {
43547 duk_hstring *h_tmp_str;
43548
43549 h_tmp_str = duk_known_hstring(thr, -1);
43550
43551 DUK_BW_WRITE_ENSURE_HSTRING(thr, bw, h_tmp_str);
43552 } else {
43553 /* undefined -> skip (replaced with empty) */
43554 }
43555 duk_pop(thr);
43556 r += capadv;
43557 continue;
43558 } else {
43559 goto repl_write;
43560 }
43561#else /* DUK_USE_REGEXP_SUPPORT */
43562 goto repl_write; /* unconditionally */
43563#endif /* DUK_USE_REGEXP_SUPPORT */
43564 } /* default case */
43565 } /* switch (ch2) */
43566
43567 repl_write:
43568 /* ch1 = (r_increment << 8) + byte */
43569
43570 DUK_BW_WRITE_ENSURE_U8(thr, bw, (duk_uint8_t) (ch1 & 0xff));
43571 r += ch1 >> 8;
43572 } /* while repl */
43573 } /* if (is_repl_func) */
43574
43575 duk_pop(thr); /* pop regexp res_obj or match string */
43576
43577#if defined(DUK_USE_REGEXP_SUPPORT)
43578 if (!is_global) {
43579#else
43580 { /* unconditionally; is_global==0 */
43581#endif
43582 break;
43583 }
43584 }
43585
43586 /* trailer */
43587 tmp_sz = (duk_size_t) (DUK_HSTRING_GET_BYTELEN(h_input) - prev_match_end_boff);
43588 DUK_BW_WRITE_ENSURE_BYTES(thr, bw, DUK_HSTRING_GET_DATA(h_input) + prev_match_end_boff, tmp_sz);
43589
43590 DUK_ASSERT_TOP(thr, 4);
43591 DUK_BW_COMPACT(thr, bw);
43592 (void) duk_buffer_to_string(thr, -1); /* Safe if inputs are safe. */
43593 return 1;
43594}
43595
43596/*
43597 * split()
43598 */
43599
43600/* XXX: very messy now, but works; clean up, remove unused variables (nomimally
43601 * used so compiler doesn't complain).
43602 */
43603
43605 duk_hstring *h_input;
43606 duk_hstring *h_sep;
43607 duk_uint32_t limit;
43608 duk_uint32_t arr_idx;
43609#if defined(DUK_USE_REGEXP_SUPPORT)
43610 duk_bool_t is_regexp;
43611#endif
43612 duk_bool_t matched; /* set to 1 if any match exists (needed for empty input special case) */
43613 duk_uint32_t prev_match_end_coff, prev_match_end_boff;
43614 duk_uint32_t match_start_boff, match_start_coff;
43615 duk_uint32_t match_end_boff, match_end_coff;
43616
43617 h_input = duk_push_this_coercible_to_string(thr);
43618 DUK_ASSERT(h_input != NULL);
43619
43620 duk_push_array(thr);
43621
43622 if (duk_is_undefined(thr, 1)) {
43623 limit = 0xffffffffUL;
43624 } else {
43625 limit = duk_to_uint32(thr, 1);
43626 }
43627
43628 if (limit == 0) {
43629 return 1;
43630 }
43631
43632 /* If the separator is a RegExp, make a "clone" of it. The specification
43633 * algorithm calls [[Match]] directly for specific indices; we emulate this
43634 * by tweaking lastIndex and using a "force global" variant of duk_regexp_match()
43635 * which will use global-style matching even when the RegExp itself is non-global.
43636 */
43637
43638 if (duk_is_undefined(thr, 0)) {
43639 /* The spec algorithm first does "R = ToString(separator)" before checking
43640 * whether separator is undefined. Since this is side effect free, we can
43641 * skip the ToString() here.
43642 */
43643 duk_dup_2(thr);
43644 duk_put_prop_index(thr, 3, 0);
43645 return 1;
43646 } else if (duk_get_hobject_with_class(thr, 0, DUK_HOBJECT_CLASS_REGEXP) != NULL) {
43647#if defined(DUK_USE_REGEXP_SUPPORT)
43649 duk_dup_0(thr);
43650 duk_new(thr, 1); /* [ ... RegExp val ] -> [ ... res ] */
43651 duk_replace(thr, 0);
43652 /* lastIndex is initialized to zero by new RegExp() */
43653 is_regexp = 1;
43654#else
43656#endif
43657 } else {
43658 duk_to_string(thr, 0);
43659#if defined(DUK_USE_REGEXP_SUPPORT)
43660 is_regexp = 0;
43661#endif
43662 }
43663
43664 /* stack[0] = separator (string or regexp)
43665 * stack[1] = limit
43666 * stack[2] = input string
43667 * stack[3] = result array
43668 */
43669
43670 prev_match_end_boff = 0;
43671 prev_match_end_coff = 0;
43672 arr_idx = 0;
43673 matched = 0;
43674
43675 for (;;) {
43676 /*
43677 * The specification uses RegExp [[Match]] to attempt match at specific
43678 * offsets. We don't have such a primitive, so we use an actual RegExp
43679 * and tweak lastIndex. Since the RegExp may be non-global, we use a
43680 * special variant which forces global-like behavior for matching.
43681 */
43682
43683 DUK_ASSERT_TOP(thr, 4);
43684
43685#if defined(DUK_USE_REGEXP_SUPPORT)
43686 if (is_regexp) {
43687 duk_dup_0(thr);
43688 duk_dup_2(thr);
43689 duk_regexp_match_force_global(thr); /* [ ... regexp input ] -> [ res_obj ] */
43690 if (!duk_is_object(thr, -1)) {
43691 duk_pop(thr);
43692 break;
43693 }
43694 matched = 1;
43695
43697 DUK_ASSERT(duk_is_number(thr, -1));
43698 match_start_coff = duk_get_uint(thr, -1);
43699 match_start_boff = (duk_uint32_t) duk_heap_strcache_offset_char2byte(thr, h_input, match_start_coff);
43700 duk_pop(thr);
43701
43702 if (match_start_coff == DUK_HSTRING_GET_CHARLEN(h_input)) {
43703 /* don't allow an empty match at the end of the string */
43704 duk_pop(thr);
43705 break;
43706 }
43707
43709 DUK_ASSERT(duk_is_number(thr, -1));
43710 match_end_coff = duk_get_uint(thr, -1);
43711 match_end_boff = (duk_uint32_t) duk_heap_strcache_offset_char2byte(thr, h_input, match_end_coff);
43712 duk_pop(thr);
43713
43714 /* empty match -> bump and continue */
43715 if (prev_match_end_boff == match_end_boff) {
43716 duk_push_uint(thr, (duk_uint_t) (match_end_coff + 1));
43718 duk_pop(thr);
43719 continue;
43720 }
43721 } else {
43722#else /* DUK_USE_REGEXP_SUPPORT */
43723 { /* unconditionally */
43724#endif /* DUK_USE_REGEXP_SUPPORT */
43725 const duk_uint8_t *p_start, *p_end, *p; /* input string scan */
43726 const duk_uint8_t *q_start; /* match string */
43727 duk_size_t q_blen, q_clen;
43728
43729 p_start = DUK_HSTRING_GET_DATA(h_input);
43730 p_end = p_start + DUK_HSTRING_GET_BYTELEN(h_input);
43731 p = p_start + prev_match_end_boff;
43732
43733 h_sep = duk_known_hstring(thr, 0); /* symbol already rejected above */
43734 q_start = DUK_HSTRING_GET_DATA(h_sep);
43735 q_blen = (duk_size_t) DUK_HSTRING_GET_BYTELEN(h_sep);
43736 q_clen = (duk_size_t) DUK_HSTRING_GET_CHARLEN(h_sep);
43737
43738 p_end -= q_blen; /* ensure full memcmp() fits in while */
43739
43740 match_start_coff = prev_match_end_coff;
43741
43742 if (q_blen == 0) {
43743 /* Handle empty separator case: it will always match, and always
43744 * triggers the check in step 13.c.iii initially. Note that we
43745 * must skip to either end of string or start of first codepoint,
43746 * skipping over any continuation bytes!
43747 *
43748 * Don't allow an empty string to match at the end of the input.
43749 */
43750
43751 matched = 1; /* empty separator can always match */
43752
43753 match_start_coff++;
43754 p++;
43755 while (p < p_end) {
43756 if ((p[0] & 0xc0) != 0x80) {
43757 goto found;
43758 }
43759 p++;
43760 }
43761 goto not_found;
43762 }
43763
43764 DUK_ASSERT(q_blen > 0 && q_clen > 0);
43765 while (p <= p_end) {
43766 DUK_ASSERT(p + q_blen <= DUK_HSTRING_GET_DATA(h_input) + DUK_HSTRING_GET_BYTELEN(h_input));
43767 DUK_ASSERT(q_blen > 0); /* no issues with empty memcmp() */
43768 if (duk_memcmp((const void *) p, (const void *) q_start, (size_t) q_blen) == 0) {
43769 /* never an empty match, so step 13.c.iii can't be triggered */
43770 goto found;
43771 }
43772
43773 /* track utf-8 non-continuation bytes */
43774 if ((p[0] & 0xc0) != 0x80) {
43775 match_start_coff++;
43776 }
43777 p++;
43778 }
43779
43780 not_found:
43781 /* not found */
43782 break;
43783
43784 found:
43785 matched = 1;
43786 match_start_boff = (duk_uint32_t) (p - p_start);
43787 match_end_coff = (duk_uint32_t) (match_start_coff + q_clen); /* constrained by string length */
43788 match_end_boff = (duk_uint32_t) (match_start_boff + q_blen); /* ditto */
43789
43790 /* empty match (may happen with empty separator) -> bump and continue */
43791 if (prev_match_end_boff == match_end_boff) {
43792 prev_match_end_boff++;
43793 prev_match_end_coff++;
43794 continue;
43795 }
43796 } /* if (is_regexp) */
43797
43798 /* stack[0] = separator (string or regexp)
43799 * stack[1] = limit
43800 * stack[2] = input string
43801 * stack[3] = result array
43802 * stack[4] = regexp res_obj (if is_regexp)
43803 */
43804
43805 DUK_DDD(DUK_DDDPRINT("split; match_start b=%ld,c=%ld, match_end b=%ld,c=%ld, prev_end b=%ld,c=%ld",
43806 (long) match_start_boff,
43807 (long) match_start_coff,
43808 (long) match_end_boff,
43809 (long) match_end_coff,
43810 (long) prev_match_end_boff,
43811 (long) prev_match_end_coff));
43812
43813 duk_push_lstring(thr,
43814 (const char *) (DUK_HSTRING_GET_DATA(h_input) + prev_match_end_boff),
43815 (duk_size_t) (match_start_boff - prev_match_end_boff));
43816 duk_put_prop_index(thr, 3, arr_idx);
43817 arr_idx++;
43818 if (arr_idx >= limit) {
43819 goto hit_limit;
43820 }
43821
43822#if defined(DUK_USE_REGEXP_SUPPORT)
43823 if (is_regexp) {
43824 duk_size_t i, len;
43825
43826 len = duk_get_length(thr, 4);
43827 for (i = 1; i < len; i++) {
43828 DUK_ASSERT(i <= DUK_UARRIDX_MAX); /* cannot have >4G captures */
43829 duk_get_prop_index(thr, 4, (duk_uarridx_t) i);
43830 duk_put_prop_index(thr, 3, arr_idx);
43831 arr_idx++;
43832 if (arr_idx >= limit) {
43833 goto hit_limit;
43834 }
43835 }
43836
43837 duk_pop(thr);
43838 /* lastIndex already set up for next match */
43839 } else {
43840#else /* DUK_USE_REGEXP_SUPPORT */
43841 {
43842 /* unconditionally */
43843#endif /* DUK_USE_REGEXP_SUPPORT */
43844 /* no action */
43845 }
43846
43847 prev_match_end_boff = match_end_boff;
43848 prev_match_end_coff = match_end_coff;
43849 continue;
43850 } /* for */
43851
43852 /* Combined step 11 (empty string special case) and 14-15. */
43853
43854 DUK_DDD(DUK_DDDPRINT("split trailer; prev_end b=%ld,c=%ld", (long) prev_match_end_boff, (long) prev_match_end_coff));
43855
43856 if (DUK_HSTRING_GET_BYTELEN(h_input) > 0 || !matched) {
43857 /* Add trailer if:
43858 * a) non-empty input
43859 * b) empty input and no (zero size) match found (step 11)
43860 */
43861
43862 duk_push_lstring(thr,
43863 (const char *) DUK_HSTRING_GET_DATA(h_input) + prev_match_end_boff,
43864 (duk_size_t) (DUK_HSTRING_GET_BYTELEN(h_input) - prev_match_end_boff));
43865 duk_put_prop_index(thr, 3, arr_idx);
43866 /* No arr_idx update or limit check */
43867 }
43868
43869 return 1;
43870
43871hit_limit:
43872#if defined(DUK_USE_REGEXP_SUPPORT)
43873 if (is_regexp) {
43875 }
43876#endif
43877
43878 return 1;
43879}
43880
43881/*
43882 * Various
43883 */
43884
43885#if defined(DUK_USE_REGEXP_SUPPORT)
43887 duk_hobject *h;
43888
43889 /* Shared helper for match() steps 3-4, search() steps 3-4. */
43890
43891 DUK_ASSERT(idx >= 0);
43892
43893 if (force_new) {
43894 goto do_new;
43895 }
43896
43898 if (!h) {
43899 goto do_new;
43901 return;
43902
43903do_new:
43905 duk_dup(thr, idx);
43906 duk_new(thr, 1); /* [ ... RegExp val ] -> [ ... res ] */
43907 duk_replace(thr, idx);
43908}
43909#endif /* DUK_USE_REGEXP_SUPPORT */
43910
43911#if defined(DUK_USE_REGEXP_SUPPORT)
43913 /* Easiest way to implement the search required by the specification
43914 * is to do a RegExp test() with lastIndex forced to zero. To avoid
43915 * side effects on the argument, "clone" the RegExp if a RegExp was
43916 * given as input.
43917 *
43918 * The global flag of the RegExp should be ignored; setting lastIndex
43919 * to zero (which happens when "cloning" the RegExp) should have an
43920 * equivalent effect.
43921 */
43922
43923 DUK_ASSERT_TOP(thr, 1);
43924 (void) duk_push_this_coercible_to_string(thr); /* at index 1 */
43925 duk__to_regexp_helper(thr, 0 /*index*/, 1 /*force_new*/);
43926
43927 /* stack[0] = regexp
43928 * stack[1] = string
43929 */
43930
43931 /* Avoid using RegExp.prototype methods, as they're writable and
43932 * configurable and may have been changed.
43933 */
43934
43935 duk_dup_0(thr);
43936 duk_dup_1(thr); /* [ ... re_obj input ] */
43937 duk_regexp_match(thr); /* -> [ ... res_obj ] */
43938
43939 if (!duk_is_object(thr, -1)) {
43940 duk_push_int(thr, -1);
43941 return 1;
43942 }
43943
43945 DUK_ASSERT(duk_is_number(thr, -1));
43946 return 1;
43947}
43948#endif /* DUK_USE_REGEXP_SUPPORT */
43949
43950#if defined(DUK_USE_REGEXP_SUPPORT)
43952 duk_bool_t global;
43953 duk_int_t prev_last_index;
43954 duk_int_t this_index;
43955 duk_int_t arr_idx;
43956
43957 DUK_ASSERT_TOP(thr, 1);
43959 duk__to_regexp_helper(thr, 0 /*index*/, 0 /*force_new*/);
43960 global = duk_get_prop_stridx_boolean(thr, 0, DUK_STRIDX_GLOBAL, NULL);
43961 DUK_ASSERT_TOP(thr, 2);
43962
43963 /* stack[0] = regexp
43964 * stack[1] = string
43965 */
43966
43967 if (!global) {
43968 duk_regexp_match(thr); /* -> [ res_obj ] */
43969 return 1; /* return 'res_obj' */
43970 }
43971
43972 /* Global case is more complex. */
43973
43974 /* [ regexp string ] */
43975
43976 duk_push_int(thr, 0);
43978 duk_push_array(thr);
43979
43980 /* [ regexp string res_arr ] */
43981
43982 prev_last_index = 0;
43983 arr_idx = 0;
43984
43985 for (;;) {
43986 DUK_ASSERT_TOP(thr, 3);
43987
43988 duk_dup_0(thr);
43989 duk_dup_1(thr);
43990 duk_regexp_match(thr); /* -> [ ... regexp string ] -> [ ... res_obj ] */
43991
43992 if (!duk_is_object(thr, -1)) {
43993 duk_pop(thr);
43994 break;
43995 }
43996
43998 DUK_ASSERT(duk_is_number(thr, -1));
43999 this_index = duk_get_int(thr, -1);
44000 duk_pop(thr);
44001
44002 if (this_index == prev_last_index) {
44003 this_index++;
44004 duk_push_int(thr, this_index);
44006 }
44007 prev_last_index = this_index;
44008
44009 duk_get_prop_index(thr, -1, 0); /* match string */
44010 duk_put_prop_index(thr, 2, (duk_uarridx_t) arr_idx);
44011 arr_idx++;
44012 duk_pop(thr); /* res_obj */
44013 }
44014
44015 if (arr_idx == 0) {
44016 duk_push_null(thr);
44017 }
44018
44019 return 1; /* return 'res_arr' or 'null' */
44020}
44021#endif /* DUK_USE_REGEXP_SUPPORT */
44022
44024 /* duk_concat() coerces arguments with ToString() in correct order */
44026 duk_insert(thr, 0); /* this is relatively expensive */
44027 duk_concat(thr, duk_get_top(thr));
44028 return 1;
44029}
44030
44032 DUK_ASSERT_TOP(thr, 0);
44034 duk_trim(thr, 0);
44035 DUK_ASSERT_TOP(thr, 1);
44036 return 1;
44037}
44038
44039#if defined(DUK_USE_ES6)
44041 duk_hstring *h_input;
44042 duk_size_t input_blen;
44043 duk_size_t result_len;
44044 duk_int_t count_signed;
44046 const duk_uint8_t *src;
44047 duk_uint8_t *buf;
44048 duk_uint8_t *p;
44049 duk_double_t d;
44050#if !defined(DUK_USE_PREFER_SIZE)
44051 duk_size_t copy_size;
44052 duk_uint8_t *p_end;
44053#endif
44054
44055 DUK_ASSERT_TOP(thr, 1);
44056 h_input = duk_push_this_coercible_to_string(thr);
44057 DUK_ASSERT(h_input != NULL);
44058 input_blen = DUK_HSTRING_GET_BYTELEN(h_input);
44059
44060 /* Count is ToNumber() coerced; +Infinity must be always rejected
44061 * (even if input string is zero length), as well as negative values
44062 * and -Infinity. -Infinity doesn't require an explicit check
44063 * because duk_get_int() clamps it to DUK_INT_MIN which gets rejected
44064 * as a negative value (regardless of input string length).
44065 */
44066 d = duk_to_number(thr, 0);
44067 if (duk_double_is_posinf(d)) {
44068 goto fail_range;
44069 }
44070 count_signed = duk_get_int(thr, 0);
44071 if (count_signed < 0) {
44072 goto fail_range;
44073 }
44074 count = (duk_uint_t) count_signed;
44075
44076 /* Overflow check for result length. */
44077 result_len = count * input_blen;
44078 if (count != 0 && result_len / count != input_blen) {
44079 goto fail_range;
44080 }
44081
44082 /* Temporary fixed buffer, later converted to string. */
44083 buf = (duk_uint8_t *) duk_push_fixed_buffer_nozero(thr, result_len);
44084 DUK_ASSERT(buf != NULL);
44085 src = (const duk_uint8_t *) DUK_HSTRING_GET_DATA(h_input);
44086 DUK_ASSERT(src != NULL);
44087
44088#if defined(DUK_USE_PREFER_SIZE)
44089 p = buf;
44090 while (count-- > 0) {
44091 duk_memcpy((void *) p, (const void *) src, input_blen); /* copy size may be zero, but pointers are valid */
44092 p += input_blen;
44093 }
44094#else /* DUK_USE_PREFER_SIZE */
44095 /* Take advantage of already copied pieces to speed up the process
44096 * especially for small repeated strings.
44097 */
44098 p = buf;
44099 p_end = p + result_len;
44100 copy_size = input_blen;
44101 for (;;) {
44102 duk_size_t remain = (duk_size_t) (p_end - p);
44103 DUK_DDD(DUK_DDDPRINT("remain=%ld, copy_size=%ld, input_blen=%ld, result_len=%ld",
44104 (long) remain,
44105 (long) copy_size,
44106 (long) input_blen,
44107 (long) result_len));
44108 if (remain <= copy_size) {
44109 /* If result_len is zero, this case is taken and does
44110 * a zero size copy (with valid pointers).
44111 */
44112 duk_memcpy((void *) p, (const void *) src, remain);
44113 break;
44114 } else {
44115 duk_memcpy((void *) p, (const void *) src, copy_size);
44116 p += copy_size;
44117 }
44118
44119 src = (const duk_uint8_t *) buf; /* Use buf as source for larger copies. */
44120 copy_size = (duk_size_t) (p - buf);
44121 }
44122#endif /* DUK_USE_PREFER_SIZE */
44123
44124 /* XXX: It would be useful to be able to create a duk_hstring with
44125 * a certain byte size whose data area wasn't initialized and which
44126 * wasn't in the string table yet. This would allow a string to be
44127 * constructed directly without a buffer temporary and when it was
44128 * finished, it could be injected into the string table. Currently
44129 * this isn't possible because duk_hstrings are only tracked by the
44130 * intern table (they are not in heap_allocated).
44131 */
44132
44133 duk_buffer_to_string(thr, -1); /* Safe if input is safe. */
44134 return 1;
44135
44136fail_range:
44138}
44139#endif /* DUK_USE_ES6 */
44140
44142 duk_hstring *h1;
44143 duk_hstring *h2;
44144 duk_size_t h1_len, h2_len, prefix_len;
44145 duk_small_int_t ret = 0;
44146 duk_small_int_t rc;
44147
44148 /* The current implementation of localeCompare() is simply a codepoint
44149 * by codepoint comparison, implemented with a simple string compare
44150 * because UTF-8 should preserve codepoint ordering (assuming valid
44151 * shortest UTF-8 encoding).
44152 *
44153 * The specification requires that the return value must be related
44154 * to the sort order: e.g. negative means that 'this' comes before
44155 * 'that' in sort order. We assume an ascending sort order.
44156 */
44157
44158 /* XXX: could share code with duk_js_ops.c, duk_js_compare_helper */
44159
44161 DUK_ASSERT(h1 != NULL);
44162
44163 h2 = duk_to_hstring(thr, 0);
44164 DUK_ASSERT(h2 != NULL);
44165
44166 h1_len = (duk_size_t) DUK_HSTRING_GET_BYTELEN(h1);
44167 h2_len = (duk_size_t) DUK_HSTRING_GET_BYTELEN(h2);
44168 prefix_len = (h1_len <= h2_len ? h1_len : h2_len);
44169
44170 rc = (duk_small_int_t) duk_memcmp((const void *) DUK_HSTRING_GET_DATA(h1),
44171 (const void *) DUK_HSTRING_GET_DATA(h2),
44172 (size_t) prefix_len);
44173
44174 if (rc < 0) {
44175 ret = -1;
44176 goto done;
44177 } else if (rc > 0) {
44178 ret = 1;
44179 goto done;
44180 }
44181
44182 /* prefix matches, lengths matter now */
44183 if (h1_len > h2_len) {
44184 ret = 1;
44185 goto done;
44186 } else if (h1_len == h2_len) {
44187 DUK_ASSERT(ret == 0);
44188 goto done;
44189 }
44190 ret = -1;
44191 goto done;
44192
44193done:
44194 duk_push_int(thr, (duk_int_t) ret);
44195 return 1;
44196}
44197
44198#if defined(DUK_USE_ES6)
44200 duk_int_t magic;
44201 duk_hstring *h_target;
44202 duk_size_t blen_target;
44203 duk_hstring *h_search;
44204 duk_size_t blen_search;
44205 duk_int_t off;
44206 duk_bool_t result = 0;
44207 duk_size_t blen_left;
44208
44209 /* Because string byte lengths are in [0,DUK_INT_MAX] it's safe to
44210 * subtract two string lengths without overflow.
44211 */
44213
44214 h_target = duk_push_this_coercible_to_string(thr);
44215 DUK_ASSERT(h_target != NULL);
44216
44217 h_search = duk__str_tostring_notregexp(thr, 0);
44218 DUK_ASSERT(h_search != NULL);
44219
44220 magic = duk_get_current_magic(thr);
44221
44222 /* Careful to avoid pointer overflows in the matching logic. */
44223
44224 blen_target = DUK_HSTRING_GET_BYTELEN(h_target);
44225 blen_search = DUK_HSTRING_GET_BYTELEN(h_search);
44226
44227#if 0
44228 /* If search string is longer than the target string, we can
44229 * never match. Could check explicitly, but should be handled
44230 * correctly below.
44231 */
44232 if (blen_search > blen_target) {
44233 goto finish;
44234 }
44235#endif
44236
44237 off = 0;
44238 if (duk_is_undefined(thr, 1)) {
44239 if (magic) {
44240 off = (duk_int_t) blen_target - (duk_int_t) blen_search;
44241 } else {
44242 DUK_ASSERT(off == 0);
44243 }
44244 } else {
44245 duk_int_t len;
44246 duk_int_t pos;
44247
44249 len = (duk_int_t) DUK_HSTRING_GET_CHARLEN(h_target);
44250 pos = duk_to_int_clamped(thr, 1, 0, len);
44251 DUK_ASSERT(pos >= 0 && pos <= len);
44252
44254 if (magic) {
44255 off -= (duk_int_t) blen_search;
44256 }
44257 }
44258 if (off < 0 || off > (duk_int_t) blen_target) {
44259 goto finish;
44260 }
44261
44262 /* The main comparison can be done using a memcmp() rather than
44263 * doing codepoint comparisons: for CESU-8 strings there is a
44264 * canonical representation for every codepoint. But we do need
44265 * to deal with the char/byte offset translation to find the
44266 * comparison range.
44267 */
44268
44269 DUK_ASSERT(off >= 0);
44270 DUK_ASSERT((duk_size_t) off <= blen_target);
44271 blen_left = blen_target - (duk_size_t) off;
44272 if (blen_left >= blen_search) {
44273 const duk_uint8_t *p_cmp_start = (const duk_uint8_t *) DUK_HSTRING_GET_DATA(h_target) + off;
44274 const duk_uint8_t *p_search = (const duk_uint8_t *) DUK_HSTRING_GET_DATA(h_search);
44275 if (duk_memcmp_unsafe((const void *) p_cmp_start, (const void *) p_search, (size_t) blen_search) == 0) {
44276 result = 1;
44277 }
44278 }
44279
44280finish:
44282 return 1;
44283}
44284#endif /* DUK_USE_ES6 */
44285
44286#if defined(DUK_USE_ES6)
44288 duk_hstring *h;
44289 duk_hstring *h_search;
44290 duk_int_t len;
44291 duk_int_t pos;
44292
44294 DUK_ASSERT(h != NULL);
44295
44296 h_search = duk__str_tostring_notregexp(thr, 0);
44297 DUK_ASSERT(h_search != NULL);
44298
44300 pos = duk_to_int_clamped(thr, 1, 0, len);
44301 DUK_ASSERT(pos >= 0 && pos <= len);
44302
44303 pos = duk__str_search_shared(thr, h, h_search, pos, 0 /*backwards*/);
44304 duk_push_boolean(thr, pos >= 0);
44305 return 1;
44306}
44307#endif /* DUK_USE_ES6 */
44308#endif /* DUK_USE_STRING_BUILTIN */
44310 * Symbol built-in
44311 */
44312
44313/* #include duk_internal.h -> already included */
44314
44315#if defined(DUK_USE_SYMBOL_BUILTIN)
44316
44317/*
44318 * Constructor
44319 */
44320
44322 const duk_uint8_t *desc;
44323 duk_size_t len;
44324 duk_uint8_t *buf;
44325 duk_uint8_t *p;
44326 duk_int_t magic;
44327
44328 magic = duk_get_current_magic(thr);
44329 if (duk_is_undefined(thr, 0) && (magic == 0)) {
44330 /* Symbol() accepts undefined and empty string, but they are
44331 * treated differently.
44332 */
44333 desc = NULL;
44334 len = 0;
44335 } else {
44336 /* Symbol.for() coerces undefined to 'undefined' */
44337 desc = (const duk_uint8_t *) duk_to_lstring(thr, 0, &len);
44338 }
44339
44340 /* Maximum symbol data length:
44341 * +1 initial byte (0x80 or 0x81)
44342 * +len description
44343 * +1 0xff after description, before unique suffix
44344 * +17 autogenerated unique suffix: 'ffffffff-ffffffff' is longest
44345 * +1 0xff after unique suffix for symbols with undefined description
44346 */
44347 buf = (duk_uint8_t *) duk_push_fixed_buffer(thr, 1 + len + 1 + 17 + 1);
44348 DUK_ASSERT(buf != NULL);
44349 p = buf + 1;
44350 DUK_ASSERT(desc != NULL || len == 0); /* may be NULL if len is 0 */
44351 duk_memcpy_unsafe((void *) p, (const void *) desc, len);
44352 p += len;
44353 if (magic == 0) {
44354 /* Symbol(): create unique symbol. Use two 32-bit values
44355 * to avoid dependency on 64-bit types and 64-bit integer
44356 * formatting (at least for now).
44357 */
44358 if (++thr->heap->sym_counter[0] == 0) {
44359 thr->heap->sym_counter[1]++;
44360 }
44361 p += DUK_SPRINTF((char *) p,
44362 "\xFF"
44363 "%lx-%lx",
44364 (unsigned long) thr->heap->sym_counter[1],
44365 (unsigned long) thr->heap->sym_counter[0]);
44366 if (desc == NULL) {
44367 /* Special case for 'undefined' description, trailing
44368 * 0xff distinguishes from empty string description,
44369 * but needs minimal special case handling elsewhere.
44370 */
44371 *p++ = 0xff;
44373 buf[0] = 0x81;
44374 } else {
44375 /* Symbol.for(): create a global symbol */
44376 buf[0] = 0x80;
44377 }
44378
44379 duk_push_lstring(thr, (const char *) buf, (duk_size_t) (p - buf));
44380 DUK_DDD(DUK_DDDPRINT("created symbol: %!T", duk_get_tval(thr, -1)));
44381 return 1;
44382}
44383
44385 duk_tval *tv;
44386 duk_hobject *h_obj;
44387 duk_hstring *h_str;
44388
44389 DUK_ASSERT(tv_arg != NULL);
44390
44391 /* XXX: add internal helper: duk_auto_unbox_tval(thr, tv, mask); */
44392 /* XXX: add internal helper: duk_auto_unbox(thr, tv, idx); */
44393
44394 tv = tv_arg;
44395 if (DUK_TVAL_IS_OBJECT(tv)) {
44396 h_obj = DUK_TVAL_GET_OBJECT(tv);
44397 DUK_ASSERT(h_obj != NULL);
44400 if (tv == NULL) {
44401 return NULL;
44402 }
44403 } else {
44404 return NULL;
44405 }
44406 }
44407
44408 if (!DUK_TVAL_IS_STRING(tv)) {
44409 return NULL;
44411 h_str = DUK_TVAL_GET_STRING(tv);
44412 DUK_ASSERT(h_str != NULL);
44413
44414 /* Here symbol is more expected than not. */
44415 if (DUK_UNLIKELY(!DUK_HSTRING_HAS_SYMBOL(h_str))) {
44416 return NULL;
44417 }
44418
44419 return h_str;
44420}
44421
44423 duk_hstring *h_str;
44424
44426 if (h_str == NULL) {
44427 return DUK_RET_TYPE_ERROR;
44429
44430 if (duk_get_current_magic(thr) == 0) {
44431 /* .toString() */
44433 } else {
44434 /* .valueOf() */
44435 duk_push_hstring(thr, h_str);
44436 }
44437 return 1;
44438}
44439
44441 duk_hstring *h;
44442 const duk_uint8_t *p;
44443
44444 /* Argument must be a symbol but not checked here. The initial byte
44445 * check will catch non-symbol strings.
44446 */
44447 h = duk_require_hstring(thr, 0);
44448 DUK_ASSERT(h != NULL);
44449
44450 p = (const duk_uint8_t *) DUK_HSTRING_GET_DATA(h);
44451 DUK_ASSERT(p != NULL);
44452
44453 /* Even for zero length strings there's at least one NUL byte so
44454 * we can safely check the initial byte.
44455 */
44456 if (p[0] == 0x80) {
44457 /* Global symbol, return its key (bytes just after the initial byte). */
44458 duk_push_lstring(thr, (const char *) (p + 1), (duk_size_t) (DUK_HSTRING_GET_BYTELEN(h) - 1));
44459 return 1;
44460 } else if (p[0] == 0x81 || p[0] == 0x82 || p[0] == 0xff) {
44461 /* Local symbol or hidden symbol, return undefined. */
44462 return 0;
44463 }
44464
44465 /* Covers normal strings and unknown initial bytes. */
44466 return DUK_RET_TYPE_ERROR;
44467}
44468
44470 duk_hstring *h_str;
44471
44473 if (h_str == NULL) {
44474 return DUK_RET_TYPE_ERROR;
44475 }
44476 duk_push_hstring(thr, h_str);
44477 return 1;
44478}
44479
44480#endif /* DUK_USE_SYMBOL_BUILTIN */
44481/*
44482 * Thread builtins
44483 */
44484
44485/* #include duk_internal.h -> already included */
44486
44487/*
44488 * Constructor
44489 */
44490
44491#if defined(DUK_USE_COROUTINE_SUPPORT)
44493 duk_hthread *new_thr;
44494 duk_hobject *func;
44495
44496 /* Check that the argument is callable; this is not 100% because we
44497 * don't allow native functions to be a thread's initial function.
44498 * Resume will reject such functions in any case.
44499 */
44500 /* XXX: need a duk_require_func_promote_lfunc() */
44501 func = duk_require_hobject_promote_lfunc(thr, 0);
44502 DUK_ASSERT(func != NULL);
44503 duk_require_callable(thr, 0);
44504
44505 duk_push_thread(thr);
44506 new_thr = (duk_hthread *) duk_known_hobject(thr, -1);
44508
44509 /* push initial function call to new thread stack; this is
44510 * picked up by resume().
44511 */
44512 duk_push_hobject(new_thr, func);
44513
44514 return 1; /* return thread */
44515}
44516#endif
44517
44518/*
44519 * Resume a thread.
44520 *
44521 * The thread must be in resumable state, either (a) new thread which hasn't
44522 * yet started, or (b) a thread which has previously yielded. This method
44523 * must be called from an ECMAScript function.
44524 *
44525 * Args:
44526 * - thread
44527 * - value
44528 * - isError (defaults to false)
44529 *
44530 * Note: yield and resume handling is currently asymmetric.
44531 */
44532
44533#if defined(DUK_USE_COROUTINE_SUPPORT)
44535 duk_hthread *thr = (duk_hthread *) ctx;
44536 duk_hthread *thr_resume;
44537 duk_hobject *caller_func;
44538 duk_small_uint_t is_error;
44539
44540 DUK_DDD(DUK_DDDPRINT("Duktape.Thread.resume(): thread=%!T, value=%!T, is_error=%!T",
44541 (duk_tval *) duk_get_tval(thr, 0),
44542 (duk_tval *) duk_get_tval(thr, 1),
44543 (duk_tval *) duk_get_tval(thr, 2)));
44544
44546 DUK_ASSERT(thr->heap->curr_thread == thr);
44547
44548 thr_resume = duk_require_hthread(thr, 0);
44549 DUK_ASSERT(duk_get_top(thr) == 3);
44550 is_error = (duk_small_uint_t) duk_to_boolean_top_pop(thr);
44551 DUK_ASSERT(duk_get_top(thr) == 2);
44552
44553 /* [ thread value ] */
44554
44555 /*
44556 * Thread state and calling context checks
44557 */
44558
44559 if (thr->callstack_top < 2) {
44561 "resume state invalid: callstack should contain at least 2 entries (caller and Duktape.Thread.resume)"));
44562 goto state_error;
44563 }
44564 DUK_ASSERT(thr->callstack_curr != NULL);
44565 DUK_ASSERT(thr->callstack_curr->parent != NULL);
44566 DUK_ASSERT(DUK_ACT_GET_FUNC(thr->callstack_curr) != NULL); /* us */
44568 DUK_ASSERT(DUK_ACT_GET_FUNC(thr->callstack_curr->parent) != NULL); /* caller */
44569
44570 caller_func = DUK_ACT_GET_FUNC(thr->callstack_curr->parent);
44571 if (!DUK_HOBJECT_IS_COMPFUNC(caller_func)) {
44572 DUK_DD(DUK_DDPRINT("resume state invalid: caller must be ECMAScript code"));
44573 goto state_error;
44574 }
44575
44576 /* Note: there is no requirement that: 'thr->callstack_preventcount == 1'
44577 * like for yield.
44578 */
44579
44580 if (thr_resume->state != DUK_HTHREAD_STATE_INACTIVE && thr_resume->state != DUK_HTHREAD_STATE_YIELDED) {
44581 DUK_DD(DUK_DDPRINT("resume state invalid: target thread must be INACTIVE or YIELDED"));
44582 goto state_error;
44583 }
44584
44586
44587 /* Further state-dependent pre-checks */
44588
44589 if (thr_resume->state == DUK_HTHREAD_STATE_YIELDED) {
44590 /* no pre-checks now, assume a previous yield() has left things in
44591 * tip-top shape (longjmp handler will assert for these).
44592 */
44593 } else {
44594 duk_hobject *h_fun;
44595
44597
44598 /* The initial function must be an ECMAScript function (but
44599 * can be bound). We must make sure of that before we longjmp
44600 * because an error in the RESUME handler call processing will
44601 * not be handled very cleanly.
44602 */
44603 if ((thr_resume->callstack_top != 0) || (thr_resume->valstack_top - thr_resume->valstack != 1)) {
44604 goto state_error;
44605 }
44606
44607 duk_push_tval(thr, DUK_GET_TVAL_NEGIDX(thr_resume, -1));
44609 h_fun = duk_require_hobject(thr, -1); /* reject lightfuncs on purpose */
44610 if (!DUK_HOBJECT_IS_CALLABLE(h_fun) || !DUK_HOBJECT_IS_COMPFUNC(h_fun)) {
44611 goto state_error;
44612 }
44613 duk_pop(thr);
44614 }
44615
44616#if 0
44617 /* This check would prevent a heap destruction time finalizer from
44618 * launching a coroutine, which would ensure that during finalization
44619 * 'thr' would always equal heap_thread. Normal runtime finalizers
44620 * run with ms_running == 0, i.e. outside mark-and-sweep. See GH-2030.
44621 */
44622 if (thr->heap->ms_running) {
44623 DUK_D(DUK_DPRINT("refuse Duktape.Thread.resume() when ms_running != 0"));
44624 goto state_error;
44625 }
44626#endif
44627
44628 /*
44629 * The error object has been augmented with a traceback and other
44630 * info from its creation point -- usually another thread. The
44631 * error handler is called here right before throwing, but it also
44632 * runs in the resumer's thread. It might be nice to get a traceback
44633 * from the resumee but this is not the case now.
44634 */
44635
44636#if defined(DUK_USE_AUGMENT_ERROR_THROW)
44637 if (is_error) {
44638 DUK_ASSERT_TOP(thr, 2); /* value (error) is at stack top */
44639 duk_err_augment_error_throw(thr); /* in resumer's context */
44640 }
44641#endif
44642
44643#if defined(DUK_USE_DEBUG)
44644 if (is_error) {
44645 DUK_DDD(DUK_DDDPRINT("RESUME ERROR: thread=%!T, value=%!T",
44646 (duk_tval *) duk_get_tval(thr, 0),
44647 (duk_tval *) duk_get_tval(thr, 1)));
44648 } else if (thr_resume->state == DUK_HTHREAD_STATE_YIELDED) {
44649 DUK_DDD(DUK_DDDPRINT("RESUME NORMAL: thread=%!T, value=%!T",
44650 (duk_tval *) duk_get_tval(thr, 0),
44651 (duk_tval *) duk_get_tval(thr, 1)));
44652 } else {
44653 DUK_DDD(DUK_DDDPRINT("RESUME INITIAL: thread=%!T, value=%!T",
44654 (duk_tval *) duk_get_tval(thr, 0),
44655 (duk_tval *) duk_get_tval(thr, 1)));
44656 }
44657#endif
44658
44660
44661 /* lj value2: thread */
44663 DUK_TVAL_SET_TVAL_UPDREF(thr, &thr->heap->lj.value2, &thr->valstack_bottom[0]); /* side effects */
44664
44665 /* lj value1: value */
44666 DUK_ASSERT(thr->valstack_bottom + 1 < thr->valstack_top);
44667 DUK_TVAL_SET_TVAL_UPDREF(thr, &thr->heap->lj.value1, &thr->valstack_bottom[1]); /* side effects */
44669
44670 thr->heap->lj.iserror = is_error;
44671
44672 DUK_ASSERT(thr->heap->lj.jmpbuf_ptr != NULL); /* call is from executor, so we know we have a jmpbuf */
44673 duk_err_longjmp(thr); /* execution resumes in bytecode executor */
44675 /* Never here, fall through to error (from compiler point of view). */
44676
44677state_error:
44679}
44680#endif
44681
44682/*
44683 * Yield the current thread.
44684 *
44685 * The thread must be in yieldable state: it must have a resumer, and there
44686 * must not be any yield-preventing calls (native calls and constructor calls,
44687 * currently) in the thread's call stack (otherwise a resume would not be
44688 * possible later). This method must be called from an ECMAScript function.
44689 *
44690 * Args:
44691 * - value
44692 * - isError (defaults to false)
44693 *
44694 * Note: yield and resume handling is currently asymmetric.
44695 */
44696
44697#if defined(DUK_USE_COROUTINE_SUPPORT)
44699 duk_hobject *caller_func;
44700 duk_small_uint_t is_error;
44701
44702 DUK_DDD(DUK_DDDPRINT("Duktape.Thread.yield(): value=%!T, is_error=%!T",
44703 (duk_tval *) duk_get_tval(thr, 0),
44704 (duk_tval *) duk_get_tval(thr, 1)));
44705
44707 DUK_ASSERT(thr->heap->curr_thread == thr);
44708
44709 DUK_ASSERT(duk_get_top(thr) == 2);
44710 is_error = (duk_small_uint_t) duk_to_boolean_top_pop(thr);
44711 DUK_ASSERT(duk_get_top(thr) == 1);
44712
44713 /* [ value ] */
44714
44715 /*
44716 * Thread state and calling context checks
44717 */
44718
44719 if (!thr->resumer) {
44720 DUK_DD(DUK_DDPRINT("yield state invalid: current thread must have a resumer"));
44721 goto state_error;
44722 }
44724
44725 if (thr->callstack_top < 2) {
44727 "yield state invalid: callstack should contain at least 2 entries (caller and Duktape.Thread.yield)"));
44728 goto state_error;
44729 }
44730 DUK_ASSERT(thr->callstack_curr != NULL);
44731 DUK_ASSERT(thr->callstack_curr->parent != NULL);
44732 DUK_ASSERT(DUK_ACT_GET_FUNC(thr->callstack_curr) != NULL); /* us */
44734 DUK_ASSERT(DUK_ACT_GET_FUNC(thr->callstack_curr->parent) != NULL); /* caller */
44735
44736 caller_func = DUK_ACT_GET_FUNC(thr->callstack_curr->parent);
44737 if (!DUK_HOBJECT_IS_COMPFUNC(caller_func)) {
44738 DUK_DD(DUK_DDPRINT("yield state invalid: caller must be ECMAScript code"));
44739 goto state_error;
44740 }
44741
44742 DUK_ASSERT(thr->callstack_preventcount >= 1); /* should never be zero, because we (Duktape.Thread.yield) are on the stack */
44743 if (thr->callstack_preventcount != 1) {
44744 /* Note: the only yield-preventing call is Duktape.Thread.yield(), hence check for 1, not 0 */
44745 DUK_DD(DUK_DDPRINT("yield state invalid: there must be no yield-preventing calls in current thread callstack "
44746 "(preventcount is %ld)",
44747 (long) thr->callstack_preventcount));
44748 goto state_error;
44749 }
44750
44751 /*
44752 * The error object has been augmented with a traceback and other
44753 * info from its creation point -- usually the current thread.
44754 * The error handler, however, is called right before throwing
44755 * and runs in the yielder's thread.
44756 */
44757
44758#if defined(DUK_USE_AUGMENT_ERROR_THROW)
44759 if (is_error) {
44760 DUK_ASSERT_TOP(thr, 1); /* value (error) is at stack top */
44761 duk_err_augment_error_throw(thr); /* in yielder's context */
44762 }
44763#endif
44764
44765#if defined(DUK_USE_DEBUG)
44766 if (is_error) {
44767 DUK_DDD(DUK_DDDPRINT("YIELD ERROR: value=%!T", (duk_tval *) duk_get_tval(thr, 0)));
44768 } else {
44769 DUK_DDD(DUK_DDDPRINT("YIELD NORMAL: value=%!T", (duk_tval *) duk_get_tval(thr, 0)));
44770 }
44771#endif
44772
44773 /*
44774 * Process yield
44775 *
44776 * After longjmp(), processing continues in bytecode executor longjmp
44777 * handler, which will e.g. update thr->resumer to NULL.
44778 */
44779
44780 thr->heap->lj.type = DUK_LJ_TYPE_YIELD;
44781
44782 /* lj value1: value */
44784 DUK_TVAL_SET_TVAL_UPDREF(thr, &thr->heap->lj.value1, &thr->valstack_bottom[0]); /* side effects */
44786
44787 thr->heap->lj.iserror = is_error;
44789 DUK_ASSERT(thr->heap->lj.jmpbuf_ptr != NULL); /* call is from executor, so we know we have a jmpbuf */
44790 duk_err_longjmp(thr); /* execution resumes in bytecode executor */
44792 /* Never here, fall through to error (from compiler point of view). */
44793
44794state_error:
44796}
44797#endif
44798
44799#if defined(DUK_USE_COROUTINE_SUPPORT)
44802 return 1;
44803}
44804#endif
44805/*
44806 * Type error thrower, E5 Section 13.2.3.
44807 */
44808
44809/* #include duk_internal.h -> already included */
44810
44813}
44814/*
44815 * Fixed buffer helper useful for debugging, requires no allocation
44816 * which is critical for debugging.
44817 */
44818
44819/* #include duk_internal.h -> already included */
44820
44821#if defined(DUK_USE_DEBUG)
44822
44823DUK_INTERNAL void duk_fb_put_bytes(duk_fixedbuffer *fb, const duk_uint8_t *buffer, duk_size_t length) {
44824 duk_size_t avail;
44825 duk_size_t copylen;
44826
44827 avail = (fb->offset >= fb->length ? (duk_size_t) 0 : (duk_size_t) (fb->length - fb->offset));
44828 if (length > avail) {
44829 copylen = avail;
44830 fb->truncated = 1;
44831 } else {
44832 copylen = length;
44833 }
44834 duk_memcpy_unsafe(fb->buffer + fb->offset, buffer, copylen);
44835 fb->offset += copylen;
44836}
44837
44838DUK_INTERNAL void duk_fb_put_byte(duk_fixedbuffer *fb, duk_uint8_t x) {
44839 duk_fb_put_bytes(fb, (const duk_uint8_t *) &x, 1);
44840}
44841
44842DUK_INTERNAL void duk_fb_put_cstring(duk_fixedbuffer *fb, const char *x) {
44843 duk_fb_put_bytes(fb, (const duk_uint8_t *) x, (duk_size_t) DUK_STRLEN(x));
44844}
44845
44846DUK_INTERNAL void duk_fb_sprintf(duk_fixedbuffer *fb, const char *fmt, ...) {
44847 duk_size_t avail;
44848 va_list ap;
44849
44850 va_start(ap, fmt);
44851 avail = (fb->offset >= fb->length ? (duk_size_t) 0 : (duk_size_t) (fb->length - fb->offset));
44852 if (avail > 0) {
44853 duk_int_t res = (duk_int_t) DUK_VSNPRINTF((char *) (fb->buffer + fb->offset), avail, fmt, ap);
44854 if (res < 0) {
44855 /* error */
44856 } else if ((duk_size_t) res >= avail) {
44857 /* (maybe) truncated */
44858 fb->offset += avail;
44859 if ((duk_size_t) res > avail) {
44860 /* actual chars dropped (not just NUL term) */
44861 fb->truncated = 1;
44862 }
44863 } else {
44864 /* normal */
44865 fb->offset += (duk_size_t) res;
44866 }
44867 }
44868 va_end(ap);
44869}
44870
44871DUK_INTERNAL void duk_fb_put_funcptr(duk_fixedbuffer *fb, duk_uint8_t *fptr, duk_size_t fptr_size) {
44872 char buf[64 + 1];
44873 duk_debug_format_funcptr(buf, sizeof(buf), fptr, fptr_size);
44874 buf[sizeof(buf) - 1] = (char) 0;
44875 duk_fb_put_cstring(fb, buf);
44876}
44877
44878DUK_INTERNAL duk_bool_t duk_fb_is_full(duk_fixedbuffer *fb) {
44879 return (fb->offset >= fb->length);
44880}
44881
44882#endif /* DUK_USE_DEBUG */
44883/*
44884 * Custom formatter for debug printing, allowing Duktape specific data
44885 * structures (such as tagged values and heap objects) to be printed with
44886 * a nice format string. Because debug printing should not affect execution
44887 * state, formatting here must be independent of execution (see implications
44888 * below) and must not allocate memory.
44889 *
44890 * Custom format tags begin with a '%!' to safely distinguish them from
44891 * standard format tags. The following conversions are supported:
44892 *
44893 * %!T tagged value (duk_tval *)
44894 * %!O heap object (duk_heaphdr *)
44895 * %!I decoded bytecode instruction
44896 * %!X bytecode instruction opcode name (arg is long)
44897 * %!C catcher (duk_catcher *)
44898 * %!A activation (duk_activation *)
44899 *
44900 * Everything is serialized in a JSON-like manner. The default depth is one
44901 * level, internal prototype is not followed, and internal properties are not
44902 * serialized. The following modifiers change this behavior:
44903 *
44904 * @ print pointers
44905 * # print binary representations (where applicable)
44906 * d deep traversal of own properties (not prototype)
44907 * p follow prototype chain (useless without 'd')
44908 * i include internal properties (other than prototype)
44909 * x hexdump buffers
44910 * h heavy formatting
44911 *
44912 * For instance, the following serializes objects recursively, but does not
44913 * follow the prototype chain nor print internal properties: "%!dO".
44914 *
44915 * Notes:
44916 *
44917 * * Standard snprintf return value semantics seem to vary. This
44918 * implementation returns the number of bytes it actually wrote
44919 * (excluding the null terminator). If retval == buffer size,
44920 * output was truncated (except for corner cases).
44921 *
44922 * * Output format is intentionally different from ECMAScript
44923 * formatting requirements, as formatting here serves debugging
44924 * of internals.
44925 *
44926 * * Depth checking (and updating) is done in each type printer
44927 * separately, to allow them to call each other freely.
44928 *
44929 * * Some pathological structures might take ages to print (e.g.
44930 * self recursion with 100 properties pointing to the object
44931 * itself). To guard against these, each printer also checks
44932 * whether the output buffer is full; if so, early exit.
44933 *
44934 * * Reference loops are detected using a loop stack.
44935 */
44936
44937/* #include duk_internal.h -> already included */
44938
44939#if defined(DUK_USE_DEBUG)
44940
44941/* #include stdio.h -> already included */
44942/* #include stdarg.h -> already included */
44943#include <string.h>
44944
44945/* list of conversion specifiers that terminate a format tag;
44946 * this is unfortunately guesswork.
44947 */
44948#define DUK__ALLOWED_STANDARD_SPECIFIERS "diouxXeEfFgGaAcsCSpnm"
44949
44950/* maximum length of standard format tag that we support */
44951#define DUK__MAX_FORMAT_TAG_LENGTH 32
44952
44953/* heapobj recursion depth when deep printing is selected */
44954#define DUK__DEEP_DEPTH_LIMIT 8
44955
44956/* maximum recursion depth for loop detection stacks */
44957#define DUK__LOOP_STACK_DEPTH 256
44958
44959/* must match bytecode defines now; build autogenerate? */
44960DUK_LOCAL const char * const duk__bc_optab[256] = {
44961 "LDREG", "STREG", "JUMP", "LDCONST", "LDINT", "LDINTX", "LDTHIS", "LDUNDEF",
44962 "LDNULL", "LDTRUE", "LDFALSE", "GETVAR", "BNOT", "LNOT", "UNM", "UNP",
44963 "EQ_RR", "EQ_CR", "EQ_RC", "EQ_CC", "NEQ_RR", "NEQ_CR", "NEQ_RC", "NEQ_CC",
44964 "SEQ_RR", "SEQ_CR", "SEQ_RC", "SEQ_CC", "SNEQ_RR", "SNEQ_CR", "SNEQ_RC", "SNEQ_CC",
44965
44966 "GT_RR", "GT_CR", "GT_RC", "GT_CC", "GE_RR", "GE_CR", "GE_RC", "GE_CC",
44967 "LT_RR", "LT_CR", "LT_RC", "LT_CC", "LE_RR", "LE_CR", "LE_RC", "LE_CC",
44968 "IFTRUE_R", "IFTRUE_C", "IFFALSE_R", "IFFALSE_C", "ADD_RR", "ADD_CR", "ADD_RC", "ADD_CC",
44969 "SUB_RR", "SUB_CR", "SUB_RC", "SUB_CC", "MUL_RR", "MUL_CR", "MUL_RC", "MUL_CC",
44970
44971 "DIV_RR", "DIV_CR", "DIV_RC", "DIV_CC", "MOD_RR", "MOD_CR", "MOD_RC", "MOD_CC",
44972 "EXP_RR", "EXP_CR", "EXP_RC", "EXP_CC", "BAND_RR", "BAND_CR", "BAND_RC", "BAND_CC",
44973 "BOR_RR", "BOR_CR", "BOR_RC", "BOR_CC", "BXOR_RR", "BXOR_CR", "BXOR_RC", "BXOR_CC",
44974 "BASL_RR", "BASL_CR", "BASL_RC", "BASL_CC", "BLSR_RR", "BLSR_CR", "BLSR_RC", "BLSR_CC",
44975
44976 "BASR_RR", "BASR_CR", "BASR_RC", "BASR_CC", "INSTOF_RR", "INSTOF_CR", "INSTOF_RC", "INSTOF_CC",
44977 "IN_RR", "IN_CR", "IN_RC", "IN_CC", "GETPROP_RR", "GETPROP_CR", "GETPROP_RC", "GETPROP_CC",
44978 "PUTPROP_RR", "PUTPROP_CR", "PUTPROP_RC", "PUTPROP_CC", "DELPROP_RR", "DELPROP_CR", "DELPROP_RC", "DELPROP_CC",
44979 "PREINCR", "PREDECR", "POSTINCR", "POSTDECR", "PREINCV", "PREDECV", "POSTINCV", "POSTDECV",
44980
44981 "PREINCP_RR", "PREINCP_CR", "PREINCP_RC", "PREINCP_CC", "PREDECP_RR", "PREDECP_CR", "PREDECP_RC", "PREDECP_CC",
44982 "POSTINCP_RR", "POSTINCP_CR", "POSTINCP_RC", "POSTINCP_CC", "POSTDECP_RR", "POSTDECP_CR", "POSTDECP_RC", "POSTDECP_CC",
44983 "DECLVAR_RR", "DECLVAR_CR", "DECLVAR_RC", "DECLVAR_CC", "REGEXP_RR", "REGEXP_RC", "REGEXP_CR", "REGEXP_CC",
44984 "CLOSURE", "TYPEOF", "TYPEOFID", "PUTVAR", "DELVAR", "RETREG", "RETUNDEF", "RETCONST",
44985
44986 "RETCONSTN", "LABEL", "ENDLABEL", "BREAK", "CONTINUE", "TRYCATCH", "ENDTRY", "ENDCATCH",
44987 "ENDFIN", "THROW", "INVLHS", "CSREG", "CSVAR_RR", "CSVAR_CR", "CSVAR_RC", "CSVAR_CC",
44988 "CALL0", "CALL1", "CALL2", "CALL3", "CALL4", "CALL5", "CALL6", "CALL7",
44989 "CALL8", "CALL9", "CALL10", "CALL11", "CALL12", "CALL13", "CALL14", "CALL15",
44990
44991 "NEWOBJ", "NEWARR", "MPUTOBJ", "MPUTOBJI", "INITSET", "INITGET", "MPUTARR", "MPUTARRI",
44992 "SETALEN", "INITENUM", "NEXTENUM", "NEWTARGET", "DEBUGGER", "NOP", "INVALID", "UNUSED207",
44993 "GETPROPC_RR", "GETPROPC_CR", "GETPROPC_RC", "GETPROPC_CC", "UNUSED212", "UNUSED213", "UNUSED214", "UNUSED215",
44994 "UNUSED216", "UNUSED217", "UNUSED218", "UNUSED219", "UNUSED220", "UNUSED221", "UNUSED222", "UNUSED223",
44995
44996 "UNUSED224", "UNUSED225", "UNUSED226", "UNUSED227", "UNUSED228", "UNUSED229", "UNUSED230", "UNUSED231",
44997 "UNUSED232", "UNUSED233", "UNUSED234", "UNUSED235", "UNUSED236", "UNUSED237", "UNUSED238", "UNUSED239",
44998 "UNUSED240", "UNUSED241", "UNUSED242", "UNUSED243", "UNUSED244", "UNUSED245", "UNUSED246", "UNUSED247",
44999 "UNUSED248", "UNUSED249", "UNUSED250", "UNUSED251", "UNUSED252", "UNUSED253", "UNUSED254", "UNUSED255"
45000};
45001
45002typedef struct duk__dprint_state duk__dprint_state;
45003struct duk__dprint_state {
45004 duk_fixedbuffer *fb;
45005
45006 /* loop_stack_index could be perhaps be replaced by 'depth', but it's nice
45007 * to not couple these two mechanisms unnecessarily.
45008 */
45009 duk_hobject *loop_stack[DUK__LOOP_STACK_DEPTH];
45010 duk_int_t loop_stack_index;
45011 duk_int_t loop_stack_limit;
45012
45013 duk_int_t depth;
45014 duk_int_t depth_limit;
45015
45016 duk_bool_t pointer;
45017 duk_bool_t heavy;
45018 duk_bool_t binary;
45019 duk_bool_t follow_proto;
45020 duk_bool_t internal;
45021 duk_bool_t hexdump;
45022};
45023
45024/* helpers */
45025DUK_LOCAL_DECL void duk__print_hstring(duk__dprint_state *st, duk_hstring *k, duk_bool_t quotes);
45026DUK_LOCAL_DECL void duk__print_hobject(duk__dprint_state *st, duk_hobject *h);
45027DUK_LOCAL_DECL void duk__print_hbuffer(duk__dprint_state *st, duk_hbuffer *h);
45028DUK_LOCAL_DECL void duk__print_tval(duk__dprint_state *st, duk_tval *tv);
45029DUK_LOCAL_DECL void duk__print_instr(duk__dprint_state *st, duk_instr_t ins);
45030DUK_LOCAL_DECL void duk__print_heaphdr(duk__dprint_state *st, duk_heaphdr *h);
45031DUK_LOCAL_DECL void duk__print_shared_heaphdr(duk__dprint_state *st, duk_heaphdr *h);
45032DUK_LOCAL_DECL void duk__print_shared_heaphdr_string(duk__dprint_state *st, duk_heaphdr_string *h);
45033
45034DUK_LOCAL void duk__print_shared_heaphdr(duk__dprint_state *st, duk_heaphdr *h) {
45035 duk_fixedbuffer *fb = st->fb;
45036
45037 if (st->heavy) {
45038 duk_fb_sprintf(fb, "(%p)", (void *) h);
45039 }
45040
45041 if (!h) {
45042 return;
45043 }
45044
45045 if (st->binary) {
45046 duk_size_t i;
45047 duk_fb_put_byte(fb, (duk_uint8_t) DUK_ASC_LBRACKET);
45048 for (i = 0; i < (duk_size_t) sizeof(*h); i++) {
45049 duk_fb_sprintf(fb, "%02lx", (unsigned long) ((duk_uint8_t *) h)[i]);
45050 }
45051 duk_fb_put_byte(fb, (duk_uint8_t) DUK_ASC_RBRACKET);
45052 }
45053
45054#if defined(DUK_USE_REFERENCE_COUNTING) /* currently implicitly also DUK_USE_DOUBLE_LINKED_HEAP */
45055 if (st->heavy) {
45056 duk_fb_sprintf(fb,
45057 "[h_next=%p,h_prev=%p,h_refcount=%lu,h_flags=%08lx,type=%ld,"
45058 "reachable=%ld,temproot=%ld,finalizable=%ld,finalized=%ld]",
45059 (void *) DUK_HEAPHDR_GET_NEXT(NULL, h),
45060 (void *) DUK_HEAPHDR_GET_PREV(NULL, h),
45061 (unsigned long) DUK_HEAPHDR_GET_REFCOUNT(h),
45062 (unsigned long) DUK_HEAPHDR_GET_FLAGS(h),
45063 (long) DUK_HEAPHDR_GET_TYPE(h),
45064 (long) (DUK_HEAPHDR_HAS_REACHABLE(h) ? 1 : 0),
45065 (long) (DUK_HEAPHDR_HAS_TEMPROOT(h) ? 1 : 0),
45066 (long) (DUK_HEAPHDR_HAS_FINALIZABLE(h) ? 1 : 0),
45067 (long) (DUK_HEAPHDR_HAS_FINALIZED(h) ? 1 : 0));
45068 }
45069#else
45070 if (st->heavy) {
45071 duk_fb_sprintf(fb,
45072 "[h_next=%p,h_flags=%08lx,type=%ld,reachable=%ld,temproot=%ld,finalizable=%ld,finalized=%ld]",
45073 (void *) DUK_HEAPHDR_GET_NEXT(NULL, h),
45074 (unsigned long) DUK_HEAPHDR_GET_FLAGS(h),
45075 (long) DUK_HEAPHDR_GET_TYPE(h),
45076 (long) (DUK_HEAPHDR_HAS_REACHABLE(h) ? 1 : 0),
45077 (long) (DUK_HEAPHDR_HAS_TEMPROOT(h) ? 1 : 0),
45078 (long) (DUK_HEAPHDR_HAS_FINALIZABLE(h) ? 1 : 0),
45079 (long) (DUK_HEAPHDR_HAS_FINALIZED(h) ? 1 : 0));
45080 }
45081#endif
45082}
45083
45084DUK_LOCAL void duk__print_shared_heaphdr_string(duk__dprint_state *st, duk_heaphdr_string *h) {
45085 duk_fixedbuffer *fb = st->fb;
45086
45087 if (st->heavy) {
45088 duk_fb_sprintf(fb, "(%p)", (void *) h);
45089 }
45090
45091 if (!h) {
45092 return;
45093 }
45094
45095 if (st->binary) {
45096 duk_size_t i;
45097 duk_fb_put_byte(fb, (duk_uint8_t) DUK_ASC_LBRACKET);
45098 for (i = 0; i < (duk_size_t) sizeof(*h); i++) {
45099 duk_fb_sprintf(fb, "%02lx", (unsigned long) ((duk_uint8_t *) h)[i]);
45100 }
45101 duk_fb_put_byte(fb, (duk_uint8_t) DUK_ASC_RBRACKET);
45102 }
45103
45104#if defined(DUK_USE_REFERENCE_COUNTING)
45105 if (st->heavy) {
45106 duk_fb_sprintf(fb,
45107 "[h_refcount=%lu,h_flags=%08lx,type=%ld,reachable=%ld,temproot=%ld,finalizable=%ld,finalized=%ld]",
45108 (unsigned long) DUK_HEAPHDR_GET_REFCOUNT((duk_heaphdr *) h),
45109 (unsigned long) DUK_HEAPHDR_GET_FLAGS((duk_heaphdr *) h),
45110 (long) DUK_HEAPHDR_GET_TYPE((duk_heaphdr *) h),
45111 (long) (DUK_HEAPHDR_HAS_REACHABLE((duk_heaphdr *) h) ? 1 : 0),
45112 (long) (DUK_HEAPHDR_HAS_TEMPROOT((duk_heaphdr *) h) ? 1 : 0),
45113 (long) (DUK_HEAPHDR_HAS_FINALIZABLE((duk_heaphdr *) h) ? 1 : 0),
45114 (long) (DUK_HEAPHDR_HAS_FINALIZED((duk_heaphdr *) h) ? 1 : 0));
45115 }
45116#else
45117 if (st->heavy) {
45118 duk_fb_sprintf(fb,
45119 "[h_flags=%08lx,type=%ld,reachable=%ld,temproot=%ld,finalizable=%ld,finalized=%ld]",
45120 (unsigned long) DUK_HEAPHDR_GET_FLAGS((duk_heaphdr *) h),
45121 (long) DUK_HEAPHDR_GET_TYPE((duk_heaphdr *) h),
45122 (long) (DUK_HEAPHDR_HAS_REACHABLE((duk_heaphdr *) h) ? 1 : 0),
45123 (long) (DUK_HEAPHDR_HAS_TEMPROOT((duk_heaphdr *) h) ? 1 : 0),
45124 (long) (DUK_HEAPHDR_HAS_FINALIZABLE((duk_heaphdr *) h) ? 1 : 0),
45125 (long) (DUK_HEAPHDR_HAS_FINALIZED((duk_heaphdr *) h) ? 1 : 0));
45126 }
45127#endif
45128}
45129
45130DUK_LOCAL void duk__print_hstring(duk__dprint_state *st, duk_hstring *h, duk_bool_t quotes) {
45131 duk_fixedbuffer *fb = st->fb;
45132 const duk_uint8_t *p;
45133 const duk_uint8_t *p_end;
45134
45135 /* terminal type: no depth check */
45136
45137 if (duk_fb_is_full(fb)) {
45138 return;
45139 }
45140
45141 duk__print_shared_heaphdr_string(st, &h->hdr);
45142
45143 if (!h) {
45144 duk_fb_put_cstring(fb, "NULL");
45145 return;
45146 }
45147
45148 p = DUK_HSTRING_GET_DATA(h);
45149 p_end = p + DUK_HSTRING_GET_BYTELEN(h);
45150
45151 if (p_end > p && p[0] == DUK_ASC_UNDERSCORE) {
45152 /* If property key begins with underscore, encode it with
45153 * forced quotes (e.g. "_Foo") to distinguish it from encoded
45154 * internal properties (e.g. \x82Bar -> _Bar).
45155 */
45156 quotes = 1;
45157 }
45158
45159 if (quotes) {
45160 duk_fb_put_byte(fb, (duk_uint8_t) DUK_ASC_DOUBLEQUOTE);
45161 }
45162 while (p < p_end) {
45163 duk_uint8_t ch = *p++;
45164
45165 /* two special escapes: '\' and '"', other printables as is */
45166 if (ch == '\\') {
45167 duk_fb_sprintf(fb, "\\\\");
45168 } else if (ch == '"') {
45169 duk_fb_sprintf(fb, "\\\"");
45170 } else if (ch >= 0x20 && ch <= 0x7e) {
45171 duk_fb_put_byte(fb, ch);
45172 } else if (ch == 0x82 && !quotes) {
45173 /* encode \x82Bar as _Bar if no quotes are
45174 * applied, this is for readable internal keys.
45175 */
45176 duk_fb_put_byte(fb, (duk_uint8_t) DUK_ASC_UNDERSCORE);
45177 } else {
45178 duk_fb_sprintf(fb, "\\x%02lx", (unsigned long) ch);
45179 }
45180 }
45181 if (quotes) {
45182 duk_fb_put_byte(fb, (duk_uint8_t) DUK_ASC_DOUBLEQUOTE);
45183 }
45184#if defined(DUK_USE_REFERENCE_COUNTING)
45185 /* XXX: limit to quoted strings only, to save keys from being cluttered? */
45186 duk_fb_sprintf(fb, "/%lu", (unsigned long) DUK_HEAPHDR_GET_REFCOUNT(&h->hdr));
45187#endif
45188}
45189
45190#define DUK__COMMA() \
45191 do { \
45192 if (first) { \
45193 first = 0; \
45194 } else { \
45195 duk_fb_put_byte(fb, (duk_uint8_t) DUK_ASC_COMMA); \
45196 } \
45197 } while (0)
45198
45199DUK_LOCAL void duk__print_hobject(duk__dprint_state *st, duk_hobject *h) {
45200 duk_fixedbuffer *fb = st->fb;
45202 duk_tval *tv;
45203 duk_hstring *key;
45204 duk_bool_t first = 1;
45205 const char *brace1 = "{";
45206 const char *brace2 = "}";
45207 duk_bool_t pushed_loopstack = 0;
45208
45209 if (duk_fb_is_full(fb)) {
45210 return;
45211 }
45212
45213 duk__print_shared_heaphdr(st, &h->hdr);
45214
45215 if (h && DUK_HOBJECT_HAS_ARRAY_PART(h)) {
45216 brace1 = "[";
45217 brace2 = "]";
45218 }
45219
45220 if (!h) {
45221 duk_fb_put_cstring(fb, "NULL");
45222 goto finished;
45223 }
45224
45225 if (st->depth >= st->depth_limit) {
45226 const char *subtype = "generic";
45227
45228 if (DUK_HOBJECT_IS_COMPFUNC(h)) {
45229 subtype = "compfunc";
45230 } else if (DUK_HOBJECT_IS_NATFUNC(h)) {
45231 subtype = "natfunc";
45232 } else if (DUK_HOBJECT_IS_THREAD(h)) {
45233 subtype = "thread";
45234 } else if (DUK_HOBJECT_IS_BUFOBJ(h)) {
45235 subtype = "bufobj";
45236 } else if (DUK_HOBJECT_IS_ARRAY(h)) {
45237 subtype = "array";
45238 }
45239 duk_fb_sprintf(fb, "%sobject/%s %p%s", (const char *) brace1, subtype, (void *) h, (const char *) brace2);
45240 return;
45241 }
45242
45243 for (i = 0; i < (duk_uint_fast32_t) st->loop_stack_index; i++) {
45244 if (st->loop_stack[i] == h) {
45245 duk_fb_sprintf(fb, "%sLOOP:%p%s", (const char *) brace1, (void *) h, (const char *) brace2);
45246 return;
45247 }
45248 }
45249
45250 /* after this, return paths should 'goto finished' for decrement */
45251 st->depth++;
45252
45253 if (st->loop_stack_index >= st->loop_stack_limit) {
45254 duk_fb_sprintf(fb, "%sOUT-OF-LOOP-STACK%s", (const char *) brace1, (const char *) brace2);
45255 goto finished;
45256 }
45257 st->loop_stack[st->loop_stack_index++] = h;
45258 pushed_loopstack = 1;
45259
45260 /*
45261 * Notation: double underscore used for internal properties which are not
45262 * stored in the property allocation (e.g. '__valstack').
45263 */
45264
45265 duk_fb_put_cstring(fb, brace1);
45266
45267 if (DUK_HOBJECT_GET_PROPS(NULL, h)) {
45268 duk_uint32_t a_limit;
45269
45270 a_limit = DUK_HOBJECT_GET_ASIZE(h);
45271 if (st->internal) {
45272 /* dump all allocated entries, unused entries print as 'unused',
45273 * note that these may extend beyond current 'length' and look
45274 * a bit funny.
45275 */
45276 } else {
45277 /* leave out trailing 'unused' elements */
45278 while (a_limit > 0) {
45279 tv = DUK_HOBJECT_A_GET_VALUE_PTR(NULL, h, a_limit - 1);
45280 if (!DUK_TVAL_IS_UNUSED(tv)) {
45281 break;
45282 }
45283 a_limit--;
45284 }
45285 }
45286
45287 for (i = 0; i < a_limit; i++) {
45288 tv = DUK_HOBJECT_A_GET_VALUE_PTR(NULL, h, i);
45289 DUK__COMMA();
45290 duk__print_tval(st, tv);
45291 }
45292 for (i = 0; i < DUK_HOBJECT_GET_ENEXT(h); i++) {
45293 key = DUK_HOBJECT_E_GET_KEY(NULL, h, i);
45294 if (!key) {
45295 continue;
45296 }
45297 if (!st->internal && DUK_HSTRING_HAS_HIDDEN(key)) {
45298 continue;
45299 }
45300 DUK__COMMA();
45301 duk__print_hstring(st, key, 0);
45302 duk_fb_put_byte(fb, (duk_uint8_t) DUK_ASC_COLON);
45303 if (DUK_HOBJECT_E_SLOT_IS_ACCESSOR(NULL, h, i)) {
45304 duk_fb_sprintf(fb,
45305 "[get:%p,set:%p]",
45306 (void *) DUK_HOBJECT_E_GET_VALUE(NULL, h, i).a.get,
45307 (void *) DUK_HOBJECT_E_GET_VALUE(NULL, h, i).a.set);
45308 } else {
45309 tv = &DUK_HOBJECT_E_GET_VALUE(NULL, h, i).v;
45310 duk__print_tval(st, tv);
45311 }
45312 if (st->heavy) {
45313 duk_fb_sprintf(fb, "<%02lx>", (unsigned long) DUK_HOBJECT_E_GET_FLAGS(NULL, h, i));
45314 }
45315 }
45316 }
45317 if (st->internal) {
45318 if (DUK_HOBJECT_IS_ARRAY(h)) {
45319 DUK__COMMA();
45320 duk_fb_sprintf(fb, "__array:true");
45321 }
45323 DUK__COMMA();
45324 duk_fb_sprintf(fb, "__extensible:true");
45325 }
45327 DUK__COMMA();
45328 duk_fb_sprintf(fb, "__constructable:true");
45329 }
45331 DUK__COMMA();
45332 duk_fb_sprintf(fb, "__boundfunc:true");
45333 }
45334 if (DUK_HOBJECT_HAS_COMPFUNC(h)) {
45335 DUK__COMMA();
45336 duk_fb_sprintf(fb, "__compfunc:true");
45337 }
45338 if (DUK_HOBJECT_HAS_NATFUNC(h)) {
45339 DUK__COMMA();
45340 duk_fb_sprintf(fb, "__natfunc:true");
45341 }
45342 if (DUK_HOBJECT_HAS_BUFOBJ(h)) {
45343 DUK__COMMA();
45344 duk_fb_sprintf(fb, "__bufobj:true");
45345 }
45346 if (DUK_HOBJECT_IS_THREAD(h)) {
45347 DUK__COMMA();
45348 duk_fb_sprintf(fb, "__thread:true");
45349 }
45351 DUK__COMMA();
45352 duk_fb_sprintf(fb, "__array_part:true");
45353 }
45354 if (DUK_HOBJECT_HAS_STRICT(h)) {
45355 DUK__COMMA();
45356 duk_fb_sprintf(fb, "__strict:true");
45357 }
45358 if (DUK_HOBJECT_HAS_NOTAIL(h)) {
45359 DUK__COMMA();
45360 duk_fb_sprintf(fb, "__notail:true");
45361 }
45362 if (DUK_HOBJECT_HAS_NEWENV(h)) {
45363 DUK__COMMA();
45364 duk_fb_sprintf(fb, "__newenv:true");
45365 }
45367 DUK__COMMA();
45368 duk_fb_sprintf(fb, "__namebinding:true");
45369 }
45371 DUK__COMMA();
45372 duk_fb_sprintf(fb, "__createargs:true");
45373 }
45375 DUK__COMMA();
45376 duk_fb_sprintf(fb, "__exotic_array:true");
45377 }
45379 DUK__COMMA();
45380 duk_fb_sprintf(fb, "__exotic_stringobj:true");
45381 }
45383 DUK__COMMA();
45384 duk_fb_sprintf(fb, "__exotic_arguments:true");
45385 }
45386 if (DUK_HOBJECT_IS_BUFOBJ(h)) {
45387 DUK__COMMA();
45388 duk_fb_sprintf(fb, "__exotic_bufobj:true");
45389 }
45391 DUK__COMMA();
45392 duk_fb_sprintf(fb, "__exotic_proxyobj:true");
45393 }
45394 }
45395
45396 if (st->internal && DUK_HOBJECT_IS_ARRAY(h)) {
45397 duk_harray *a = (duk_harray *) h;
45398 DUK__COMMA();
45399 duk_fb_sprintf(fb, "__length:%ld", (long) a->length);
45400 DUK__COMMA();
45401 duk_fb_sprintf(fb, "__length_nonwritable:%ld", (long) a->length_nonwritable);
45402 } else if (st->internal && DUK_HOBJECT_IS_COMPFUNC(h)) {
45403 duk_hcompfunc *f = (duk_hcompfunc *) h;
45404 DUK__COMMA();
45405 duk_fb_put_cstring(fb, "__data:");
45406 duk__print_hbuffer(st, (duk_hbuffer *) DUK_HCOMPFUNC_GET_DATA(NULL, f));
45407 DUK__COMMA();
45408 duk_fb_put_cstring(fb, "__lexenv:");
45409 duk__print_hobject(st, DUK_HCOMPFUNC_GET_LEXENV(NULL, f));
45410 DUK__COMMA();
45411 duk_fb_put_cstring(fb, "__varenv:");
45412 duk__print_hobject(st, DUK_HCOMPFUNC_GET_VARENV(NULL, f));
45413 DUK__COMMA();
45414 duk_fb_sprintf(fb, "__nregs:%ld", (long) f->nregs);
45415 DUK__COMMA();
45416 duk_fb_sprintf(fb, "__nargs:%ld", (long) f->nargs);
45417#if defined(DUK_USE_DEBUGGER_SUPPORT)
45418 DUK__COMMA();
45419 duk_fb_sprintf(fb, "__start_line:%ld", (long) f->start_line);
45420 DUK__COMMA();
45421 duk_fb_sprintf(fb, "__end_line:%ld", (long) f->end_line);
45422#endif
45423 DUK__COMMA();
45424 duk_fb_put_cstring(fb, "__data:");
45425 duk__print_hbuffer(st, (duk_hbuffer *) DUK_HCOMPFUNC_GET_DATA(NULL, f));
45426 } else if (st->internal && DUK_HOBJECT_IS_NATFUNC(h)) {
45427 duk_hnatfunc *f = (duk_hnatfunc *) h;
45428 DUK__COMMA();
45429 duk_fb_sprintf(fb, "__func:");
45430 duk_fb_put_funcptr(fb, (duk_uint8_t *) &f->func, sizeof(f->func));
45431 DUK__COMMA();
45432 duk_fb_sprintf(fb, "__nargs:%ld", (long) f->nargs);
45433 DUK__COMMA();
45434 duk_fb_sprintf(fb, "__magic:%ld", (long) f->magic);
45435 } else if (st->internal && DUK_HOBJECT_IS_DECENV(h)) {
45436 duk_hdecenv *e = (duk_hdecenv *) h;
45437 DUK__COMMA();
45438 duk_fb_sprintf(fb, "__thread:");
45439 duk__print_hobject(st, (duk_hobject *) e->thread);
45440 DUK__COMMA();
45441 duk_fb_sprintf(fb, "__varmap:");
45442 duk__print_hobject(st, (duk_hobject *) e->varmap);
45443 DUK__COMMA();
45444 duk_fb_sprintf(fb, "__regbase_byteoff:%ld", (long) e->regbase_byteoff);
45445 } else if (st->internal && DUK_HOBJECT_IS_OBJENV(h)) {
45446 duk_hobjenv *e = (duk_hobjenv *) h;
45447 DUK__COMMA();
45448 duk_fb_sprintf(fb, "__target:");
45449 duk__print_hobject(st, (duk_hobject *) e->target);
45450 DUK__COMMA();
45451 duk_fb_sprintf(fb, "__has_this:%ld", (long) e->has_this);
45452#if defined(DUK_USE_BUFFEROBJECT_SUPPORT)
45453 } else if (st->internal && DUK_HOBJECT_IS_BUFOBJ(h)) {
45454 duk_hbufobj *b = (duk_hbufobj *) h;
45455 DUK__COMMA();
45456 duk_fb_sprintf(fb, "__buf:");
45457 duk__print_hbuffer(st, (duk_hbuffer *) b->buf);
45458 DUK__COMMA();
45459 duk_fb_sprintf(fb, "__buf_prop:");
45460 duk__print_hobject(st, (duk_hobject *) b->buf_prop);
45461 DUK__COMMA();
45462 duk_fb_sprintf(fb, "__offset:%ld", (long) b->offset);
45463 DUK__COMMA();
45464 duk_fb_sprintf(fb, "__length:%ld", (long) b->length);
45465 DUK__COMMA();
45466 duk_fb_sprintf(fb, "__shift:%ld", (long) b->shift);
45467 DUK__COMMA();
45468 duk_fb_sprintf(fb, "__elemtype:%ld", (long) b->elem_type);
45469#endif
45470 } else if (st->internal && DUK_HOBJECT_IS_PROXY(h)) {
45471 duk_hproxy *p = (duk_hproxy *) h;
45472 DUK__COMMA();
45473 duk_fb_sprintf(fb, "__target:");
45474 duk__print_hobject(st, p->target);
45475 DUK__COMMA();
45476 duk_fb_sprintf(fb, "__handler:");
45477 duk__print_hobject(st, p->handler);
45478 } else if (st->internal && DUK_HOBJECT_IS_THREAD(h)) {
45479 duk_hthread *t = (duk_hthread *) h;
45480 DUK__COMMA();
45481 duk_fb_sprintf(fb, "__ptr_curr_pc:%p", (void *) t->ptr_curr_pc);
45482 DUK__COMMA();
45483 duk_fb_sprintf(fb, "__heap:%p", (void *) t->heap);
45484 DUK__COMMA();
45485 duk_fb_sprintf(fb, "__strict:%ld", (long) t->strict);
45486 DUK__COMMA();
45487 duk_fb_sprintf(fb, "__state:%ld", (long) t->state);
45488 DUK__COMMA();
45489 duk_fb_sprintf(fb, "__unused1:%ld", (long) t->unused1);
45490 DUK__COMMA();
45491 duk_fb_sprintf(fb, "__unused2:%ld", (long) t->unused2);
45492 DUK__COMMA();
45493 duk_fb_sprintf(fb, "__valstack:%p", (void *) t->valstack);
45494 DUK__COMMA();
45495 duk_fb_sprintf(fb, "__valstack_end:%p/%ld", (void *) t->valstack_end, (long) (t->valstack_end - t->valstack));
45496 DUK__COMMA();
45497 duk_fb_sprintf(fb,
45498 "__valstack_alloc_end:%p/%ld",
45499 (void *) t->valstack_alloc_end,
45500 (long) (t->valstack_alloc_end - t->valstack));
45501 DUK__COMMA();
45502 duk_fb_sprintf(fb,
45503 "__valstack_bottom:%p/%ld",
45504 (void *) t->valstack_bottom,
45505 (long) (t->valstack_bottom - t->valstack));
45506 DUK__COMMA();
45507 duk_fb_sprintf(fb, "__valstack_top:%p/%ld", (void *) t->valstack_top, (long) (t->valstack_top - t->valstack));
45508 DUK__COMMA();
45509 duk_fb_sprintf(fb, "__callstack_curr:%p", (void *) t->callstack_curr);
45510 DUK__COMMA();
45511 duk_fb_sprintf(fb, "__callstack_top:%ld", (long) t->callstack_top);
45512 DUK__COMMA();
45513 duk_fb_sprintf(fb, "__callstack_preventcount:%ld", (long) t->callstack_preventcount);
45514 DUK__COMMA();
45515 duk_fb_sprintf(fb, "__resumer:");
45516 duk__print_hobject(st, (duk_hobject *) t->resumer);
45517 DUK__COMMA();
45518 duk_fb_sprintf(fb, "__compile_ctx:%p", (void *) t->compile_ctx);
45519#if defined(DUK_USE_INTERRUPT_COUNTER)
45520 DUK__COMMA();
45521 duk_fb_sprintf(fb, "__interrupt_counter:%ld", (long) t->interrupt_counter);
45522 DUK__COMMA();
45523 duk_fb_sprintf(fb, "__interrupt_init:%ld", (long) t->interrupt_init);
45524#endif
45525
45526 /* XXX: print built-ins array? */
45527 }
45528#if defined(DUK_USE_REFERENCE_COUNTING)
45529 if (st->internal) {
45530 DUK__COMMA();
45531 duk_fb_sprintf(fb, "__refcount:%lu", (unsigned long) DUK_HEAPHDR_GET_REFCOUNT((duk_heaphdr *) h));
45532 }
45533#endif
45534 if (st->internal) {
45535 DUK__COMMA();
45536 duk_fb_sprintf(fb, "__class:%ld", (long) DUK_HOBJECT_GET_CLASS_NUMBER(h));
45537 }
45538
45539 DUK__COMMA();
45540 duk_fb_sprintf(fb, "__heapptr:%p", (void *) h); /* own pointer */
45541
45542 /* prototype should be last, for readability */
45543 if (DUK_HOBJECT_GET_PROTOTYPE(NULL, h)) {
45544 if (st->follow_proto) {
45545 DUK__COMMA();
45546 duk_fb_put_cstring(fb, "__prototype:");
45547 duk__print_hobject(st, DUK_HOBJECT_GET_PROTOTYPE(NULL, h));
45548 } else {
45549 DUK__COMMA();
45550 duk_fb_sprintf(fb, "__prototype:%p", (void *) DUK_HOBJECT_GET_PROTOTYPE(NULL, h));
45551 }
45552 }
45553
45554 duk_fb_put_cstring(fb, brace2);
45555
45556#if defined(DUK_USE_HOBJECT_HASH_PART)
45557 if (st->heavy && DUK_HOBJECT_GET_HSIZE(h) > 0) {
45558 duk_fb_put_byte(fb, (duk_uint8_t) DUK_ASC_LANGLE);
45559 for (i = 0; i < DUK_HOBJECT_GET_HSIZE(h); i++) {
45560 duk_uint_t h_idx = DUK_HOBJECT_H_GET_INDEX(NULL, h, i);
45561 if (i > 0) {
45562 duk_fb_put_byte(fb, (duk_uint8_t) DUK_ASC_COMMA);
45563 }
45564 if (h_idx == DUK_HOBJECT_HASHIDX_UNUSED) {
45565 duk_fb_sprintf(fb, "u");
45566 } else if (h_idx == DUK_HOBJECT_HASHIDX_DELETED) {
45567 duk_fb_sprintf(fb, "d");
45568 } else {
45569 duk_fb_sprintf(fb, "%ld", (long) h_idx);
45570 }
45571 }
45572 duk_fb_put_byte(fb, (duk_uint8_t) DUK_ASC_RANGLE);
45573 }
45574#endif
45575
45576finished:
45577 st->depth--;
45578 if (pushed_loopstack) {
45579 st->loop_stack_index--;
45580 st->loop_stack[st->loop_stack_index] = NULL;
45581 }
45582}
45583
45584DUK_LOCAL void duk__print_hbuffer(duk__dprint_state *st, duk_hbuffer *h) {
45585 duk_fixedbuffer *fb = st->fb;
45586 duk_size_t i, n;
45587 duk_uint8_t *p;
45588
45589 if (duk_fb_is_full(fb)) {
45590 return;
45591 }
45592
45593 /* terminal type: no depth check */
45594
45595 if (!h) {
45596 duk_fb_put_cstring(fb, "NULL");
45597 return;
45598 }
45599
45600 if (DUK_HBUFFER_HAS_DYNAMIC(h)) {
45601 if (DUK_HBUFFER_HAS_EXTERNAL(h)) {
45603 duk_fb_sprintf(fb,
45604 "buffer:external:%p:%ld",
45605 (void *) DUK_HBUFFER_EXTERNAL_GET_DATA_PTR(NULL, g),
45607 } else {
45609 duk_fb_sprintf(fb,
45610 "buffer:dynamic:%p:%ld",
45611 (void *) DUK_HBUFFER_DYNAMIC_GET_DATA_PTR(NULL, g),
45613 }
45614 } else {
45615 duk_fb_sprintf(fb, "buffer:fixed:%ld", (long) DUK_HBUFFER_GET_SIZE(h));
45616 }
45617
45618#if defined(DUK_USE_REFERENCE_COUNTING)
45619 duk_fb_sprintf(fb, "/%lu", (unsigned long) DUK_HEAPHDR_GET_REFCOUNT(&h->hdr));
45620#endif
45621
45622 if (st->hexdump) {
45623 duk_fb_sprintf(fb, "=[");
45624 n = DUK_HBUFFER_GET_SIZE(h);
45625 p = (duk_uint8_t *) DUK_HBUFFER_GET_DATA_PTR(NULL, h);
45626 for (i = 0; i < n; i++) {
45627 duk_fb_sprintf(fb, "%02lx", (unsigned long) p[i]);
45628 }
45629 duk_fb_sprintf(fb, "]");
45630 }
45631}
45632
45633DUK_LOCAL void duk__print_heaphdr(duk__dprint_state *st, duk_heaphdr *h) {
45634 duk_fixedbuffer *fb = st->fb;
45635
45636 if (duk_fb_is_full(fb)) {
45637 return;
45638 }
45639
45640 if (!h) {
45641 duk_fb_put_cstring(fb, "NULL");
45642 return;
45643 }
45644
45645 switch (DUK_HEAPHDR_GET_TYPE(h)) {
45646 case DUK_HTYPE_STRING:
45647 duk__print_hstring(st, (duk_hstring *) h, 1);
45648 break;
45649 case DUK_HTYPE_OBJECT:
45650 duk__print_hobject(st, (duk_hobject *) h);
45651 break;
45652 case DUK_HTYPE_BUFFER:
45653 duk__print_hbuffer(st, (duk_hbuffer *) h);
45654 break;
45655 default:
45656 duk_fb_sprintf(fb, "[unknown htype %ld]", (long) DUK_HEAPHDR_GET_TYPE(h));
45657 break;
45658 }
45659}
45660
45661DUK_LOCAL void duk__print_tval(duk__dprint_state *st, duk_tval *tv) {
45662 duk_fixedbuffer *fb = st->fb;
45663
45664 if (duk_fb_is_full(fb)) {
45665 return;
45666 }
45667
45668 /* depth check is done when printing an actual type */
45669
45670 if (st->heavy) {
45671 duk_fb_sprintf(fb, "(%p)", (void *) tv);
45672 }
45673
45674 if (!tv) {
45675 duk_fb_put_cstring(fb, "NULL");
45676 return;
45677 }
45678
45679 if (st->binary) {
45680 duk_size_t i;
45681 duk_fb_put_byte(fb, (duk_uint8_t) DUK_ASC_LBRACKET);
45682 for (i = 0; i < (duk_size_t) sizeof(*tv); i++) {
45683 duk_fb_sprintf(fb, "%02lx", (unsigned long) ((duk_uint8_t *) tv)[i]);
45684 }
45685 duk_fb_put_byte(fb, (duk_uint8_t) DUK_ASC_RBRACKET);
45686 }
45687
45688 if (st->heavy) {
45689 duk_fb_put_byte(fb, (duk_uint8_t) DUK_ASC_LANGLE);
45690 }
45691 switch (DUK_TVAL_GET_TAG(tv)) {
45692 case DUK_TAG_UNDEFINED: {
45693 duk_fb_put_cstring(fb, "undefined");
45694 break;
45695 }
45696 case DUK_TAG_UNUSED: {
45697 duk_fb_put_cstring(fb, "unused");
45698 break;
45699 }
45700 case DUK_TAG_NULL: {
45701 duk_fb_put_cstring(fb, "null");
45702 break;
45703 }
45704 case DUK_TAG_BOOLEAN: {
45705 duk_fb_put_cstring(fb, DUK_TVAL_GET_BOOLEAN(tv) ? "true" : "false");
45706 break;
45707 }
45708 case DUK_TAG_STRING: {
45709 /* Note: string is a terminal heap object, so no depth check here */
45710 duk__print_hstring(st, DUK_TVAL_GET_STRING(tv), 1);
45711 break;
45712 }
45713 case DUK_TAG_OBJECT: {
45714 duk__print_hobject(st, DUK_TVAL_GET_OBJECT(tv));
45715 break;
45716 }
45717 case DUK_TAG_BUFFER: {
45718 duk__print_hbuffer(st, DUK_TVAL_GET_BUFFER(tv));
45719 break;
45720 }
45721 case DUK_TAG_POINTER: {
45722 duk_fb_sprintf(fb, "pointer:%p", (void *) DUK_TVAL_GET_POINTER(tv));
45723 break;
45724 }
45725 case DUK_TAG_LIGHTFUNC: {
45726 duk_c_function func;
45727 duk_small_uint_t lf_flags;
45728
45729 DUK_TVAL_GET_LIGHTFUNC(tv, func, lf_flags);
45730 duk_fb_sprintf(fb, "lightfunc:");
45731 duk_fb_put_funcptr(fb, (duk_uint8_t *) &func, sizeof(func));
45732 duk_fb_sprintf(fb, ":%04lx", (long) lf_flags);
45733 break;
45734 }
45735#if defined(DUK_USE_FASTINT)
45736 case DUK_TAG_FASTINT:
45739 duk_fb_sprintf(fb, "%.18g_F", (double) DUK_TVAL_GET_NUMBER(tv));
45740 break;
45741#endif
45742 default: {
45743 /* IEEE double is approximately 16 decimal digits; print a couple extra */
45746 duk_fb_sprintf(fb, "%.18g", (double) DUK_TVAL_GET_NUMBER(tv));
45747 break;
45748 }
45749 }
45750 if (st->heavy) {
45751 duk_fb_put_byte(fb, (duk_uint8_t) DUK_ASC_RANGLE);
45752 }
45753}
45754
45755DUK_LOCAL void duk__print_instr(duk__dprint_state *st, duk_instr_t ins) {
45756 duk_fixedbuffer *fb = st->fb;
45757 duk_small_int_t op;
45758 const char *op_name;
45759
45760 op = (duk_small_int_t) DUK_DEC_OP(ins);
45761 op_name = duk__bc_optab[op];
45762
45763 /* XXX: option to fix opcode length so it lines up nicely */
45764
45765 if (op == DUK_OP_JUMP) {
45766 duk_int_t diff1 = (duk_int_t) (DUK_DEC_ABC(ins) - DUK_BC_JUMP_BIAS); /* from next pc */
45767 duk_int_t diff2 = diff1 + 1; /* from curr pc */
45768
45769 duk_fb_sprintf(fb,
45770 "%s %ld (to pc%c%ld)",
45771 (const char *) op_name,
45772 (long) diff1,
45773 (int) (diff2 >= 0 ? '+' : '-'), /* char format: use int */
45774 (long) (diff2 >= 0 ? diff2 : -diff2));
45775 } else {
45776 duk_fb_sprintf(fb,
45777 "%s %ld, %ld, %ld",
45778 (const char *) op_name,
45779 (long) DUK_DEC_A(ins),
45780 (long) DUK_DEC_B(ins),
45781 (long) DUK_DEC_C(ins));
45782 }
45783}
45784
45785DUK_LOCAL void duk__print_opcode(duk__dprint_state *st, duk_small_int_t opcode) {
45786 duk_fixedbuffer *fb = st->fb;
45787
45788 if (opcode < DUK_BC_OP_MIN || opcode > DUK_BC_OP_MAX) {
45789 duk_fb_sprintf(fb, "?(%ld)", (long) opcode);
45790 } else {
45791 duk_fb_sprintf(fb, "%s", (const char *) duk__bc_optab[opcode]);
45792 }
45793}
45794
45795DUK_LOCAL void duk__print_catcher(duk__dprint_state *st, duk_catcher *cat) {
45796 duk_fixedbuffer *fb = st->fb;
45797
45798 if (duk_fb_is_full(fb)) {
45799 return;
45800 }
45801
45802 if (!cat) {
45803 duk_fb_put_cstring(fb, "NULL");
45804 return;
45805 }
45806
45807 duk_fb_sprintf(fb,
45808 "[catcher ptr=%p parent=%p varname=%p pc_base=%p, idx_base=%ld, flags=0x%08lx]",
45809 (void *) cat,
45810 (void *) cat->parent,
45811 (void *) cat->h_varname,
45812 (void *) cat->pc_base,
45813 (long) cat->idx_base,
45814 (unsigned long) cat->flags);
45815}
45816
45817DUK_LOCAL void duk__print_activation(duk__dprint_state *st, duk_activation *act) {
45818 duk_fixedbuffer *fb = st->fb;
45819
45820 if (duk_fb_is_full(fb)) {
45821 return;
45822 }
45823
45824 if (!act) {
45825 duk_fb_put_cstring(fb, "NULL");
45826 return;
45827 }
45828
45829 /* prev_caller: conditional, omitted on purpose, it's rarely used. */
45830 /* prev_line: conditional, omitted on purpose (but would be nice). */
45831 duk_fb_sprintf(fb,
45832 "[activation ptr=%p tv_func=<omit> func=%p parent=%p var_env=%p lex_env=%p cat=%p curr_pc=%p "
45833 "bottom_byteoff=%ld retval_byteoff=%ld reserve_byteoff=%ld flags=%ld]",
45834 (void *) act,
45835 (void *) act->func,
45836 (void *) act->parent,
45837 (void *) act->var_env,
45838 (void *) act->lex_env,
45839 (void *) act->cat,
45840 (void *) act->curr_pc,
45841 (long) act->bottom_byteoff,
45842 (long) act->retval_byteoff,
45843 (long) act->reserve_byteoff,
45844 (long) act->flags);
45845}
45846
45847DUK_INTERNAL duk_int_t duk_debug_vsnprintf(char *str, duk_size_t size, const char *format, va_list ap) {
45848 duk_fixedbuffer fb;
45849 const char *p = format;
45850 const char *p_end = p + DUK_STRLEN(format);
45851 duk_int_t retval;
45852
45853 duk_memzero(&fb, sizeof(fb));
45854 fb.buffer = (duk_uint8_t *) str;
45855 fb.length = size;
45856 fb.offset = 0;
45857 fb.truncated = 0;
45858
45859 while (p < p_end) {
45860 char ch = *p++;
45861 const char *p_begfmt = NULL;
45862 duk_bool_t got_exclamation = 0;
45863 duk_bool_t got_long = 0; /* %lf, %ld etc */
45864 duk__dprint_state st;
45865
45866 if (ch != DUK_ASC_PERCENT) {
45867 duk_fb_put_byte(&fb, (duk_uint8_t) ch);
45868 continue;
45869 }
45870
45871 /*
45872 * Format tag parsing. Since we don't understand all the
45873 * possible format tags allowed, we just scan for a terminating
45874 * specifier and keep track of relevant modifiers that we do
45875 * understand. See man 3 printf.
45876 */
45877
45878 duk_memzero(&st, sizeof(st));
45879 st.fb = &fb;
45880 st.depth = 0;
45881 st.depth_limit = 1;
45882 st.loop_stack_index = 0;
45883 st.loop_stack_limit = DUK__LOOP_STACK_DEPTH;
45884
45885 p_begfmt = p - 1;
45886 while (p < p_end) {
45887 ch = *p++;
45888
45889 if (ch == DUK_ASC_STAR) {
45890 /* unsupported: would consume multiple args */
45891 goto format_error;
45892 } else if (ch == DUK_ASC_PERCENT) {
45893 duk_fb_put_byte(&fb, (duk_uint8_t) DUK_ASC_PERCENT);
45894 break;
45895 } else if (ch == DUK_ASC_EXCLAMATION) {
45896 got_exclamation = 1;
45897 } else if (!got_exclamation && ch == DUK_ASC_LC_L) {
45898 got_long = 1;
45899 } else if (got_exclamation && ch == DUK_ASC_LC_D) {
45900 st.depth_limit = DUK__DEEP_DEPTH_LIMIT;
45901 } else if (got_exclamation && ch == DUK_ASC_LC_P) {
45902 st.follow_proto = 1;
45903 } else if (got_exclamation && ch == DUK_ASC_LC_I) {
45904 st.internal = 1;
45905 } else if (got_exclamation && ch == DUK_ASC_LC_X) {
45906 st.hexdump = 1;
45907 } else if (got_exclamation && ch == DUK_ASC_LC_H) {
45908 st.heavy = 1;
45909 } else if (got_exclamation && ch == DUK_ASC_ATSIGN) {
45910 st.pointer = 1;
45911 } else if (got_exclamation && ch == DUK_ASC_HASH) {
45912 st.binary = 1;
45913 } else if (got_exclamation && ch == DUK_ASC_UC_T) {
45914 duk_tval *t = va_arg(ap, duk_tval *);
45915 if (st.pointer && !st.heavy) {
45916 duk_fb_sprintf(&fb, "(%p)", (void *) t);
45917 }
45918 duk__print_tval(&st, t);
45919 break;
45920 } else if (got_exclamation && ch == DUK_ASC_UC_O) {
45921 duk_heaphdr *t = va_arg(ap, duk_heaphdr *);
45922 if (st.pointer && !st.heavy) {
45923 duk_fb_sprintf(&fb, "(%p)", (void *) t);
45924 }
45925 duk__print_heaphdr(&st, t);
45926 break;
45927 } else if (got_exclamation && ch == DUK_ASC_UC_I) {
45928 duk_instr_t t = va_arg(ap, duk_instr_t);
45929 duk__print_instr(&st, t);
45930 break;
45931 } else if (got_exclamation && ch == DUK_ASC_UC_X) {
45932 long t = va_arg(ap, long);
45933 duk__print_opcode(&st, (duk_small_int_t) t);
45934 break;
45935 } else if (got_exclamation && ch == DUK_ASC_UC_C) {
45936 duk_catcher *t = va_arg(ap, duk_catcher *);
45937 duk__print_catcher(&st, t);
45938 break;
45939 } else if (got_exclamation && ch == DUK_ASC_UC_A) {
45940 duk_activation *t = va_arg(ap, duk_activation *);
45941 duk__print_activation(&st, t);
45942 break;
45943 } else if (!got_exclamation && strchr(DUK__ALLOWED_STANDARD_SPECIFIERS, (int) ch)) {
45944 char fmtbuf[DUK__MAX_FORMAT_TAG_LENGTH];
45945 duk_size_t fmtlen;
45946
45947 DUK_ASSERT(p >= p_begfmt);
45948 fmtlen = (duk_size_t) (p - p_begfmt);
45949 if (fmtlen >= sizeof(fmtbuf)) {
45950 /* format is too large, abort */
45951 goto format_error;
45952 }
45953 duk_memzero(fmtbuf, sizeof(fmtbuf));
45954 duk_memcpy(fmtbuf, p_begfmt, fmtlen);
45955
45956 /* assume exactly 1 arg, which is why '*' is forbidden; arg size still
45957 * depends on type though.
45958 */
45959
45960 if (ch == DUK_ASC_LC_F || ch == DUK_ASC_LC_G || ch == DUK_ASC_LC_E) {
45961 /* %f and %lf both consume a 'long' */
45962 double arg = va_arg(ap, double);
45963 duk_fb_sprintf(&fb, fmtbuf, arg);
45964 } else if (ch == DUK_ASC_LC_D && got_long) {
45965 /* %ld */
45966 long arg = va_arg(ap, long);
45967 duk_fb_sprintf(&fb, fmtbuf, arg);
45968 } else if (ch == DUK_ASC_LC_D) {
45969 /* %d; only 16 bits are guaranteed */
45970 int arg = va_arg(ap, int);
45971 duk_fb_sprintf(&fb, fmtbuf, arg);
45972 } else if (ch == DUK_ASC_LC_U && got_long) {
45973 /* %lu */
45974 unsigned long arg = va_arg(ap, unsigned long);
45975 duk_fb_sprintf(&fb, fmtbuf, arg);
45976 } else if (ch == DUK_ASC_LC_U) {
45977 /* %u; only 16 bits are guaranteed */
45978 unsigned int arg = va_arg(ap, unsigned int);
45979 duk_fb_sprintf(&fb, fmtbuf, arg);
45980 } else if (ch == DUK_ASC_LC_X && got_long) {
45981 /* %lx */
45982 unsigned long arg = va_arg(ap, unsigned long);
45983 duk_fb_sprintf(&fb, fmtbuf, arg);
45984 } else if (ch == DUK_ASC_LC_X) {
45985 /* %x; only 16 bits are guaranteed */
45986 unsigned int arg = va_arg(ap, unsigned int);
45987 duk_fb_sprintf(&fb, fmtbuf, arg);
45988 } else if (ch == DUK_ASC_LC_S) {
45989 /* %s */
45990 const char *arg = va_arg(ap, const char *);
45991 if (arg == NULL) {
45992 /* '%s' and NULL is not portable, so special case
45993 * it for debug printing.
45994 */
45995 duk_fb_sprintf(&fb, "NULL");
45996 } else {
45997 duk_fb_sprintf(&fb, fmtbuf, arg);
45998 }
45999 } else if (ch == DUK_ASC_LC_P) {
46000 /* %p */
46001 void *arg = va_arg(ap, void *);
46002 if (arg == NULL) {
46003 /* '%p' and NULL is portable, but special case it
46004 * anyway to get a standard NULL marker in logs.
46005 */
46006 duk_fb_sprintf(&fb, "NULL");
46007 } else {
46008 duk_fb_sprintf(&fb, fmtbuf, arg);
46009 }
46010 } else if (ch == DUK_ASC_LC_C) {
46011 /* '%c', passed concretely as int */
46012 int arg = va_arg(ap, int);
46013 duk_fb_sprintf(&fb, fmtbuf, arg);
46014 } else {
46015 /* Should not happen. */
46016 duk_fb_sprintf(&fb, "INVALID-FORMAT(%s)", (const char *) fmtbuf);
46017 }
46018 break;
46019 } else {
46020 /* ignore */
46021 }
46022 }
46023 }
46024 goto done;
46025
46026format_error:
46027 duk_fb_put_cstring(&fb, "FMTERR");
46028 /* fall through */
46029
46030done:
46031 retval = (duk_int_t) fb.offset;
46032 duk_fb_put_byte(&fb, (duk_uint8_t) 0);
46033
46034 /* return total chars written excluding terminator */
46035 return retval;
46036}
46037
46038#if 0 /*unused*/
46039DUK_INTERNAL duk_int_t duk_debug_snprintf(char *str, duk_size_t size, const char *format, ...) {
46040 duk_int_t retval;
46041 va_list ap;
46042 va_start(ap, format);
46043 retval = duk_debug_vsnprintf(str, size, format, ap);
46044 va_end(ap);
46045 return retval;
46046}
46047#endif
46048
46049/* Formatting function pointers is tricky: there is no standard pointer for
46050 * function pointers and the size of a function pointer may depend on the
46051 * specific pointer type. This helper formats a function pointer based on
46052 * its memory layout to get something useful on most platforms.
46053 */
46054DUK_INTERNAL void duk_debug_format_funcptr(char *buf, duk_size_t buf_size, duk_uint8_t *fptr, duk_size_t fptr_size) {
46055 duk_size_t i;
46056 duk_uint8_t *p = (duk_uint8_t *) buf;
46057 duk_uint8_t *p_end = (duk_uint8_t *) (buf + buf_size - 1);
46058
46059 DUK_ASSERT(buf != NULL);
46060 duk_memzero(buf, buf_size);
46061
46062 for (i = 0; i < fptr_size; i++) {
46063 duk_int_t left = (duk_int_t) (p_end - p);
46064 duk_uint8_t ch;
46065 if (left <= 0) {
46066 break;
46067 }
46068
46069 /* Quite approximate but should be useful for little and big endian. */
46070#if defined(DUK_USE_INTEGER_BE)
46071 ch = fptr[i];
46072#else
46073 ch = fptr[fptr_size - 1 - i];
46074#endif
46075 p += DUK_SNPRINTF((char *) p, (duk_size_t) left, "%02lx", (unsigned long) ch);
46076 }
46077}
46078
46079#endif /* DUK_USE_DEBUG */
46080
46081/* automatic undefs */
46082#undef DUK__ALLOWED_STANDARD_SPECIFIERS
46083#undef DUK__COMMA
46084#undef DUK__DEEP_DEPTH_LIMIT
46085#undef DUK__LOOP_STACK_DEPTH
46086#undef DUK__MAX_FORMAT_TAG_LENGTH
46087/*
46088 * Duktape debugger
46089 */
46090
46091/* #include duk_internal.h -> already included */
46092
46093#if defined(DUK_USE_DEBUGGER_SUPPORT)
46094
46095/*
46096 * Assert helpers
46097 */
46098
46099#if defined(DUK_USE_ASSERTIONS)
46100#define DUK__DBG_TPORT_ENTER() \
46101 do { \
46102 DUK_ASSERT(heap->dbg_calling_transport == 0); \
46103 heap->dbg_calling_transport = 1; \
46104 } while (0)
46105#define DUK__DBG_TPORT_EXIT() \
46106 do { \
46107 DUK_ASSERT(heap->dbg_calling_transport == 1); \
46108 heap->dbg_calling_transport = 0; \
46109 } while (0)
46110#else
46111#define DUK__DBG_TPORT_ENTER() \
46112 do { \
46113 } while (0)
46114#define DUK__DBG_TPORT_EXIT() \
46115 do { \
46116 } while (0)
46117#endif
46118
46119/*
46120 * Helper structs
46121 */
46122
46123typedef union {
46124 void *p;
46125 duk_uint_t b[1];
46126 /* Use b[] to access the size of the union, which is strictly not
46127 * correct. Can't use fixed size unless there's feature detection
46128 * for pointer byte size.
46129 */
46130} duk__ptr_union;
46131
46132/*
46133 * Detach handling
46134 */
46135
46136#define DUK__SET_CONN_BROKEN(thr, reason) \
46137 do { \
46138 /* For now shared handler is fine. */ \
46139 duk__debug_do_detach1((thr)->heap, (reason)); \
46140 } while (0)
46141
46142DUK_LOCAL void duk__debug_do_detach1(duk_heap *heap, duk_int_t reason) {
46143 /* Can be called multiple times with no harm. Mark the transport
46144 * bad (dbg_read_cb == NULL) and clear state except for the detached
46145 * callback and the udata field. The detached callback is delayed
46146 * to the message loop so that it can be called between messages;
46147 * this avoids corner cases related to immediate debugger reattach
46148 * inside the detached callback.
46149 */
46150
46151 if (heap->dbg_detaching) {
46152 DUK_D(DUK_DPRINT("debugger already detaching, ignore detach1"));
46153 return;
46154 }
46155
46156 DUK_D(DUK_DPRINT("debugger transport detaching, marking transport broken"));
46157
46158 heap->dbg_detaching = 1; /* prevent multiple in-progress detaches */
46159
46160 if (heap->dbg_write_cb != NULL) {
46161 duk_hthread *thr;
46162
46163 thr = heap->heap_thread;
46164 DUK_ASSERT(thr != NULL);
46165
46166 duk_debug_write_notify(thr, DUK_DBG_CMD_DETACHING);
46167 duk_debug_write_int(thr, reason);
46168 duk_debug_write_eom(thr);
46169 }
46170
46171 heap->dbg_read_cb = NULL;
46172 heap->dbg_write_cb = NULL;
46173 heap->dbg_peek_cb = NULL;
46174 heap->dbg_read_flush_cb = NULL;
46175 heap->dbg_write_flush_cb = NULL;
46176 heap->dbg_request_cb = NULL;
46177 /* heap->dbg_detached_cb: keep */
46178 /* heap->dbg_udata: keep */
46179 /* heap->dbg_processing: keep on purpose to avoid debugger re-entry in detaching state */
46180 heap->dbg_state_dirty = 0;
46181 heap->dbg_force_restart = 0;
46182 heap->dbg_pause_flags = 0;
46183 heap->dbg_pause_act = NULL;
46184 heap->dbg_pause_startline = 0;
46185 heap->dbg_have_next_byte = 0;
46186 duk_debug_clear_paused(heap); /* XXX: some overlap with field inits above */
46187 heap->dbg_state_dirty = 0; /* XXX: clear_paused sets dirty; rework? */
46188
46189 /* Ensure there are no stale active breakpoint pointers.
46190 * Breakpoint list is currently kept - we could empty it
46191 * here but we'd need to handle refcounts correctly, and
46192 * we'd need a 'thr' reference for that.
46193 *
46194 * XXX: clear breakpoint on either attach or detach?
46195 */
46196 heap->dbg_breakpoints_active[0] = (duk_breakpoint *) NULL;
46197}
46198
46199DUK_LOCAL void duk__debug_do_detach2(duk_heap *heap) {
46200 duk_debug_detached_function detached_cb;
46201 void *detached_udata;
46202 duk_hthread *thr;
46203
46204 thr = heap->heap_thread;
46205 if (thr == NULL) {
46206 DUK_ASSERT(heap->dbg_detached_cb == NULL);
46207 return;
46208 }
46209
46210 /* Safe to call multiple times. */
46211
46212 detached_cb = heap->dbg_detached_cb;
46213 detached_udata = heap->dbg_udata;
46214 heap->dbg_detached_cb = NULL;
46215 heap->dbg_udata = NULL;
46216
46217 if (detached_cb) {
46218 /* Careful here: state must be wiped before the call
46219 * so that we can cleanly handle a re-attach from
46220 * inside the callback.
46221 */
46222 DUK_D(DUK_DPRINT("detached during message loop, delayed call to detached_cb"));
46223 detached_cb(thr, detached_udata);
46224 }
46225
46226 heap->dbg_detaching = 0;
46227}
46228
46229DUK_INTERNAL void duk_debug_do_detach(duk_heap *heap) {
46230 duk__debug_do_detach1(heap, 0);
46231 duk__debug_do_detach2(heap);
46232}
46233
46234/* Called on a read/write error: NULL all callbacks except the detached
46235 * callback so that we never accidentally call them after a read/write
46236 * error has been indicated. This is especially important for the transport
46237 * I/O callbacks to fulfill guaranteed callback semantics.
46238 */
46239DUK_LOCAL void duk__debug_null_most_callbacks(duk_hthread *thr) {
46240 duk_heap *heap;
46241
46242 DUK_ASSERT(thr != NULL);
46243
46244 heap = thr->heap;
46245 DUK_D(DUK_DPRINT("transport read/write error, NULL all callbacks expected detached"));
46246 heap->dbg_read_cb = NULL;
46247 heap->dbg_write_cb = NULL; /* this is especially critical to avoid another write call in detach1() */
46248 heap->dbg_peek_cb = NULL;
46249 heap->dbg_read_flush_cb = NULL;
46250 heap->dbg_write_flush_cb = NULL;
46251 heap->dbg_request_cb = NULL;
46252 /* keep heap->dbg_detached_cb */
46253}
46254
46255/*
46256 * Pause handling
46257 */
46258
46259DUK_LOCAL void duk__debug_set_pause_state(duk_hthread *thr, duk_heap *heap, duk_small_uint_t pause_flags) {
46261
46262 line = duk_debug_curr_line(thr);
46263 if (line == 0) {
46264 /* No line info for current function. */
46265 duk_small_uint_t updated_flags;
46266
46267 updated_flags = pause_flags & ~(DUK_PAUSE_FLAG_LINE_CHANGE);
46268 DUK_D(DUK_DPRINT("no line info for current activation, disable line-based pause flags: 0x%08lx -> 0x%08lx",
46269 (long) pause_flags,
46270 (long) updated_flags));
46271 pause_flags = updated_flags;
46272 }
46273
46274 heap->dbg_pause_flags = pause_flags;
46275 heap->dbg_pause_act = thr->callstack_curr;
46276 heap->dbg_pause_startline = (duk_uint32_t) line;
46277 heap->dbg_state_dirty = 1;
46278
46279 DUK_D(DUK_DPRINT("set state for automatic pause triggers, flags=0x%08lx, act=%p, startline=%ld",
46280 (long) heap->dbg_pause_flags,
46281 (void *) heap->dbg_pause_act,
46282 (long) heap->dbg_pause_startline));
46283}
46284
46285/*
46286 * Debug connection peek and flush primitives
46287 */
46288
46289DUK_INTERNAL duk_bool_t duk_debug_read_peek(duk_hthread *thr) {
46290 duk_heap *heap;
46291 duk_bool_t ret;
46292
46293 DUK_ASSERT(thr != NULL);
46294 heap = thr->heap;
46295 DUK_ASSERT(heap != NULL);
46296
46297 if (heap->dbg_read_cb == NULL) {
46298 DUK_D(DUK_DPRINT("attempt to peek in detached state, return zero (= no data)"));
46299 return 0;
46300 }
46301 if (heap->dbg_peek_cb == NULL) {
46302 DUK_DD(DUK_DDPRINT("no peek callback, return zero (= no data)"));
46303 return 0;
46304 }
46305
46306 DUK__DBG_TPORT_ENTER();
46307 ret = (duk_bool_t) (heap->dbg_peek_cb(heap->dbg_udata) > 0);
46308 DUK__DBG_TPORT_EXIT();
46309 return ret;
46310}
46311
46312DUK_INTERNAL void duk_debug_read_flush(duk_hthread *thr) {
46313 duk_heap *heap;
46314
46315 DUK_ASSERT(thr != NULL);
46316 heap = thr->heap;
46317 DUK_ASSERT(heap != NULL);
46318
46319 if (heap->dbg_read_cb == NULL) {
46320 DUK_D(DUK_DPRINT("attempt to read flush in detached state, ignore"));
46321 return;
46322 }
46323 if (heap->dbg_read_flush_cb == NULL) {
46324 DUK_DD(DUK_DDPRINT("no read flush callback, ignore"));
46325 return;
46326 }
46327
46328 DUK__DBG_TPORT_ENTER();
46329 heap->dbg_read_flush_cb(heap->dbg_udata);
46330 DUK__DBG_TPORT_EXIT();
46331}
46332
46333DUK_INTERNAL void duk_debug_write_flush(duk_hthread *thr) {
46334 duk_heap *heap;
46335
46336 DUK_ASSERT(thr != NULL);
46337 heap = thr->heap;
46338 DUK_ASSERT(heap != NULL);
46339
46340 if (heap->dbg_read_cb == NULL) {
46341 DUK_D(DUK_DPRINT("attempt to write flush in detached state, ignore"));
46342 return;
46343 }
46344 if (heap->dbg_write_flush_cb == NULL) {
46345 DUK_DD(DUK_DDPRINT("no write flush callback, ignore"));
46346 return;
46347 }
46348
46349 DUK__DBG_TPORT_ENTER();
46350 heap->dbg_write_flush_cb(heap->dbg_udata);
46351 DUK__DBG_TPORT_EXIT();
46352}
46353
46354/*
46355 * Debug connection skip primitives
46356 */
46357
46358/* Skip fully. */
46359DUK_INTERNAL void duk_debug_skip_bytes(duk_hthread *thr, duk_size_t length) {
46360 duk_uint8_t dummy[64];
46361 duk_size_t now;
46362
46363 DUK_ASSERT(thr != NULL);
46364
46365 while (length > 0) {
46366 now = (length > sizeof(dummy) ? sizeof(dummy) : length);
46367 duk_debug_read_bytes(thr, dummy, now);
46368 length -= now;
46369 }
46370}
46371
46372DUK_INTERNAL void duk_debug_skip_byte(duk_hthread *thr) {
46373 DUK_ASSERT(thr != NULL);
46374
46375 (void) duk_debug_read_byte(thr);
46376}
46377
46378/*
46379 * Debug connection read primitives
46380 */
46381
46382/* Peek ahead in the stream one byte. */
46383DUK_INTERNAL uint8_t duk_debug_peek_byte(duk_hthread *thr) {
46384 /* It is important not to call this if the last byte read was an EOM.
46385 * Reading ahead in this scenario would cause unnecessary blocking if
46386 * another message is not available.
46387 */
46388
46389 duk_uint8_t x;
46390
46391 x = duk_debug_read_byte(thr);
46392 thr->heap->dbg_have_next_byte = 1;
46393 thr->heap->dbg_next_byte = x;
46394 return x;
46395}
46396
46397/* Read fully. */
46398DUK_INTERNAL void duk_debug_read_bytes(duk_hthread *thr, duk_uint8_t *data, duk_size_t length) {
46399 duk_heap *heap;
46400 duk_uint8_t *p;
46401 duk_size_t left;
46402 duk_size_t got;
46403
46404 DUK_ASSERT(thr != NULL);
46405 heap = thr->heap;
46406 DUK_ASSERT(heap != NULL);
46407 DUK_ASSERT(data != NULL);
46408
46409 if (heap->dbg_read_cb == NULL) {
46410 DUK_D(DUK_DPRINT("attempt to read %ld bytes in detached state, return zero data", (long) length));
46411 goto fail;
46412 }
46413
46414 /* NOTE: length may be zero */
46415 p = data;
46416 if (length >= 1 && heap->dbg_have_next_byte) {
46417 heap->dbg_have_next_byte = 0;
46418 *p++ = heap->dbg_next_byte;
46419 }
46420 for (;;) {
46421 left = (duk_size_t) ((data + length) - p);
46422 if (left == 0) {
46423 break;
46424 }
46425 DUK_ASSERT(heap->dbg_read_cb != NULL);
46426 DUK_ASSERT(left >= 1);
46427#if defined(DUK_USE_DEBUGGER_TRANSPORT_TORTURE)
46428 left = 1;
46429#endif
46430 DUK__DBG_TPORT_ENTER();
46431 got = heap->dbg_read_cb(heap->dbg_udata, (char *) p, left);
46432 DUK__DBG_TPORT_EXIT();
46433
46434 if (got == 0 || got > left) {
46435 DUK_D(DUK_DPRINT("connection error during read, return zero data"));
46436 duk__debug_null_most_callbacks(thr); /* avoid calling write callback in detach1() */
46437 DUK__SET_CONN_BROKEN(thr, 1);
46438 goto fail;
46439 }
46440 p += got;
46441 }
46442 return;
46443
46444fail:
46445 duk_memzero((void *) data, (size_t) length);
46446}
46447
46448DUK_INTERNAL duk_uint8_t duk_debug_read_byte(duk_hthread *thr) {
46449 duk_uint8_t x;
46450
46451 x = 0; /* just in case callback is broken and won't write 'x' */
46452 duk_debug_read_bytes(thr, &x, 1);
46453 return x;
46454}
46455
46456DUK_LOCAL duk_uint32_t duk__debug_read_uint32_raw(duk_hthread *thr) {
46457 duk_uint8_t buf[4];
46458
46459 DUK_ASSERT(thr != NULL);
46460
46461 duk_debug_read_bytes(thr, buf, 4);
46462 return ((duk_uint32_t) buf[0] << 24) | ((duk_uint32_t) buf[1] << 16) | ((duk_uint32_t) buf[2] << 8) | (duk_uint32_t) buf[3];
46463}
46464
46465DUK_LOCAL duk_int32_t duk__debug_read_int32_raw(duk_hthread *thr) {
46466 return (duk_int32_t) duk__debug_read_uint32_raw(thr);
46467}
46468
46469DUK_LOCAL duk_uint16_t duk__debug_read_uint16_raw(duk_hthread *thr) {
46470 duk_uint8_t buf[2];
46471
46472 DUK_ASSERT(thr != NULL);
46473
46474 duk_debug_read_bytes(thr, buf, 2);
46475 return ((duk_uint16_t) buf[0] << 8) | (duk_uint16_t) buf[1];
46476}
46477
46478DUK_INTERNAL duk_int32_t duk_debug_read_int(duk_hthread *thr) {
46481
46482 DUK_ASSERT(thr != NULL);
46483
46484 x = duk_debug_read_byte(thr);
46485 if (x >= 0xc0) {
46486 t = duk_debug_read_byte(thr);
46487 return (duk_int32_t) (((x - 0xc0) << 8) + t);
46488 } else if (x >= 0x80) {
46489 return (duk_int32_t) (x - 0x80);
46490 } else if (x == DUK_DBG_IB_INT4) {
46491 return (duk_int32_t) duk__debug_read_uint32_raw(thr);
46492 }
46493
46494 DUK_D(DUK_DPRINT("debug connection error: failed to decode int"));
46495 DUK__SET_CONN_BROKEN(thr, 1);
46496 return 0;
46497}
46498
46499DUK_LOCAL duk_hstring *duk__debug_read_hstring_raw(duk_hthread *thr, duk_uint32_t len) {
46500 duk_uint8_t buf[31];
46501 duk_uint8_t *p;
46502
46503 if (len <= sizeof(buf)) {
46504 duk_debug_read_bytes(thr, buf, (duk_size_t) len);
46505 duk_push_lstring(thr, (const char *) buf, (duk_size_t) len);
46506 } else {
46507 p = (duk_uint8_t *) duk_push_fixed_buffer(thr, (duk_size_t) len); /* zero for paranoia */
46508 DUK_ASSERT(p != NULL);
46509 duk_debug_read_bytes(thr, p, (duk_size_t) len);
46510 (void) duk_buffer_to_string(thr, -1); /* Safety relies on debug client, which is OK. */
46511 }
46512
46513 return duk_require_hstring(thr, -1);
46514}
46515
46516DUK_INTERNAL duk_hstring *duk_debug_read_hstring(duk_hthread *thr) {
46518 duk_uint32_t len;
46519
46520 DUK_ASSERT(thr != NULL);
46521
46522 x = duk_debug_read_byte(thr);
46523 if (x >= 0x60 && x <= 0x7f) {
46524 /* For short strings, use a fixed temp buffer. */
46525 len = (duk_uint32_t) (x - 0x60);
46526 } else if (x == DUK_DBG_IB_STR2) {
46527 len = (duk_uint32_t) duk__debug_read_uint16_raw(thr);
46528 } else if (x == DUK_DBG_IB_STR4) {
46529 len = (duk_uint32_t) duk__debug_read_uint32_raw(thr);
46530 } else {
46531 goto fail;
46532 }
46533
46534 return duk__debug_read_hstring_raw(thr, len);
46535
46536fail:
46537 DUK_D(DUK_DPRINT("debug connection error: failed to decode int"));
46538 DUK__SET_CONN_BROKEN(thr, 1);
46539 duk_push_hstring_empty(thr); /* always push some string */
46540 return duk_require_hstring(thr, -1);
46541}
46542
46543DUK_LOCAL duk_hbuffer *duk__debug_read_hbuffer_raw(duk_hthread *thr, duk_uint32_t len) {
46544 duk_uint8_t *p;
46545
46546 p = (duk_uint8_t *) duk_push_fixed_buffer(thr, (duk_size_t) len); /* zero for paranoia */
46547 DUK_ASSERT(p != NULL);
46548 duk_debug_read_bytes(thr, p, (duk_size_t) len);
46549
46550 return duk_require_hbuffer(thr, -1);
46551}
46552
46553DUK_LOCAL void *duk__debug_read_pointer_raw(duk_hthread *thr) {
46555 duk__ptr_union pu;
46556
46557 DUK_ASSERT(thr != NULL);
46558
46559 x = duk_debug_read_byte(thr);
46560 if (x != sizeof(pu)) {
46561 goto fail;
46562 }
46563 duk_debug_read_bytes(thr, (duk_uint8_t *) &pu.p, sizeof(pu));
46564#if defined(DUK_USE_INTEGER_LE)
46565 duk_byteswap_bytes((duk_uint8_t *) pu.b, sizeof(pu));
46566#endif
46567 return (void *) pu.p;
46568
46569fail:
46570 DUK_D(DUK_DPRINT("debug connection error: failed to decode pointer"));
46571 DUK__SET_CONN_BROKEN(thr, 1);
46572 return (void *) NULL;
46573}
46574
46575DUK_LOCAL duk_double_t duk__debug_read_double_raw(duk_hthread *thr) {
46577
46578 DUK_ASSERT(sizeof(du.uc) == 8);
46579 duk_debug_read_bytes(thr, (duk_uint8_t *) du.uc, sizeof(du.uc));
46581 return du.d;
46582}
46583
46584#if 0
46585DUK_INTERNAL duk_heaphdr *duk_debug_read_heapptr(duk_hthread *thr) {
46587
46588 DUK_ASSERT(thr != NULL);
46589
46590 x = duk_debug_read_byte(thr);
46591 if (x != DUK_DBG_IB_HEAPPTR) {
46592 goto fail;
46593 }
46594
46595 return (duk_heaphdr *) duk__debug_read_pointer_raw(thr);
46596
46597 fail:
46598 DUK_D(DUK_DPRINT("debug connection error: failed to decode heapptr"));
46599 DUK__SET_CONN_BROKEN(thr, 1);
46600 return NULL;
46601}
46602#endif
46603
46604DUK_INTERNAL duk_heaphdr *duk_debug_read_any_ptr(duk_hthread *thr) {
46606
46607 DUK_ASSERT(thr != NULL);
46608
46609 x = duk_debug_read_byte(thr);
46610 switch (x) {
46611 case DUK_DBG_IB_OBJECT:
46612 case DUK_DBG_IB_POINTER:
46613 case DUK_DBG_IB_HEAPPTR:
46614 /* Accept any pointer-like value; for 'object' dvalue, read
46615 * and ignore the class number.
46616 */
46617 if (x == DUK_DBG_IB_OBJECT) {
46618 duk_debug_skip_byte(thr);
46619 }
46620 break;
46621 default:
46622 goto fail;
46623 }
46624
46625 return (duk_heaphdr *) duk__debug_read_pointer_raw(thr);
46626
46627fail:
46628 DUK_D(DUK_DPRINT("debug connection error: failed to decode any pointer (object, pointer, heapptr)"));
46629 DUK__SET_CONN_BROKEN(thr, 1);
46630 return NULL;
46631}
46632
46633DUK_INTERNAL duk_tval *duk_debug_read_tval(duk_hthread *thr) {
46634 duk_uint8_t x;
46635 duk_uint_t t;
46636 duk_uint32_t len;
46637
46638 DUK_ASSERT(thr != NULL);
46639
46640 x = duk_debug_read_byte(thr);
46641
46642 if (x >= 0xc0) {
46643 t = (duk_uint_t) (x - 0xc0);
46644 t = (t << 8) + duk_debug_read_byte(thr);
46645 duk_push_uint(thr, (duk_uint_t) t);
46646 goto return_ptr;
46647 }
46648 if (x >= 0x80) {
46649 duk_push_uint(thr, (duk_uint_t) (x - 0x80));
46650 goto return_ptr;
46651 }
46652 if (x >= 0x60) {
46653 len = (duk_uint32_t) (x - 0x60);
46654 duk__debug_read_hstring_raw(thr, len);
46655 goto return_ptr;
46656 }
46657
46658 switch (x) {
46659 case DUK_DBG_IB_INT4: {
46660 duk_int32_t i = duk__debug_read_int32_raw(thr);
46661 duk_push_i32(thr, i);
46662 break;
46663 }
46664 case DUK_DBG_IB_STR4: {
46665 len = duk__debug_read_uint32_raw(thr);
46666 duk__debug_read_hstring_raw(thr, len);
46667 break;
46668 }
46669 case DUK_DBG_IB_STR2: {
46670 len = duk__debug_read_uint16_raw(thr);
46671 duk__debug_read_hstring_raw(thr, len);
46672 break;
46673 }
46674 case DUK_DBG_IB_BUF4: {
46675 len = duk__debug_read_uint32_raw(thr);
46676 duk__debug_read_hbuffer_raw(thr, len);
46677 break;
46678 }
46679 case DUK_DBG_IB_BUF2: {
46680 len = duk__debug_read_uint16_raw(thr);
46681 duk__debug_read_hbuffer_raw(thr, len);
46682 break;
46683 }
46684 case DUK_DBG_IB_UNDEFINED: {
46685 duk_push_undefined(thr);
46686 break;
46687 }
46688 case DUK_DBG_IB_NULL: {
46689 duk_push_null(thr);
46690 break;
46691 }
46692 case DUK_DBG_IB_TRUE: {
46693 duk_push_true(thr);
46694 break;
46695 }
46696 case DUK_DBG_IB_FALSE: {
46697 duk_push_false(thr);
46698 break;
46699 }
46700 case DUK_DBG_IB_NUMBER: {
46701 duk_double_t d;
46702 d = duk__debug_read_double_raw(thr);
46703 duk_push_number(thr, d);
46704 break;
46705 }
46706 case DUK_DBG_IB_OBJECT: {
46707 duk_heaphdr *h;
46708 duk_debug_skip_byte(thr);
46709 h = (duk_heaphdr *) duk__debug_read_pointer_raw(thr);
46710 duk_push_heapptr(thr, (void *) h);
46711 break;
46712 }
46713 case DUK_DBG_IB_POINTER: {
46714 void *ptr;
46715 ptr = duk__debug_read_pointer_raw(thr);
46716 duk_push_pointer(thr, ptr);
46717 break;
46718 }
46719 case DUK_DBG_IB_LIGHTFUNC: {
46720 /* XXX: Not needed for now, so not implemented. Note that
46721 * function pointers may have different size/layout than
46722 * a void pointer.
46723 */
46724 DUK_D(DUK_DPRINT("reading lightfunc values unimplemented"));
46725 goto fail;
46726 }
46727 case DUK_DBG_IB_HEAPPTR: {
46728 duk_heaphdr *h;
46729 h = (duk_heaphdr *) duk__debug_read_pointer_raw(thr);
46730 duk_push_heapptr(thr, (void *) h);
46731 break;
46732 }
46733 case DUK_DBG_IB_UNUSED: /* unused: not accepted in inbound messages */
46734 default:
46735 goto fail;
46736 }
46737
46738return_ptr:
46739 return DUK_GET_TVAL_NEGIDX(thr, -1);
46740
46741fail:
46742 DUK_D(DUK_DPRINT("debug connection error: failed to decode tval"));
46743 DUK__SET_CONN_BROKEN(thr, 1);
46744 return NULL;
46745}
46746
46747/*
46748 * Debug connection write primitives
46749 */
46750
46751/* Write fully. */
46752DUK_INTERNAL void duk_debug_write_bytes(duk_hthread *thr, const duk_uint8_t *data, duk_size_t length) {
46753 duk_heap *heap;
46754 const duk_uint8_t *p;
46755 duk_size_t left;
46756 duk_size_t got;
46757
46758 DUK_ASSERT(thr != NULL);
46759 DUK_ASSERT(length == 0 || data != NULL);
46760 heap = thr->heap;
46761 DUK_ASSERT(heap != NULL);
46762
46763 if (heap->dbg_write_cb == NULL) {
46764 DUK_D(DUK_DPRINT("attempt to write %ld bytes in detached state, ignore", (long) length));
46765 return;
46766 }
46767 if (length == 0) {
46768 /* Avoid doing an actual write callback with length == 0,
46769 * because that's reserved for a write flush.
46770 */
46771 return;
46772 }
46773 DUK_ASSERT(data != NULL);
46774
46775 p = data;
46776 for (;;) {
46777 left = (duk_size_t) ((data + length) - p);
46778 if (left == 0) {
46779 break;
46780 }
46781 DUK_ASSERT(heap->dbg_write_cb != NULL);
46782 DUK_ASSERT(left >= 1);
46783#if defined(DUK_USE_DEBUGGER_TRANSPORT_TORTURE)
46784 left = 1;
46785#endif
46786 DUK__DBG_TPORT_ENTER();
46787 got = heap->dbg_write_cb(heap->dbg_udata, (const char *) p, left);
46788 DUK__DBG_TPORT_EXIT();
46789
46790 if (got == 0 || got > left) {
46791 duk__debug_null_most_callbacks(thr); /* avoid calling write callback in detach1() */
46792 DUK_D(DUK_DPRINT("connection error during write"));
46793 DUK__SET_CONN_BROKEN(thr, 1);
46794 return;
46795 }
46796 p += got;
46797 }
46798}
46799
46800DUK_INTERNAL void duk_debug_write_byte(duk_hthread *thr, duk_uint8_t x) {
46801 duk_debug_write_bytes(thr, (const duk_uint8_t *) &x, 1);
46802}
46803
46804DUK_INTERNAL void duk_debug_write_unused(duk_hthread *thr) {
46805 duk_debug_write_byte(thr, DUK_DBG_IB_UNUSED);
46806}
46807
46808DUK_INTERNAL void duk_debug_write_undefined(duk_hthread *thr) {
46809 duk_debug_write_byte(thr, DUK_DBG_IB_UNDEFINED);
46810}
46811
46812#if defined(DUK_USE_DEBUGGER_INSPECT)
46813DUK_INTERNAL void duk_debug_write_null(duk_hthread *thr) {
46814 duk_debug_write_byte(thr, DUK_DBG_IB_NULL);
46815}
46816#endif
46817
46818DUK_INTERNAL void duk_debug_write_boolean(duk_hthread *thr, duk_uint_t val) {
46819 duk_debug_write_byte(thr, val ? DUK_DBG_IB_TRUE : DUK_DBG_IB_FALSE);
46820}
46821
46822/* Write signed 32-bit integer. */
46823DUK_INTERNAL void duk_debug_write_int(duk_hthread *thr, duk_int32_t x) {
46824 duk_uint8_t buf[5];
46825 duk_size_t len;
46826
46827 DUK_ASSERT(thr != NULL);
46828
46829 if (x >= 0 && x <= 0x3fL) {
46830 buf[0] = (duk_uint8_t) (0x80 + x);
46831 len = 1;
46832 } else if (x >= 0 && x <= 0x3fffL) {
46833 buf[0] = (duk_uint8_t) (0xc0 + (x >> 8));
46834 buf[1] = (duk_uint8_t) (x & 0xff);
46835 len = 2;
46836 } else {
46837 /* Signed integers always map to 4 bytes now. */
46838 buf[0] = (duk_uint8_t) DUK_DBG_IB_INT4;
46839 buf[1] = (duk_uint8_t) ((x >> 24) & 0xff);
46840 buf[2] = (duk_uint8_t) ((x >> 16) & 0xff);
46841 buf[3] = (duk_uint8_t) ((x >> 8) & 0xff);
46842 buf[4] = (duk_uint8_t) (x & 0xff);
46843 len = 5;
46844 }
46845 duk_debug_write_bytes(thr, buf, len);
46846}
46847
46848/* Write unsigned 32-bit integer. */
46849DUK_INTERNAL void duk_debug_write_uint(duk_hthread *thr, duk_uint32_t x) {
46850 /* The debugger protocol doesn't support a plain integer encoding for
46851 * the full 32-bit unsigned range (only 32-bit signed). For now,
46852 * unsigned 32-bit values simply written as signed ones. This is not
46853 * a concrete issue except for 32-bit heaphdr fields. Proper solutions
46854 * would be to (a) write such integers as IEEE doubles or (b) add an
46855 * unsigned 32-bit dvalue.
46856 */
46857 if (x >= 0x80000000UL) {
46858 DUK_D(DUK_DPRINT("writing unsigned integer 0x%08lx as signed integer", (long) x));
46859 }
46860 duk_debug_write_int(thr, (duk_int32_t) x);
46861}
46862
46863DUK_INTERNAL void duk_debug_write_strbuf(duk_hthread *thr, const char *data, duk_size_t length, duk_uint8_t marker_base) {
46864 duk_uint8_t buf[5];
46865 duk_size_t buflen;
46866
46867 DUK_ASSERT(thr != NULL);
46868 DUK_ASSERT(length == 0 || data != NULL);
46869
46870 if (length <= 0x1fUL && marker_base == DUK_DBG_IB_STR4) {
46871 /* For strings, special form for short lengths. */
46872 buf[0] = (duk_uint8_t) (0x60 + length);
46873 buflen = 1;
46874 } else if (length <= 0xffffUL) {
46875 buf[0] = (duk_uint8_t) (marker_base + 1);
46876 buf[1] = (duk_uint8_t) (length >> 8);
46877 buf[2] = (duk_uint8_t) (length & 0xff);
46878 buflen = 3;
46879 } else {
46880 buf[0] = (duk_uint8_t) marker_base;
46881 buf[1] = (duk_uint8_t) (length >> 24);
46882 buf[2] = (duk_uint8_t) ((length >> 16) & 0xff);
46883 buf[3] = (duk_uint8_t) ((length >> 8) & 0xff);
46884 buf[4] = (duk_uint8_t) (length & 0xff);
46885 buflen = 5;
46886 }
46887
46888 duk_debug_write_bytes(thr, (const duk_uint8_t *) buf, buflen);
46889 duk_debug_write_bytes(thr, (const duk_uint8_t *) data, length);
46890}
46891
46892DUK_INTERNAL void duk_debug_write_string(duk_hthread *thr, const char *data, duk_size_t length) {
46893 duk_debug_write_strbuf(thr, data, length, DUK_DBG_IB_STR4);
46894}
46895
46896DUK_INTERNAL void duk_debug_write_cstring(duk_hthread *thr, const char *data) {
46897 DUK_ASSERT(thr != NULL);
46898
46899 duk_debug_write_string(thr, data, data ? DUK_STRLEN(data) : 0);
46900}
46901
46902DUK_INTERNAL void duk_debug_write_hstring(duk_hthread *thr, duk_hstring *h) {
46903 DUK_ASSERT(thr != NULL);
46904
46905 /* XXX: differentiate null pointer from empty string? */
46906 duk_debug_write_string(thr,
46907 (h != NULL ? (const char *) DUK_HSTRING_GET_DATA(h) : NULL),
46908 (h != NULL ? (duk_size_t) DUK_HSTRING_GET_BYTELEN(h) : 0));
46909}
46910
46911DUK_LOCAL void duk__debug_write_hstring_safe_top(duk_hthread *thr) {
46912 duk_debug_write_hstring(thr, duk_safe_to_hstring(thr, -1));
46913}
46914
46915DUK_INTERNAL void duk_debug_write_buffer(duk_hthread *thr, const char *data, duk_size_t length) {
46916 duk_debug_write_strbuf(thr, data, length, DUK_DBG_IB_BUF4);
46917}
46918
46919DUK_INTERNAL void duk_debug_write_hbuffer(duk_hthread *thr, duk_hbuffer *h) {
46920 DUK_ASSERT(thr != NULL);
46921
46922 duk_debug_write_buffer(thr,
46923 (h != NULL ? (const char *) DUK_HBUFFER_GET_DATA_PTR(thr->heap, h) : NULL),
46924 (h != NULL ? (duk_size_t) DUK_HBUFFER_GET_SIZE(h) : 0));
46925}
46926
46927DUK_LOCAL void duk__debug_write_pointer_raw(duk_hthread *thr, void *ptr, duk_uint8_t ibyte) {
46928 duk_uint8_t buf[2];
46929 duk__ptr_union pu;
46930
46931 DUK_ASSERT(thr != NULL);
46932 DUK_ASSERT(sizeof(ptr) >= 1 && sizeof(ptr) <= 16);
46933 /* ptr may be NULL */
46934
46935 buf[0] = ibyte;
46936 buf[1] = sizeof(pu);
46937 duk_debug_write_bytes(thr, buf, 2);
46938 pu.p = (void *) ptr;
46939#if defined(DUK_USE_INTEGER_LE)
46940 duk_byteswap_bytes((duk_uint8_t *) pu.b, sizeof(pu));
46941#endif
46942 duk_debug_write_bytes(thr, (const duk_uint8_t *) &pu.p, (duk_size_t) sizeof(pu));
46943}
46944
46945DUK_INTERNAL void duk_debug_write_pointer(duk_hthread *thr, void *ptr) {
46946 duk__debug_write_pointer_raw(thr, ptr, DUK_DBG_IB_POINTER);
46947}
46948
46949#if defined(DUK_USE_DEBUGGER_DUMPHEAP) || defined(DUK_USE_DEBUGGER_INSPECT)
46950DUK_INTERNAL void duk_debug_write_heapptr(duk_hthread *thr, duk_heaphdr *h) {
46951 duk__debug_write_pointer_raw(thr, (void *) h, DUK_DBG_IB_HEAPPTR);
46952}
46953#endif /* DUK_USE_DEBUGGER_DUMPHEAP || DUK_USE_DEBUGGER_INSPECT */
46954
46955DUK_INTERNAL void duk_debug_write_hobject(duk_hthread *thr, duk_hobject *obj) {
46956 duk_uint8_t buf[3];
46957 duk__ptr_union pu;
46958
46959 DUK_ASSERT(thr != NULL);
46960 DUK_ASSERT(sizeof(obj) >= 1 && sizeof(obj) <= 16);
46961 DUK_ASSERT(obj != NULL);
46962
46963 buf[0] = DUK_DBG_IB_OBJECT;
46964 buf[1] = (duk_uint8_t) DUK_HOBJECT_GET_CLASS_NUMBER(obj);
46965 buf[2] = sizeof(pu);
46966 duk_debug_write_bytes(thr, buf, 3);
46967 pu.p = (void *) obj;
46968#if defined(DUK_USE_INTEGER_LE)
46969 duk_byteswap_bytes((duk_uint8_t *) pu.b, sizeof(pu));
46970#endif
46971 duk_debug_write_bytes(thr, (const duk_uint8_t *) &pu.p, (duk_size_t) sizeof(pu));
46972}
46973
46974DUK_INTERNAL void duk_debug_write_tval(duk_hthread *thr, duk_tval *tv) {
46975 duk_c_function lf_func;
46976 duk_small_uint_t lf_flags;
46977 duk_uint8_t buf[4];
46978 duk_double_union du1;
46979 duk_double_union du2;
46980 duk_int32_t i32;
46981
46982 DUK_ASSERT(thr != NULL);
46983 DUK_ASSERT(tv != NULL);
46984
46985 switch (DUK_TVAL_GET_TAG(tv)) {
46986 case DUK_TAG_UNDEFINED:
46987 duk_debug_write_byte(thr, DUK_DBG_IB_UNDEFINED);
46988 break;
46989 case DUK_TAG_UNUSED:
46990 duk_debug_write_byte(thr, DUK_DBG_IB_UNUSED);
46991 break;
46992 case DUK_TAG_NULL:
46993 duk_debug_write_byte(thr, DUK_DBG_IB_NULL);
46994 break;
46995 case DUK_TAG_BOOLEAN:
46997 duk_debug_write_boolean(thr, DUK_TVAL_GET_BOOLEAN(tv));
46998 break;
46999 case DUK_TAG_POINTER:
47000 duk_debug_write_pointer(thr, (void *) DUK_TVAL_GET_POINTER(tv));
47001 break;
47002 case DUK_TAG_LIGHTFUNC:
47003 DUK_TVAL_GET_LIGHTFUNC(tv, lf_func, lf_flags);
47004 buf[0] = DUK_DBG_IB_LIGHTFUNC;
47005 buf[1] = (duk_uint8_t) (lf_flags >> 8);
47006 buf[2] = (duk_uint8_t) (lf_flags & 0xff);
47007 buf[3] = sizeof(lf_func);
47008 duk_debug_write_bytes(thr, buf, 4);
47009 duk_debug_write_bytes(thr, (const duk_uint8_t *) &lf_func, sizeof(lf_func));
47010 break;
47011 case DUK_TAG_STRING:
47012 duk_debug_write_hstring(thr, DUK_TVAL_GET_STRING(tv));
47013 break;
47014 case DUK_TAG_OBJECT:
47015 duk_debug_write_hobject(thr, DUK_TVAL_GET_OBJECT(tv));
47016 break;
47017 case DUK_TAG_BUFFER:
47018 duk_debug_write_hbuffer(thr, DUK_TVAL_GET_BUFFER(tv));
47019 break;
47020#if defined(DUK_USE_FASTINT)
47021 case DUK_TAG_FASTINT:
47022#endif
47023 default:
47024 /* Numbers are normalized to big (network) endian. We can
47025 * (but are not required) to use integer dvalues when there's
47026 * no loss of precision.
47027 *
47028 * XXX: share check with other code; this check is slow but
47029 * reliable and doesn't require careful exponent/mantissa
47030 * mask tricks as in the fastint downgrade code.
47031 */
47034 du1.d = DUK_TVAL_GET_NUMBER(tv);
47035 i32 = (duk_int32_t) du1.d;
47036 du2.d = (duk_double_t) i32;
47037
47038 DUK_DD(DUK_DDPRINT("i32=%ld du1=%02x%02x%02x%02x%02x%02x%02x%02x "
47039 "du2=%02x%02x%02x%02x%02x%02x%02x%02x",
47040 (long) i32,
47041 (unsigned int) du1.uc[0],
47042 (unsigned int) du1.uc[1],
47043 (unsigned int) du1.uc[2],
47044 (unsigned int) du1.uc[3],
47045 (unsigned int) du1.uc[4],
47046 (unsigned int) du1.uc[5],
47047 (unsigned int) du1.uc[6],
47048 (unsigned int) du1.uc[7],
47049 (unsigned int) du2.uc[0],
47050 (unsigned int) du2.uc[1],
47051 (unsigned int) du2.uc[2],
47052 (unsigned int) du2.uc[3],
47053 (unsigned int) du2.uc[4],
47054 (unsigned int) du2.uc[5],
47055 (unsigned int) du2.uc[6],
47056 (unsigned int) du2.uc[7]));
47057
47058 if (duk_memcmp((const void *) du1.uc, (const void *) du2.uc, sizeof(du1.uc)) == 0) {
47059 duk_debug_write_int(thr, i32);
47060 } else {
47061 DUK_DBLUNION_DOUBLE_HTON(&du1);
47062 duk_debug_write_byte(thr, DUK_DBG_IB_NUMBER);
47063 duk_debug_write_bytes(thr, (const duk_uint8_t *) du1.uc, sizeof(du1.uc));
47064 }
47065 }
47066}
47067
47068#if defined(DUK_USE_DEBUGGER_DUMPHEAP)
47069/* Variant for writing duk_tvals so that any heap allocated values are
47070 * written out as tagged heap pointers.
47071 */
47072DUK_LOCAL void duk__debug_write_tval_heapptr(duk_hthread *thr, duk_tval *tv) {
47075 duk_debug_write_heapptr(thr, h);
47076 } else {
47077 duk_debug_write_tval(thr, tv);
47078 }
47079}
47080#endif /* DUK_USE_DEBUGGER_DUMPHEAP */
47081
47082/*
47083 * Debug connection message write helpers
47084 */
47085
47086#if 0 /* unused */
47087DUK_INTERNAL void duk_debug_write_request(duk_hthread *thr, duk_small_uint_t command) {
47088 duk_debug_write_byte(thr, DUK_DBG_IB_REQUEST);
47089 duk_debug_write_int(thr, command);
47090}
47091#endif
47092
47093DUK_INTERNAL void duk_debug_write_reply(duk_hthread *thr) {
47094 duk_debug_write_byte(thr, DUK_DBG_IB_REPLY);
47095}
47096
47097DUK_INTERNAL void duk_debug_write_error_eom(duk_hthread *thr, duk_small_uint_t err_code, const char *msg) {
47098 /* Allow NULL 'msg' */
47099 duk_debug_write_byte(thr, DUK_DBG_IB_ERROR);
47100 duk_debug_write_int(thr, (duk_int32_t) err_code);
47101 duk_debug_write_cstring(thr, msg);
47102 duk_debug_write_eom(thr);
47103}
47104
47105DUK_INTERNAL void duk_debug_write_notify(duk_hthread *thr, duk_small_uint_t command) {
47106 duk_debug_write_byte(thr, DUK_DBG_IB_NOTIFY);
47107 duk_debug_write_int(thr, (duk_int32_t) command);
47108}
47109
47110DUK_INTERNAL void duk_debug_write_eom(duk_hthread *thr) {
47111 duk_debug_write_byte(thr, DUK_DBG_IB_EOM);
47112
47113 /* As an initial implementation, write flush after every EOM (and the
47114 * version identifier). A better implementation would flush only when
47115 * Duktape is finished processing messages so that a flush only happens
47116 * after all outbound messages are finished on that occasion.
47117 */
47118 duk_debug_write_flush(thr);
47119}
47120
47121/*
47122 * Status message and helpers
47123 */
47124
47125DUK_INTERNAL duk_uint_fast32_t duk_debug_curr_line(duk_hthread *thr) {
47126 duk_activation *act;
47129
47130 act = thr->callstack_curr;
47131 if (act == NULL) {
47132 return 0;
47133 }
47134
47135 /* We're conceptually between two opcodes; act->pc indicates the next
47136 * instruction to be executed. This is usually the correct pc/line to
47137 * indicate in Status. (For the 'debugger' statement this now reports
47138 * the pc/line after the debugger statement because the debugger opcode
47139 * has already been executed.)
47140 */
47141
47142 pc = duk_hthread_get_act_curr_pc(thr, act);
47143
47144 /* XXX: this should be optimized to be a raw query and avoid valstack
47145 * operations if possible.
47146 */
47147 duk_push_tval(thr, &act->tv_func);
47148 line = duk_hobject_pc2line_query(thr, -1, pc);
47149 duk_pop(thr);
47150 return line;
47151}
47152
47153DUK_INTERNAL void duk_debug_send_status(duk_hthread *thr) {
47154 duk_activation *act;
47155
47156 duk_debug_write_notify(thr, DUK_DBG_CMD_STATUS);
47157 duk_debug_write_int(thr, (DUK_HEAP_HAS_DEBUGGER_PAUSED(thr->heap) ? 1 : 0));
47158
47159 act = thr->callstack_curr;
47160 if (act == NULL) {
47161 duk_debug_write_undefined(thr);
47162 duk_debug_write_undefined(thr);
47163 duk_debug_write_int(thr, 0);
47164 duk_debug_write_int(thr, 0);
47165 } else {
47166 duk_push_tval(thr, &act->tv_func);
47167 duk_get_prop_literal(thr, -1, "fileName");
47168 duk__debug_write_hstring_safe_top(thr);
47169 duk_get_prop_literal(thr, -2, "name");
47170 duk__debug_write_hstring_safe_top(thr);
47171 duk_pop_3(thr);
47172 /* Report next pc/line to be executed. */
47173 duk_debug_write_uint(thr, (duk_uint32_t) duk_debug_curr_line(thr));
47174 duk_debug_write_uint(thr, (duk_uint32_t) duk_hthread_get_act_curr_pc(thr, act));
47175 }
47176
47177 duk_debug_write_eom(thr);
47178}
47179
47180#if defined(DUK_USE_DEBUGGER_THROW_NOTIFY)
47181DUK_INTERNAL void duk_debug_send_throw(duk_hthread *thr, duk_bool_t fatal) {
47182 /*
47183 * NFY <int: 5> <int: fatal> <str: msg> <str: filename> <int: linenumber> EOM
47184 */
47185
47186 duk_activation *act;
47187 duk_uint32_t pc;
47188
47189 DUK_ASSERT(thr->valstack_top > thr->valstack); /* At least: ... [err] */
47190
47191 duk_debug_write_notify(thr, DUK_DBG_CMD_THROW);
47192 duk_debug_write_int(thr, (duk_int32_t) fatal);
47193
47194 /* Report thrown value to client coerced to string */
47195 duk_dup_top(thr);
47196 duk__debug_write_hstring_safe_top(thr);
47197 duk_pop(thr);
47198
47199 if (duk_is_error(thr, -1)) {
47200 /* Error instance, use augmented error data directly */
47202 duk__debug_write_hstring_safe_top(thr);
47204 duk_debug_write_uint(thr, duk_get_uint(thr, -1));
47205 duk_pop_2(thr);
47206 } else {
47207 /* For anything other than an Error instance, we calculate the
47208 * error location directly from the current activation if one
47209 * exists.
47210 */
47211 act = thr->callstack_curr;
47212 if (act != NULL) {
47213 duk_push_tval(thr, &act->tv_func);
47214 duk_get_prop_literal(thr, -1, "fileName");
47215 duk__debug_write_hstring_safe_top(thr);
47216 pc = (duk_uint32_t) duk_hthread_get_act_prev_pc(thr, act);
47217 duk_debug_write_uint(thr, (duk_uint32_t) duk_hobject_pc2line_query(thr, -2, pc));
47218 duk_pop_2(thr);
47219 } else {
47220 /* Can happen if duk_throw() is called on an empty
47221 * callstack.
47222 */
47223 duk_debug_write_cstring(thr, "");
47224 duk_debug_write_uint(thr, 0);
47225 }
47226 }
47227
47228 duk_debug_write_eom(thr);
47229}
47230#endif /* DUK_USE_DEBUGGER_THROW_NOTIFY */
47231
47232/*
47233 * Debug message processing
47234 */
47235
47236/* Skip dvalue. */
47237DUK_LOCAL duk_bool_t duk__debug_skip_dvalue(duk_hthread *thr) {
47238 duk_uint8_t x;
47239 duk_uint32_t len;
47240
47241 x = duk_debug_read_byte(thr);
47242
47243 if (x >= 0xc0) {
47244 duk_debug_skip_byte(thr);
47245 return 0;
47246 }
47247 if (x >= 0x80) {
47248 return 0;
47249 }
47250 if (x >= 0x60) {
47251 duk_debug_skip_bytes(thr, (duk_size_t) (x - 0x60));
47252 return 0;
47253 }
47254 switch (x) {
47255 case DUK_DBG_IB_EOM:
47256 return 1; /* Return 1: got EOM */
47257 case DUK_DBG_IB_REQUEST:
47258 case DUK_DBG_IB_REPLY:
47259 case DUK_DBG_IB_ERROR:
47260 case DUK_DBG_IB_NOTIFY:
47261 break;
47262 case DUK_DBG_IB_INT4:
47263 (void) duk__debug_read_uint32_raw(thr);
47264 break;
47265 case DUK_DBG_IB_STR4:
47266 case DUK_DBG_IB_BUF4:
47267 len = duk__debug_read_uint32_raw(thr);
47268 duk_debug_skip_bytes(thr, len);
47269 break;
47270 case DUK_DBG_IB_STR2:
47271 case DUK_DBG_IB_BUF2:
47272 len = duk__debug_read_uint16_raw(thr);
47273 duk_debug_skip_bytes(thr, len);
47274 break;
47275 case DUK_DBG_IB_UNUSED:
47277 case DUK_DBG_IB_NULL:
47278 case DUK_DBG_IB_TRUE:
47279 case DUK_DBG_IB_FALSE:
47280 break;
47281 case DUK_DBG_IB_NUMBER:
47282 duk_debug_skip_bytes(thr, 8);
47283 break;
47284 case DUK_DBG_IB_OBJECT:
47285 duk_debug_skip_byte(thr);
47286 len = duk_debug_read_byte(thr);
47287 duk_debug_skip_bytes(thr, len);
47288 break;
47289 case DUK_DBG_IB_POINTER:
47290 case DUK_DBG_IB_HEAPPTR:
47291 len = duk_debug_read_byte(thr);
47292 duk_debug_skip_bytes(thr, len);
47293 break;
47295 duk_debug_skip_bytes(thr, 2);
47296 len = duk_debug_read_byte(thr);
47297 duk_debug_skip_bytes(thr, len);
47298 break;
47299 default:
47300 goto fail;
47301 }
47302
47303 return 0;
47304
47305fail:
47306 DUK__SET_CONN_BROKEN(thr, 1);
47307 return 1; /* Pretend like we got EOM */
47308}
47309
47310/* Skip dvalues to EOM. */
47311DUK_LOCAL void duk__debug_skip_to_eom(duk_hthread *thr) {
47312 for (;;) {
47313 if (duk__debug_skip_dvalue(thr)) {
47314 break;
47315 }
47316 }
47317}
47318
47319/* Read and validate a call stack index. If index is invalid, write out an
47320 * error message and return zero.
47321 */
47322DUK_LOCAL duk_int32_t duk__debug_read_validate_csindex(duk_hthread *thr) {
47323 duk_int32_t level;
47324 level = duk_debug_read_int(thr);
47325 if (level >= 0 || -level > (duk_int32_t) thr->callstack_top) {
47326 duk_debug_write_error_eom(thr, DUK_DBG_ERR_NOTFOUND, "invalid callstack index");
47327 return 0; /* zero indicates failure */
47328 }
47329 return level;
47330}
47331
47332/* Read a call stack index and lookup the corresponding duk_activation.
47333 * If index is invalid, write out an error message and return NULL.
47334 */
47335DUK_LOCAL duk_activation *duk__debug_read_level_get_activation(duk_hthread *thr) {
47336 duk_activation *act;
47337 duk_int32_t level;
47338
47339 level = duk_debug_read_int(thr);
47340 act = duk_hthread_get_activation_for_level(thr, level);
47341 if (act == NULL) {
47342 duk_debug_write_error_eom(thr, DUK_DBG_ERR_NOTFOUND, "invalid callstack index");
47343 }
47344 return act;
47345}
47346
47347/*
47348 * Simple commands
47349 */
47350
47351DUK_LOCAL void duk__debug_handle_basic_info(duk_hthread *thr, duk_heap *heap) {
47352 DUK_UNREF(heap);
47353 DUK_D(DUK_DPRINT("debug command Version"));
47354
47355 duk_debug_write_reply(thr);
47356 duk_debug_write_int(thr, DUK_VERSION);
47357 duk_debug_write_cstring(thr, DUK_GIT_DESCRIBE);
47358 duk_debug_write_cstring(thr, DUK_USE_TARGET_INFO);
47359#if defined(DUK_USE_DOUBLE_LE)
47360 duk_debug_write_int(thr, 1);
47361#elif defined(DUK_USE_DOUBLE_ME)
47362 duk_debug_write_int(thr, 2);
47363#elif defined(DUK_USE_DOUBLE_BE)
47364 duk_debug_write_int(thr, 3);
47365#else
47366 duk_debug_write_int(thr, 0);
47367#endif
47368 duk_debug_write_int(thr, (duk_int_t) sizeof(void *));
47369 duk_debug_write_eom(thr);
47370}
47371
47372DUK_LOCAL void duk__debug_handle_trigger_status(duk_hthread *thr, duk_heap *heap) {
47373 DUK_UNREF(heap);
47374 DUK_D(DUK_DPRINT("debug command TriggerStatus"));
47375
47376 duk_debug_write_reply(thr);
47377 duk_debug_write_eom(thr);
47378 heap->dbg_state_dirty = 1;
47379}
47380
47381DUK_LOCAL void duk__debug_handle_pause(duk_hthread *thr, duk_heap *heap) {
47382 DUK_D(DUK_DPRINT("debug command Pause"));
47383 duk_debug_set_paused(heap);
47384 duk_debug_write_reply(thr);
47385 duk_debug_write_eom(thr);
47386}
47387
47388DUK_LOCAL void duk__debug_handle_resume(duk_hthread *thr, duk_heap *heap) {
47389 duk_small_uint_t pause_flags;
47390
47391 DUK_D(DUK_DPRINT("debug command Resume"));
47392
47393 duk_debug_clear_paused(heap);
47394
47395 pause_flags = 0;
47396#if 0 /* manual testing */
47397 pause_flags |= DUK_PAUSE_FLAG_ONE_OPCODE;
47398 pause_flags |= DUK_PAUSE_FLAG_CAUGHT_ERROR;
47399 pause_flags |= DUK_PAUSE_FLAG_UNCAUGHT_ERROR;
47400#endif
47401#if defined(DUK_USE_DEBUGGER_PAUSE_UNCAUGHT)
47402 pause_flags |= DUK_PAUSE_FLAG_UNCAUGHT_ERROR;
47403#endif
47404
47405 duk__debug_set_pause_state(thr, heap, pause_flags);
47406
47407 duk_debug_write_reply(thr);
47408 duk_debug_write_eom(thr);
47409}
47410
47411DUK_LOCAL void duk__debug_handle_step(duk_hthread *thr, duk_heap *heap, duk_int32_t cmd) {
47412 duk_small_uint_t pause_flags;
47413
47414 DUK_D(DUK_DPRINT("debug command StepInto/StepOver/StepOut: %d", (int) cmd));
47415
47416 if (cmd == DUK_DBG_CMD_STEPINTO) {
47418 } else if (cmd == DUK_DBG_CMD_STEPOVER) {
47420 } else {
47422 pause_flags = DUK_PAUSE_FLAG_FUNC_EXIT;
47423 }
47424#if defined(DUK_USE_DEBUGGER_PAUSE_UNCAUGHT)
47425 pause_flags |= DUK_PAUSE_FLAG_UNCAUGHT_ERROR;
47426#endif
47427
47428 /* If current activation doesn't have line information, line-based
47429 * pause flags are automatically disabled. As a result, e.g.
47430 * StepInto will then pause on (native) function entry or exit.
47431 */
47432 duk_debug_clear_paused(heap);
47433 duk__debug_set_pause_state(thr, heap, pause_flags);
47434
47435 duk_debug_write_reply(thr);
47436 duk_debug_write_eom(thr);
47437}
47438
47439DUK_LOCAL void duk__debug_handle_list_break(duk_hthread *thr, duk_heap *heap) {
47441
47442 DUK_D(DUK_DPRINT("debug command ListBreak"));
47443 duk_debug_write_reply(thr);
47444 for (i = 0; i < (duk_small_int_t) heap->dbg_breakpoint_count; i++) {
47445 duk_debug_write_hstring(thr, heap->dbg_breakpoints[i].filename);
47446 duk_debug_write_uint(thr, (duk_uint32_t) heap->dbg_breakpoints[i].line);
47447 }
47448 duk_debug_write_eom(thr);
47449}
47450
47451DUK_LOCAL void duk__debug_handle_add_break(duk_hthread *thr, duk_heap *heap) {
47452 duk_hstring *filename;
47453 duk_uint32_t linenumber;
47454 duk_small_int_t idx;
47455
47456 DUK_UNREF(heap);
47457
47458 filename = duk_debug_read_hstring(thr);
47459 linenumber = (duk_uint32_t) duk_debug_read_int(thr);
47460 DUK_D(DUK_DPRINT("debug command AddBreak: %!O:%ld", (duk_hobject *) filename, (long) linenumber));
47461 idx = duk_debug_add_breakpoint(thr, filename, linenumber);
47462 if (idx >= 0) {
47463 duk_debug_write_reply(thr);
47464 duk_debug_write_int(thr, (duk_int32_t) idx);
47465 duk_debug_write_eom(thr);
47466 } else {
47467 duk_debug_write_error_eom(thr, DUK_DBG_ERR_TOOMANY, "no space for breakpoint");
47468 }
47469}
47470
47471DUK_LOCAL void duk__debug_handle_del_break(duk_hthread *thr, duk_heap *heap) {
47472 duk_small_uint_t idx;
47473
47474 DUK_UNREF(heap);
47475
47476 DUK_D(DUK_DPRINT("debug command DelBreak"));
47477 idx = (duk_small_uint_t) duk_debug_read_int(thr);
47478 if (duk_debug_remove_breakpoint(thr, idx)) {
47479 duk_debug_write_reply(thr);
47480 duk_debug_write_eom(thr);
47481 } else {
47482 duk_debug_write_error_eom(thr, DUK_DBG_ERR_NOTFOUND, "invalid breakpoint index");
47483 }
47484}
47485
47486DUK_LOCAL void duk__debug_handle_get_var(duk_hthread *thr, duk_heap *heap) {
47487 duk_activation *act;
47488 duk_hstring *str;
47489 duk_bool_t rc;
47490
47491 DUK_UNREF(heap);
47492 DUK_D(DUK_DPRINT("debug command GetVar"));
47493
47494 act = duk__debug_read_level_get_activation(thr);
47495 if (act == NULL) {
47496 return;
47497 }
47498 str = duk_debug_read_hstring(thr); /* push to stack */
47499 DUK_ASSERT(str != NULL);
47500
47501 rc = duk_js_getvar_activation(thr, act, str, 0);
47502
47503 duk_debug_write_reply(thr);
47504 if (rc) {
47505 duk_debug_write_int(thr, 1);
47506 DUK_ASSERT(duk_get_tval(thr, -2) != NULL);
47507 duk_debug_write_tval(thr, duk_get_tval(thr, -2));
47508 } else {
47509 duk_debug_write_int(thr, 0);
47510 duk_debug_write_unused(thr);
47511 }
47512 duk_debug_write_eom(thr);
47513}
47514
47515DUK_LOCAL void duk__debug_handle_put_var(duk_hthread *thr, duk_heap *heap) {
47516 duk_activation *act;
47517 duk_hstring *str;
47518 duk_tval *tv;
47519
47520 DUK_UNREF(heap);
47521 DUK_D(DUK_DPRINT("debug command PutVar"));
47522
47523 act = duk__debug_read_level_get_activation(thr);
47524 if (act == NULL) {
47525 return;
47526 }
47527 str = duk_debug_read_hstring(thr); /* push to stack */
47528 DUK_ASSERT(str != NULL);
47529 tv = duk_debug_read_tval(thr);
47530 if (tv == NULL) {
47531 /* detached */
47532 return;
47533 }
47534
47535 duk_js_putvar_activation(thr, act, str, tv, 0);
47536
47537 /* XXX: Current putvar implementation doesn't have a success flag,
47538 * add one and send to debug client?
47539 */
47540 duk_debug_write_reply(thr);
47541 duk_debug_write_eom(thr);
47542}
47543
47544DUK_LOCAL void duk__debug_handle_get_call_stack(duk_hthread *thr, duk_heap *heap) {
47545 duk_hthread *curr_thr = thr;
47546 duk_activation *curr_act;
47549
47550 DUK_ASSERT(thr != NULL);
47551 DUK_UNREF(heap);
47552
47553 duk_debug_write_reply(thr);
47554 while (curr_thr != NULL) {
47555 for (curr_act = curr_thr->callstack_curr; curr_act != NULL; curr_act = curr_act->parent) {
47556 /* PC/line semantics here are:
47557 * - For callstack top we're conceptually between two
47558 * opcodes and current PC indicates next line to
47559 * execute, so report that (matches Status).
47560 * - For other activations we're conceptually still
47561 * executing the instruction at PC-1, so report that
47562 * (matches error stacktrace behavior).
47563 * - See: https://github.com/svaarala/duktape/issues/281
47564 */
47565
47566 /* XXX: optimize to use direct reads, i.e. avoid
47567 * value stack operations.
47568 */
47569 duk_push_tval(thr, &curr_act->tv_func);
47571 duk__debug_write_hstring_safe_top(thr);
47573 duk__debug_write_hstring_safe_top(thr);
47574 pc = duk_hthread_get_act_curr_pc(thr, curr_act);
47575 if (curr_act != curr_thr->callstack_curr && pc > 0) {
47576 pc--;
47577 }
47578 line = duk_hobject_pc2line_query(thr, -3, pc);
47579 duk_debug_write_uint(thr, (duk_uint32_t) line);
47580 duk_debug_write_uint(thr, (duk_uint32_t) pc);
47581 duk_pop_3(thr);
47582 }
47583 curr_thr = curr_thr->resumer;
47584 }
47585 /* SCANBUILD: warning about 'thr' potentially being NULL here,
47586 * warning is incorrect because thr != NULL always here.
47587 */
47588 duk_debug_write_eom(thr);
47589}
47590
47591DUK_LOCAL void duk__debug_handle_get_locals(duk_hthread *thr, duk_heap *heap) {
47592 duk_activation *act;
47593 duk_hstring *varname;
47594
47595 DUK_UNREF(heap);
47596
47597 act = duk__debug_read_level_get_activation(thr);
47598 if (act == NULL) {
47599 return;
47600 }
47601
47602 duk_debug_write_reply(thr);
47603
47604 /* XXX: several nice-to-have improvements here:
47605 * - Use direct reads avoiding value stack operations
47606 * - Avoid triggering getters, indicate getter values to debug client
47607 * - If side effects are possible, add error catching
47608 */
47609
47610 if (DUK_TVAL_IS_OBJECT(&act->tv_func)) {
47611 duk_hobject *h_func = DUK_TVAL_GET_OBJECT(&act->tv_func);
47612 duk_hobject *h_varmap;
47613
47614 h_varmap = duk_hobject_get_varmap(thr, h_func);
47615 if (h_varmap != NULL) {
47616 duk_push_hobject(thr, h_varmap);
47617 duk_enum(thr, -1, 0 /*enum_flags*/);
47618 while (duk_next(thr, -1 /*enum_index*/, 0 /*get_value*/)) {
47619 varname = duk_known_hstring(thr, -1);
47620
47621 duk_js_getvar_activation(thr, act, varname, 0 /*throw_flag*/);
47622 /* [ ... func varmap enum key value this ] */
47623 duk_debug_write_hstring(thr, duk_get_hstring(thr, -3));
47624 duk_debug_write_tval(thr, duk_get_tval(thr, -2));
47625 duk_pop_3(thr); /* -> [ ... func varmap enum ] */
47626 }
47627 } else {
47628 DUK_D(DUK_DPRINT("varmap missing in GetLocals, ignore"));
47629 }
47630 } else {
47631 DUK_D(DUK_DPRINT("varmap is not an object in GetLocals, ignore"));
47632 }
47633
47634 duk_debug_write_eom(thr);
47635}
47636
47637DUK_LOCAL void duk__debug_handle_eval(duk_hthread *thr, duk_heap *heap) {
47638 duk_small_uint_t call_flags;
47639 duk_int_t call_ret;
47640 duk_small_int_t eval_err;
47641 duk_bool_t direct_eval;
47642 duk_int32_t level;
47643 duk_idx_t idx_func;
47644
47645 DUK_UNREF(heap);
47646
47647 DUK_D(DUK_DPRINT("debug command Eval"));
47648
47649 /* The eval code is executed within the lexical environment of a specified
47650 * activation. For now, use global object eval() function, with the eval
47651 * considered a 'direct call to eval'.
47652 *
47653 * Callstack index for debug commands only affects scope -- the callstack
47654 * as seen by, e.g. Duktape.act() will be the same regardless.
47655 */
47656
47657 /* nargs == 2 so we can pass a callstack index to eval(). */
47658 idx_func = duk_get_top(thr);
47660 duk_push_undefined(thr); /* 'this' binding shouldn't matter here */
47661
47662 /* Read callstack index, if non-null. */
47663 if (duk_debug_peek_byte(thr) == DUK_DBG_IB_NULL) {
47664 direct_eval = 0;
47665 level = -1; /* Not needed, but silences warning. */
47666 (void) duk_debug_read_byte(thr);
47667 } else {
47668 direct_eval = 1;
47669 level = duk__debug_read_validate_csindex(thr);
47670 if (level == 0) {
47671 return;
47672 }
47673 }
47674
47675 DUK_ASSERT(!direct_eval || (level < 0 && -level <= (duk_int32_t) thr->callstack_top));
47676
47677 (void) duk_debug_read_hstring(thr);
47678 if (direct_eval) {
47679 duk_push_int(thr, level - 1); /* compensate for eval() call */
47680 }
47681
47682 /* [ ... eval "eval" eval_input level? ] */
47683
47684 call_flags = 0;
47685 if (direct_eval) {
47686 duk_activation *act;
47687 duk_hobject *fun;
47688
47689 act = duk_hthread_get_activation_for_level(thr, level);
47690 if (act != NULL) {
47691 fun = DUK_ACT_GET_FUNC(act);
47692 if (fun != NULL && DUK_HOBJECT_IS_COMPFUNC(fun)) {
47693 /* Direct eval requires that there's a current
47694 * activation and it is an ECMAScript function.
47695 * When Eval is executed from e.g. cooperate API
47696 * call we'll need to do an indirect eval instead.
47697 */
47698 call_flags |= DUK_CALL_FLAG_DIRECT_EVAL;
47699 }
47700 }
47701 }
47702
47703 call_ret = duk_pcall_method_flags(thr, duk_get_top(thr) - (idx_func + 2), call_flags);
47704
47705 if (call_ret == DUK_EXEC_SUCCESS) {
47706 eval_err = 0;
47707 /* Use result value as is. */
47708 } else {
47709 /* For errors a string coerced result is most informative
47710 * right now, as the debug client doesn't have the capability
47711 * to traverse the error object.
47712 */
47713 eval_err = 1;
47714 duk_safe_to_string(thr, -1);
47715 }
47716
47717 /* [ ... result ] */
47718
47719 duk_debug_write_reply(thr);
47720 duk_debug_write_int(thr, (duk_int32_t) eval_err);
47721 DUK_ASSERT(duk_get_tval(thr, -1) != NULL);
47722 duk_debug_write_tval(thr, duk_get_tval(thr, -1));
47723 duk_debug_write_eom(thr);
47724}
47725
47726DUK_LOCAL void duk__debug_handle_detach(duk_hthread *thr, duk_heap *heap) {
47727 DUK_UNREF(heap);
47728 DUK_D(DUK_DPRINT("debug command Detach"));
47729
47730 duk_debug_write_reply(thr);
47731 duk_debug_write_eom(thr);
47732
47733 DUK_D(DUK_DPRINT("debug connection detached, mark broken"));
47734 DUK__SET_CONN_BROKEN(thr, 0); /* not an error */
47735}
47736
47737DUK_LOCAL void duk__debug_handle_apprequest(duk_hthread *thr, duk_heap *heap) {
47738 duk_idx_t old_top;
47739
47740 DUK_D(DUK_DPRINT("debug command AppRequest"));
47741
47742 old_top = duk_get_top(thr); /* save stack top */
47743
47744 if (heap->dbg_request_cb != NULL) {
47745 duk_idx_t nrets;
47746 duk_idx_t nvalues = 0;
47747 duk_idx_t top, idx;
47748
47749 /* Read tvals from the message and push them onto the valstack,
47750 * then call the request callback to process the request.
47751 */
47752 while (duk_debug_peek_byte(thr) != DUK_DBG_IB_EOM) {
47753 duk_tval *tv;
47754 if (!duk_check_stack(thr, 1)) {
47755 DUK_D(DUK_DPRINT("failed to allocate space for request dvalue(s)"));
47756 goto fail;
47757 }
47758 tv = duk_debug_read_tval(thr); /* push to stack */
47759 if (tv == NULL) {
47760 /* detached */
47761 return;
47762 }
47763 nvalues++;
47764 }
47765 DUK_ASSERT(duk_get_top(thr) == old_top + nvalues);
47766
47767 /* Request callback should push values for reply to client onto valstack */
47768 DUK_D(DUK_DPRINT("calling into AppRequest request_cb with nvalues=%ld, old_top=%ld, top=%ld",
47769 (long) nvalues,
47770 (long) old_top,
47771 (long) duk_get_top(thr)));
47772 nrets = heap->dbg_request_cb(thr, heap->dbg_udata, nvalues);
47773 DUK_D(DUK_DPRINT("returned from AppRequest request_cb; nvalues=%ld -> nrets=%ld, old_top=%ld, top=%ld",
47774 (long) nvalues,
47775 (long) nrets,
47776 (long) old_top,
47777 (long) duk_get_top(thr)));
47778 if (nrets >= 0) {
47779 DUK_ASSERT(duk_get_top(thr) >= old_top + nrets);
47780 if (duk_get_top(thr) < old_top + nrets) {
47781 DUK_D(DUK_DPRINT("AppRequest callback doesn't match value stack configuration, "
47782 "top=%ld < old_top=%ld + nrets=%ld; "
47783 "this might mean it's unsafe to continue!",
47784 (long) duk_get_top(thr),
47785 (long) old_top,
47786 (long) nrets));
47787 goto fail;
47788 }
47789
47790 /* Reply with tvals pushed by request callback */
47791 duk_debug_write_byte(thr, DUK_DBG_IB_REPLY);
47792 top = duk_get_top(thr);
47793 for (idx = top - nrets; idx < top; idx++) {
47794 duk_debug_write_tval(thr, DUK_GET_TVAL_POSIDX(thr, idx));
47795 }
47796 duk_debug_write_eom(thr);
47797 } else {
47798 DUK_ASSERT(duk_get_top(thr) >= old_top + 1);
47799 if (duk_get_top(thr) < old_top + 1) {
47800 DUK_D(DUK_DPRINT("request callback return value doesn't match value stack configuration"));
47801 goto fail;
47802 }
47803 duk_debug_write_error_eom(thr, DUK_DBG_ERR_APPLICATION, duk_get_string(thr, -1));
47804 }
47805
47806 duk_set_top(thr, old_top); /* restore stack top */
47807 } else {
47808 DUK_D(DUK_DPRINT("no request callback, treat AppRequest as unsupported"));
47809 duk_debug_write_error_eom(thr, DUK_DBG_ERR_UNSUPPORTED, "AppRequest unsupported by target");
47810 }
47811
47812 return;
47813
47814fail:
47815 duk_set_top(thr, old_top); /* restore stack top */
47816 DUK__SET_CONN_BROKEN(thr, 1);
47817}
47818
47819/*
47820 * DumpHeap command
47821 */
47822
47823#if defined(DUK_USE_DEBUGGER_DUMPHEAP)
47824/* XXX: this has some overlap with object inspection; remove this and make
47825 * DumpHeap return lists of heapptrs instead?
47826 */
47827DUK_LOCAL void duk__debug_dump_heaphdr(duk_hthread *thr, duk_heap *heap, duk_heaphdr *hdr) {
47828 DUK_UNREF(heap);
47829
47830 duk_debug_write_heapptr(thr, hdr);
47831 duk_debug_write_uint(thr, (duk_uint32_t) DUK_HEAPHDR_GET_TYPE(hdr));
47832 duk_debug_write_uint(thr, (duk_uint32_t) DUK_HEAPHDR_GET_FLAGS_RAW(hdr));
47833#if defined(DUK_USE_REFERENCE_COUNTING)
47834 duk_debug_write_uint(thr, (duk_uint32_t) DUK_HEAPHDR_GET_REFCOUNT(hdr));
47835#else
47836 duk_debug_write_int(thr, (duk_int32_t) -1);
47837#endif
47838
47839 switch (DUK_HEAPHDR_GET_TYPE(hdr)) {
47840 case DUK_HTYPE_STRING: {
47841 duk_hstring *h = (duk_hstring *) hdr;
47842
47843 duk_debug_write_uint(thr, (duk_uint32_t) DUK_HSTRING_GET_BYTELEN(h));
47844 duk_debug_write_uint(thr, (duk_uint32_t) DUK_HSTRING_GET_CHARLEN(h));
47845 duk_debug_write_uint(thr, (duk_uint32_t) DUK_HSTRING_GET_HASH(h));
47846 duk_debug_write_hstring(thr, h);
47847 break;
47848 }
47849 case DUK_HTYPE_OBJECT: {
47850 duk_hobject *h = (duk_hobject *) hdr;
47851 duk_hstring *k;
47853
47854 duk_debug_write_uint(thr, (duk_uint32_t) DUK_HOBJECT_GET_CLASS_NUMBER(h));
47855 duk_debug_write_heapptr(thr, (duk_heaphdr *) DUK_HOBJECT_GET_PROTOTYPE(heap, h));
47856 duk_debug_write_uint(thr, (duk_uint32_t) DUK_HOBJECT_GET_ESIZE(h));
47857 duk_debug_write_uint(thr, (duk_uint32_t) DUK_HOBJECT_GET_ENEXT(h));
47858 duk_debug_write_uint(thr, (duk_uint32_t) DUK_HOBJECT_GET_ASIZE(h));
47859 duk_debug_write_uint(thr, (duk_uint32_t) DUK_HOBJECT_GET_HSIZE(h));
47860
47861 for (i = 0; i < (duk_uint_fast32_t) DUK_HOBJECT_GET_ENEXT(h); i++) {
47862 duk_debug_write_uint(thr, (duk_uint32_t) DUK_HOBJECT_E_GET_FLAGS(heap, h, i));
47863 k = DUK_HOBJECT_E_GET_KEY(heap, h, i);
47864 duk_debug_write_heapptr(thr, (duk_heaphdr *) k);
47865 if (k == NULL) {
47866 duk_debug_write_int(thr, 0); /* isAccessor */
47867 duk_debug_write_unused(thr);
47868 continue;
47869 }
47870 if (DUK_HOBJECT_E_SLOT_IS_ACCESSOR(heap, h, i)) {
47871 duk_debug_write_int(thr, 1); /* isAccessor */
47872 duk_debug_write_heapptr(thr, (duk_heaphdr *) DUK_HOBJECT_E_GET_VALUE_PTR(heap, h, i)->a.get);
47873 duk_debug_write_heapptr(thr, (duk_heaphdr *) DUK_HOBJECT_E_GET_VALUE_PTR(heap, h, i)->a.set);
47874 } else {
47875 duk_debug_write_int(thr, 0); /* isAccessor */
47876
47877 duk__debug_write_tval_heapptr(thr, &DUK_HOBJECT_E_GET_VALUE_PTR(heap, h, i)->v);
47878 }
47879 }
47880
47881 for (i = 0; i < (duk_uint_fast32_t) DUK_HOBJECT_GET_ASIZE(h); i++) {
47882 /* Note: array dump will include elements beyond
47883 * 'length'.
47884 */
47885 duk__debug_write_tval_heapptr(thr, DUK_HOBJECT_A_GET_VALUE_PTR(heap, h, i));
47886 }
47887 break;
47888 }
47889 case DUK_HTYPE_BUFFER: {
47890 duk_hbuffer *h = (duk_hbuffer *) hdr;
47891
47892 duk_debug_write_uint(thr, (duk_uint32_t) DUK_HBUFFER_GET_SIZE(h));
47893 duk_debug_write_buffer(thr, (const char *) DUK_HBUFFER_GET_DATA_PTR(heap, h), (duk_size_t) DUK_HBUFFER_GET_SIZE(h));
47894 break;
47895 }
47896 default: {
47897 DUK_D(DUK_DPRINT("invalid htype: %d", (int) DUK_HEAPHDR_GET_TYPE(hdr)));
47898 }
47899 }
47900}
47901
47902DUK_LOCAL void duk__debug_dump_heap_allocated(duk_hthread *thr, duk_heap *heap) {
47903 duk_heaphdr *hdr;
47904
47905 hdr = heap->heap_allocated;
47906 while (hdr != NULL) {
47907 duk__debug_dump_heaphdr(thr, heap, hdr);
47908 hdr = DUK_HEAPHDR_GET_NEXT(heap, hdr);
47909 }
47910}
47911
47912DUK_LOCAL void duk__debug_dump_strtab(duk_hthread *thr, duk_heap *heap) {
47913 duk_uint32_t i;
47914 duk_hstring *h;
47915
47916 for (i = 0; i < heap->st_size; i++) {
47917#if defined(DUK_USE_STRTAB_PTRCOMP)
47918 h = DUK_USE_HEAPPTR_DEC16((heap)->heap_udata, heap->strtable16[i]);
47919#else
47920 h = heap->strtable[i];
47921#endif
47922 while (h != NULL) {
47923 duk__debug_dump_heaphdr(thr, heap, (duk_heaphdr *) h);
47924 h = h->hdr.h_next;
47925 }
47926 }
47927}
47928
47929DUK_LOCAL void duk__debug_handle_dump_heap(duk_hthread *thr, duk_heap *heap) {
47930 DUK_D(DUK_DPRINT("debug command DumpHeap"));
47931
47932 duk_debug_write_reply(thr);
47933 duk__debug_dump_heap_allocated(thr, heap);
47934 duk__debug_dump_strtab(thr, heap);
47935 duk_debug_write_eom(thr);
47936}
47937#endif /* DUK_USE_DEBUGGER_DUMPHEAP */
47938
47939DUK_LOCAL void duk__debug_handle_get_bytecode(duk_hthread *thr, duk_heap *heap) {
47940 duk_activation *act;
47941 duk_hcompfunc *fun = NULL;
47942 duk_size_t i, n;
47943 duk_tval *tv;
47944 duk_hobject **fn;
47945 duk_int32_t level = -1;
47946 duk_uint8_t ibyte;
47947
47948 DUK_UNREF(heap);
47949
47950 DUK_D(DUK_DPRINT("debug command GetBytecode"));
47951
47952 ibyte = duk_debug_peek_byte(thr);
47953 if (ibyte != DUK_DBG_IB_EOM) {
47954 tv = duk_debug_read_tval(thr);
47955 if (tv == NULL) {
47956 /* detached */
47957 return;
47958 }
47959 if (DUK_TVAL_IS_OBJECT(tv)) {
47960 /* tentative, checked later */
47961 fun = (duk_hcompfunc *) DUK_TVAL_GET_OBJECT(tv);
47962 DUK_ASSERT(fun != NULL);
47963 } else if (DUK_TVAL_IS_NUMBER(tv)) {
47964 level = (duk_int32_t) DUK_TVAL_GET_NUMBER(tv);
47965 } else {
47966 DUK_D(DUK_DPRINT("invalid argument to GetBytecode: %!T", tv));
47967 goto fail_args;
47968 }
47969 }
47970
47971 if (fun == NULL) {
47972 act = duk_hthread_get_activation_for_level(thr, level);
47973 if (act == NULL) {
47974 goto fail_index;
47975 }
47976 fun = (duk_hcompfunc *) DUK_ACT_GET_FUNC(act);
47977 }
47978
47979 if (fun == NULL || !DUK_HOBJECT_IS_COMPFUNC((duk_hobject *) fun)) {
47980 DUK_D(DUK_DPRINT("invalid argument to GetBytecode: %!O", fun));
47981 goto fail_args;
47982 }
47983 DUK_ASSERT(fun != NULL && DUK_HOBJECT_IS_COMPFUNC((duk_hobject *) fun));
47984
47985 duk_debug_write_reply(thr);
47986 n = DUK_HCOMPFUNC_GET_CONSTS_COUNT(heap, fun);
47987 duk_debug_write_int(thr, (duk_int32_t) n);
47988 tv = DUK_HCOMPFUNC_GET_CONSTS_BASE(heap, fun);
47989 for (i = 0; i < n; i++) {
47990 duk_debug_write_tval(thr, tv);
47991 tv++;
47992 }
47993 n = DUK_HCOMPFUNC_GET_FUNCS_COUNT(heap, fun);
47994 duk_debug_write_int(thr, (duk_int32_t) n);
47995 fn = DUK_HCOMPFUNC_GET_FUNCS_BASE(heap, fun);
47996 for (i = 0; i < n; i++) {
47997 duk_debug_write_hobject(thr, *fn);
47998 fn++;
47999 }
48000 duk_debug_write_string(thr,
48001 (const char *) DUK_HCOMPFUNC_GET_CODE_BASE(heap, fun),
48003 duk_debug_write_eom(thr);
48004 return;
48005
48006fail_args:
48007 duk_debug_write_error_eom(thr, DUK_DBG_ERR_UNKNOWN, "invalid argument");
48008 return;
48009
48010fail_index:
48011 duk_debug_write_error_eom(thr, DUK_DBG_ERR_NOTFOUND, "invalid callstack index");
48012 return;
48013}
48014
48015/*
48016 * Object inspection commands: GetHeapObjInfo, GetObjPropDesc,
48017 * GetObjPropDescRange
48018 */
48019
48020#if defined(DUK_USE_DEBUGGER_INSPECT)
48021
48022#if 0 /* pruned */
48023DUK_LOCAL const char * const duk__debug_getinfo_heaphdr_keys[] = {
48024 "reachable",
48025 "temproot",
48026 "finalizable",
48027 "finalized",
48028 "readonly"
48029 /* NULL not needed here */
48030};
48031DUK_LOCAL duk_uint_t duk__debug_getinfo_heaphdr_masks[] = {
48037 0 /* terminator */
48038};
48039#endif
48040DUK_LOCAL const char * const duk__debug_getinfo_hstring_keys[] = {
48041#if 0
48042 "arridx",
48043 "symbol",
48044 "hidden",
48045 "reserved_word",
48046 "strict_reserved_word",
48047 "eval_or_arguments",
48048#endif
48049 "extdata"
48050 /* NULL not needed here */
48051};
48052DUK_LOCAL duk_uint_t duk__debug_getinfo_hstring_masks[] = {
48053#if 0
48060#endif
48062 0 /* terminator */
48063};
48064DUK_LOCAL const char * const duk__debug_getinfo_hobject_keys[] = {
48065 "extensible", "constructable", "callable", "boundfunc", "compfunc", "natfunc", "bufobj",
48066 "fastrefs", "array_part", "strict", "notail", "newenv", "namebinding", "createargs",
48067 "have_finalizer", "exotic_array", "exotic_stringobj", "exotic_arguments", "exotic_proxyobj", "special_call"
48068 /* NULL not needed here */
48069};
48070DUK_LOCAL duk_uint_t duk__debug_getinfo_hobject_masks[] = {
48078};
48079DUK_LOCAL const char * const duk__debug_getinfo_hbuffer_keys[] = {
48080 "dynamic",
48081 "external"
48082 /* NULL not needed here */
48083};
48084DUK_LOCAL duk_uint_t duk__debug_getinfo_hbuffer_masks[] = {
48087 0 /* terminator */
48088};
48089
48090DUK_LOCAL void duk__debug_getinfo_flags_key(duk_hthread *thr, const char *key) {
48091 duk_debug_write_uint(thr, 0);
48092 duk_debug_write_cstring(thr, key);
48093}
48094
48095DUK_LOCAL void duk__debug_getinfo_prop_uint(duk_hthread *thr, const char *key, duk_uint_t val) {
48096 duk_debug_write_uint(thr, 0);
48097 duk_debug_write_cstring(thr, key);
48098 duk_debug_write_uint(thr, val);
48099}
48100
48101DUK_LOCAL void duk__debug_getinfo_prop_int(duk_hthread *thr, const char *key, duk_int_t val) {
48102 duk_debug_write_uint(thr, 0);
48103 duk_debug_write_cstring(thr, key);
48104 duk_debug_write_int(thr, val);
48105}
48106
48107DUK_LOCAL void duk__debug_getinfo_prop_bool(duk_hthread *thr, const char *key, duk_bool_t val) {
48108 duk_debug_write_uint(thr, 0);
48109 duk_debug_write_cstring(thr, key);
48110 duk_debug_write_boolean(thr, val);
48111}
48112
48113DUK_LOCAL void duk__debug_getinfo_bitmask(duk_hthread *thr, const char * const *keys, duk_uint_t *masks, duk_uint_t flags) {
48114 const char *key;
48115 duk_uint_t mask;
48116
48117 for (;;) {
48118 mask = *masks++;
48119 if (mask == 0) {
48120 break;
48121 }
48122 key = *keys++;
48123 DUK_ASSERT(key != NULL);
48124
48125 DUK_DD(DUK_DDPRINT("inspect bitmask: key=%s, mask=0x%08lx, flags=0x%08lx",
48126 key,
48127 (unsigned long) mask,
48128 (unsigned long) flags));
48129 duk__debug_getinfo_prop_bool(thr, key, flags & mask);
48130 }
48131}
48132
48133/* Inspect a property using a virtual index into a conceptual property list
48134 * consisting of (1) all array part items from [0,a_size[ (even when above
48135 * .length) and (2) all entry part items from [0,e_next[. Unused slots are
48136 * indicated using dvalue 'unused'.
48137 */
48138DUK_LOCAL duk_bool_t duk__debug_getprop_index(duk_hthread *thr, duk_heap *heap, duk_hobject *h_obj, duk_uint_t idx) {
48139 duk_uint_t a_size;
48140 duk_tval *tv;
48141 duk_hstring *h_key;
48142 duk_hobject *h_getset;
48143 duk_uint_t flags;
48144
48145 DUK_UNREF(heap);
48146
48147 a_size = DUK_HOBJECT_GET_ASIZE(h_obj);
48148 if (idx < a_size) {
48149 duk_debug_write_uint(thr, DUK_PROPDESC_FLAGS_WEC);
48150 duk_debug_write_uint(thr, idx);
48151 tv = DUK_HOBJECT_A_GET_VALUE_PTR(heap, h_obj, idx);
48152 duk_debug_write_tval(thr, tv);
48153 return 1;
48154 }
48155
48156 idx -= a_size;
48157 if (idx >= DUK_HOBJECT_GET_ENEXT(h_obj)) {
48158 return 0;
48159 }
48160
48161 h_key = DUK_HOBJECT_E_GET_KEY(heap, h_obj, idx);
48162 if (h_key == NULL) {
48163 duk_debug_write_uint(thr, 0);
48164 duk_debug_write_null(thr);
48165 duk_debug_write_unused(thr);
48166 return 1;
48167 }
48168
48169 flags = DUK_HOBJECT_E_GET_FLAGS(heap, h_obj, idx);
48170 if (DUK_HSTRING_HAS_SYMBOL(h_key)) {
48171 flags |= DUK_DBG_PROPFLAG_SYMBOL;
48172 }
48173 if (DUK_HSTRING_HAS_HIDDEN(h_key)) {
48174 flags |= DUK_DBG_PROPFLAG_HIDDEN;
48175 }
48176 duk_debug_write_uint(thr, flags);
48177 duk_debug_write_hstring(thr, h_key);
48178 if (flags & DUK_PROPDESC_FLAG_ACCESSOR) {
48179 h_getset = DUK_HOBJECT_E_GET_VALUE_GETTER(heap, h_obj, idx);
48180 if (h_getset) {
48181 duk_debug_write_hobject(thr, h_getset);
48182 } else {
48183 duk_debug_write_null(thr);
48184 }
48185 h_getset = DUK_HOBJECT_E_GET_VALUE_SETTER(heap, h_obj, idx);
48186 if (h_getset) {
48187 duk_debug_write_hobject(thr, h_getset);
48188 } else {
48189 duk_debug_write_null(thr);
48190 }
48191 } else {
48192 tv = DUK_HOBJECT_E_GET_VALUE_TVAL_PTR(heap, h_obj, idx);
48193 duk_debug_write_tval(thr, tv);
48194 }
48195 return 1;
48196}
48197
48198DUK_LOCAL void duk__debug_handle_get_heap_obj_info(duk_hthread *thr, duk_heap *heap) {
48199 duk_heaphdr *h;
48200
48201 DUK_D(DUK_DPRINT("debug command GetHeapObjInfo"));
48202 DUK_UNREF(heap);
48203
48204 DUK_ASSERT(sizeof(duk__debug_getinfo_hstring_keys) / sizeof(const char *) ==
48205 sizeof(duk__debug_getinfo_hstring_masks) / sizeof(duk_uint_t) - 1);
48206 DUK_ASSERT(sizeof(duk__debug_getinfo_hobject_keys) / sizeof(const char *) ==
48207 sizeof(duk__debug_getinfo_hobject_masks) / sizeof(duk_uint_t) - 1);
48208 DUK_ASSERT(sizeof(duk__debug_getinfo_hbuffer_keys) / sizeof(const char *) ==
48209 sizeof(duk__debug_getinfo_hbuffer_masks) / sizeof(duk_uint_t) - 1);
48210
48211 h = duk_debug_read_any_ptr(thr);
48212 if (!h) {
48213 duk_debug_write_error_eom(thr, DUK_DBG_ERR_UNKNOWN, "invalid target");
48214 return;
48215 }
48216
48217 duk_debug_write_reply(thr);
48218
48219 /* As with all inspection code, we rely on the debug client providing
48220 * a valid, non-stale pointer: there's no portable way to safely
48221 * validate the pointer here.
48222 */
48223
48224 duk__debug_getinfo_flags_key(thr, "heapptr");
48225 duk_debug_write_heapptr(thr, h);
48226
48227 /* XXX: comes out as signed now */
48228 duk__debug_getinfo_prop_uint(thr, "heaphdr_flags", (duk_uint_t) DUK_HEAPHDR_GET_FLAGS(h));
48229 duk__debug_getinfo_prop_uint(thr, "heaphdr_type", (duk_uint_t) DUK_HEAPHDR_GET_TYPE(h));
48230#if defined(DUK_USE_REFERENCE_COUNTING)
48231 duk__debug_getinfo_prop_uint(thr, "refcount", (duk_uint_t) DUK_HEAPHDR_GET_REFCOUNT(h));
48232#endif
48233#if 0 /* pruned */
48234 duk__debug_getinfo_bitmask(thr,
48235 duk__debug_getinfo_heaphdr_keys,
48236 duk__debug_getinfo_heaphdr_masks,
48238#endif
48239
48240 switch (DUK_HEAPHDR_GET_TYPE(h)) {
48241 case DUK_HTYPE_STRING: {
48242 duk_hstring *h_str;
48243
48244 h_str = (duk_hstring *) h;
48245 duk__debug_getinfo_bitmask(thr,
48246 duk__debug_getinfo_hstring_keys,
48247 duk__debug_getinfo_hstring_masks,
48249 duk__debug_getinfo_prop_uint(thr, "bytelen", (duk_uint_t) DUK_HSTRING_GET_BYTELEN(h_str));
48250 duk__debug_getinfo_prop_uint(thr, "charlen", (duk_uint_t) DUK_HSTRING_GET_CHARLEN(h_str));
48251 duk__debug_getinfo_prop_uint(thr, "hash", (duk_uint_t) DUK_HSTRING_GET_HASH(h_str));
48252 duk__debug_getinfo_flags_key(thr, "data");
48253 duk_debug_write_hstring(thr, h_str);
48254 break;
48255 }
48256 case DUK_HTYPE_OBJECT: {
48257 duk_hobject *h_obj;
48258 duk_hobject *h_proto;
48259
48260 h_obj = (duk_hobject *) h;
48261 h_proto = DUK_HOBJECT_GET_PROTOTYPE(heap, h_obj);
48262
48263 /* duk_hobject specific fields. */
48264 duk__debug_getinfo_bitmask(thr,
48265 duk__debug_getinfo_hobject_keys,
48266 duk__debug_getinfo_hobject_masks,
48268 duk__debug_getinfo_prop_uint(thr, "class_number", DUK_HOBJECT_GET_CLASS_NUMBER(h_obj));
48269 duk__debug_getinfo_flags_key(thr, "class_name");
48270 duk_debug_write_hstring(thr, DUK_HOBJECT_GET_CLASS_STRING(heap, h_obj));
48271 duk__debug_getinfo_flags_key(thr, "prototype");
48272 if (h_proto != NULL) {
48273 duk_debug_write_hobject(thr, h_proto);
48274 } else {
48275 duk_debug_write_null(thr);
48276 }
48277 duk__debug_getinfo_flags_key(thr, "props");
48278 duk_debug_write_pointer(thr, (void *) DUK_HOBJECT_GET_PROPS(heap, h_obj));
48279 duk__debug_getinfo_prop_uint(thr, "e_size", (duk_uint_t) DUK_HOBJECT_GET_ESIZE(h_obj));
48280 duk__debug_getinfo_prop_uint(thr, "e_next", (duk_uint_t) DUK_HOBJECT_GET_ENEXT(h_obj));
48281 duk__debug_getinfo_prop_uint(thr, "a_size", (duk_uint_t) DUK_HOBJECT_GET_ASIZE(h_obj));
48282 duk__debug_getinfo_prop_uint(thr, "h_size", (duk_uint_t) DUK_HOBJECT_GET_HSIZE(h_obj));
48283
48284 if (DUK_HOBJECT_IS_ARRAY(h_obj)) {
48285 duk_harray *h_arr;
48286 h_arr = (duk_harray *) h_obj;
48287
48288 duk__debug_getinfo_prop_uint(thr, "length", (duk_uint_t) h_arr->length);
48289 duk__debug_getinfo_prop_bool(thr, "length_nonwritable", h_arr->length_nonwritable);
48290 }
48291
48292 if (DUK_HOBJECT_IS_NATFUNC(h_obj)) {
48293 duk_hnatfunc *h_fun;
48294 h_fun = (duk_hnatfunc *) h_obj;
48295
48296 duk__debug_getinfo_prop_int(thr, "nargs", h_fun->nargs);
48297 duk__debug_getinfo_prop_int(thr, "magic", h_fun->magic);
48298 duk__debug_getinfo_prop_bool(thr, "varargs", h_fun->magic == DUK_HNATFUNC_NARGS_VARARGS);
48299 /* Native function pointer may be different from a void pointer,
48300 * and we serialize it from memory directly now (no byte swapping etc).
48301 */
48302 duk__debug_getinfo_flags_key(thr, "funcptr");
48303 duk_debug_write_buffer(thr, (const char *) &h_fun->func, sizeof(h_fun->func));
48304 }
48305
48306 if (DUK_HOBJECT_IS_COMPFUNC(h_obj)) {
48307 duk_hcompfunc *h_fun;
48308 duk_hbuffer *h_buf;
48309 duk_hobject *h_lexenv;
48310 duk_hobject *h_varenv;
48311 h_fun = (duk_hcompfunc *) h_obj;
48312
48313 duk__debug_getinfo_prop_int(thr, "nregs", h_fun->nregs);
48314 duk__debug_getinfo_prop_int(thr, "nargs", h_fun->nargs);
48315
48316 duk__debug_getinfo_flags_key(thr, "lex_env");
48317 h_lexenv = DUK_HCOMPFUNC_GET_LEXENV(thr->heap, h_fun);
48318 if (h_lexenv != NULL) {
48319 duk_debug_write_hobject(thr, h_lexenv);
48320 } else {
48321 duk_debug_write_null(thr);
48322 }
48323 duk__debug_getinfo_flags_key(thr, "var_env");
48324 h_varenv = DUK_HCOMPFUNC_GET_VARENV(thr->heap, h_fun);
48325 if (h_varenv != NULL) {
48326 duk_debug_write_hobject(thr, h_varenv);
48327 } else {
48328 duk_debug_write_null(thr);
48329 }
48330
48331 duk__debug_getinfo_prop_uint(thr, "start_line", h_fun->start_line);
48332 duk__debug_getinfo_prop_uint(thr, "end_line", h_fun->end_line);
48333 h_buf = (duk_hbuffer *) DUK_HCOMPFUNC_GET_DATA(thr->heap, h_fun);
48334 if (h_buf != NULL) {
48335 duk__debug_getinfo_flags_key(thr, "data");
48336 duk_debug_write_heapptr(thr, (duk_heaphdr *) h_buf);
48337 }
48338 }
48339
48340 if (DUK_HOBJECT_IS_BOUNDFUNC(h_obj)) {
48341 duk_hboundfunc *h_bfun;
48342 h_bfun = (duk_hboundfunc *) (void *) h_obj;
48343
48344 duk__debug_getinfo_flags_key(thr, "target");
48345 duk_debug_write_tval(thr, &h_bfun->target);
48346 duk__debug_getinfo_flags_key(thr, "this_binding");
48347 duk_debug_write_tval(thr, &h_bfun->this_binding);
48348 duk__debug_getinfo_flags_key(thr, "nargs");
48349 duk_debug_write_int(thr, h_bfun->nargs);
48350 /* h_bfun->args not exposed now */
48351 }
48352
48353 if (DUK_HOBJECT_IS_THREAD(h_obj)) {
48354 /* XXX: Currently no inspection of threads, e.g. value stack, call
48355 * stack, catch stack, etc.
48356 */
48357 duk_hthread *h_thr;
48358 h_thr = (duk_hthread *) h_obj;
48359 DUK_UNREF(h_thr);
48360 }
48361
48362 if (DUK_HOBJECT_IS_DECENV(h_obj)) {
48363 duk_hdecenv *h_env;
48364 h_env = (duk_hdecenv *) h_obj;
48365
48366 duk__debug_getinfo_flags_key(thr, "thread");
48367 duk_debug_write_heapptr(thr, (duk_heaphdr *) (h_env->thread));
48368 duk__debug_getinfo_flags_key(thr, "varmap");
48369 duk_debug_write_heapptr(thr, (duk_heaphdr *) (h_env->varmap));
48370 duk__debug_getinfo_prop_uint(thr, "regbase", (duk_uint_t) h_env->regbase_byteoff);
48371 }
48372
48373 if (DUK_HOBJECT_IS_OBJENV(h_obj)) {
48374 duk_hobjenv *h_env;
48375 h_env = (duk_hobjenv *) h_obj;
48376
48377 duk__debug_getinfo_flags_key(thr, "target");
48378 duk_debug_write_heapptr(thr, (duk_heaphdr *) (h_env->target));
48379 duk__debug_getinfo_prop_bool(thr, "has_this", h_env->has_this);
48380 }
48381
48382#if defined(DUK_USE_BUFFEROBJECT_SUPPORT)
48383 if (DUK_HOBJECT_IS_BUFOBJ(h_obj)) {
48384 duk_hbufobj *h_bufobj;
48385 h_bufobj = (duk_hbufobj *) h_obj;
48386
48387 duk__debug_getinfo_prop_uint(thr, "slice_offset", h_bufobj->offset);
48388 duk__debug_getinfo_prop_uint(thr, "slice_length", h_bufobj->length);
48389 duk__debug_getinfo_prop_uint(thr, "elem_shift", (duk_uint_t) h_bufobj->shift);
48390 duk__debug_getinfo_prop_uint(thr, "elem_type", (duk_uint_t) h_bufobj->elem_type);
48391 duk__debug_getinfo_prop_bool(thr, "is_typedarray", (duk_uint_t) h_bufobj->is_typedarray);
48392 if (h_bufobj->buf != NULL) {
48393 duk__debug_getinfo_flags_key(thr, "buffer");
48394 duk_debug_write_heapptr(thr, (duk_heaphdr *) h_bufobj->buf);
48395 }
48396 }
48397#endif /* DUK_USE_BUFFEROBJECT_SUPPORT */
48398 break;
48399 }
48400 case DUK_HTYPE_BUFFER: {
48401 duk_hbuffer *h_buf;
48402
48403 h_buf = (duk_hbuffer *) h;
48404 duk__debug_getinfo_bitmask(thr,
48405 duk__debug_getinfo_hbuffer_keys,
48406 duk__debug_getinfo_hbuffer_masks,
48408 duk__debug_getinfo_prop_uint(thr, "size", (duk_uint_t) DUK_HBUFFER_GET_SIZE(h_buf));
48409 duk__debug_getinfo_flags_key(thr, "dataptr");
48410 duk_debug_write_pointer(thr, (void *) DUK_HBUFFER_GET_DATA_PTR(thr->heap, h_buf));
48411 duk__debug_getinfo_flags_key(thr, "data");
48412 duk_debug_write_hbuffer(thr, h_buf); /* tolerates NULL h_buf */
48413 break;
48414 }
48415 default: {
48416 /* Since we already started writing the reply, just emit nothing. */
48417 DUK_D(DUK_DPRINT("inspect target pointer has invalid heaphdr type"));
48418 }
48419 }
48420
48421 duk_debug_write_eom(thr);
48422}
48423
48424DUK_LOCAL void duk__debug_handle_get_obj_prop_desc(duk_hthread *thr, duk_heap *heap) {
48425 duk_heaphdr *h;
48426 duk_hobject *h_obj;
48427 duk_hstring *h_key;
48428 duk_propdesc desc;
48429
48430 DUK_D(DUK_DPRINT("debug command GetObjPropDesc"));
48431 DUK_UNREF(heap);
48432
48433 h = duk_debug_read_any_ptr(thr);
48434 if (!h) {
48435 duk_debug_write_error_eom(thr, DUK_DBG_ERR_UNKNOWN, "invalid target");
48436 return;
48437 }
48438 h_key = duk_debug_read_hstring(thr);
48439 if (h == NULL || DUK_HEAPHDR_GET_TYPE(h) != DUK_HTYPE_OBJECT || h_key == NULL) {
48440 goto fail_args;
48441 }
48442 h_obj = (duk_hobject *) h;
48443
48444 if (duk_hobject_get_own_propdesc(thr, h_obj, h_key, &desc, 0 /*flags*/)) {
48445 duk_int_t virtual_idx;
48446 duk_bool_t rc;
48447
48448 /* To use the shared helper need the virtual index. */
48449 DUK_ASSERT(desc.e_idx >= 0 || desc.a_idx >= 0);
48450 virtual_idx = (desc.a_idx >= 0 ? desc.a_idx : (duk_int_t) DUK_HOBJECT_GET_ASIZE(h_obj) + desc.e_idx);
48451
48452 duk_debug_write_reply(thr);
48453 rc = duk__debug_getprop_index(thr, heap, h_obj, (duk_uint_t) virtual_idx);
48454 DUK_ASSERT(rc == 1);
48455 DUK_UNREF(rc);
48456 duk_debug_write_eom(thr);
48457 } else {
48458 duk_debug_write_error_eom(thr, DUK_DBG_ERR_NOTFOUND, "not found");
48459 }
48460 return;
48461
48462fail_args:
48463 duk_debug_write_error_eom(thr, DUK_DBG_ERR_UNKNOWN, "invalid args");
48464}
48465
48466DUK_LOCAL void duk__debug_handle_get_obj_prop_desc_range(duk_hthread *thr, duk_heap *heap) {
48467 duk_heaphdr *h;
48468 duk_hobject *h_obj;
48469 duk_uint_t idx, idx_start, idx_end;
48470
48471 DUK_D(DUK_DPRINT("debug command GetObjPropDescRange"));
48472 DUK_UNREF(heap);
48473
48474 h = duk_debug_read_any_ptr(thr);
48475 idx_start = (duk_uint_t) duk_debug_read_int(thr);
48476 idx_end = (duk_uint_t) duk_debug_read_int(thr);
48477 if (h == NULL || DUK_HEAPHDR_GET_TYPE(h) != DUK_HTYPE_OBJECT) {
48478 goto fail_args;
48479 }
48480 h_obj = (duk_hobject *) h;
48481
48482 /* The index range space is conceptually the array part followed by the
48483 * entry part. Unlike normal enumeration all slots are exposed here as
48484 * is and return 'unused' if the slots are not in active use. In particular
48485 * the array part is included for the full a_size regardless of what the
48486 * array .length is.
48487 */
48488
48489 duk_debug_write_reply(thr);
48490 for (idx = idx_start; idx < idx_end; idx++) {
48491 if (!duk__debug_getprop_index(thr, heap, h_obj, idx)) {
48492 break;
48493 }
48494 }
48495 duk_debug_write_eom(thr);
48496 return;
48497
48498fail_args:
48499 duk_debug_write_error_eom(thr, DUK_DBG_ERR_UNKNOWN, "invalid args");
48500}
48501
48502#endif /* DUK_USE_DEBUGGER_INSPECT */
48503
48504/*
48505 * Process incoming debug requests
48506 *
48507 * Individual request handlers can push temporaries on the value stack and
48508 * rely on duk__debug_process_message() to restore the value stack top
48509 * automatically.
48510 */
48511
48512/* Process one debug message. Automatically restore value stack top to its
48513 * entry value, so that individual message handlers don't need exact value
48514 * stack handling which is convenient.
48515 */
48516DUK_LOCAL void duk__debug_process_message(duk_hthread *thr) {
48517 duk_heap *heap;
48518 duk_uint8_t x;
48519 duk_int32_t cmd;
48520 duk_idx_t entry_top;
48521
48522 DUK_ASSERT(thr != NULL);
48523 heap = thr->heap;
48524 DUK_ASSERT(heap != NULL);
48525
48526 entry_top = duk_get_top(thr);
48527
48528 x = duk_debug_read_byte(thr);
48529 switch (x) {
48530 case DUK_DBG_IB_REQUEST: {
48531 cmd = duk_debug_read_int(thr);
48532 switch (cmd) {
48533 case DUK_DBG_CMD_BASICINFO: {
48534 duk__debug_handle_basic_info(thr, heap);
48535 break;
48536 }
48538 duk__debug_handle_trigger_status(thr, heap);
48539 break;
48540 }
48541 case DUK_DBG_CMD_PAUSE: {
48542 duk__debug_handle_pause(thr, heap);
48543 break;
48544 }
48545 case DUK_DBG_CMD_RESUME: {
48546 duk__debug_handle_resume(thr, heap);
48547 break;
48548 }
48551 case DUK_DBG_CMD_STEPOUT: {
48552 duk__debug_handle_step(thr, heap, cmd);
48553 break;
48554 }
48555 case DUK_DBG_CMD_LISTBREAK: {
48556 duk__debug_handle_list_break(thr, heap);
48557 break;
48558 }
48559 case DUK_DBG_CMD_ADDBREAK: {
48560 duk__debug_handle_add_break(thr, heap);
48561 break;
48562 }
48563 case DUK_DBG_CMD_DELBREAK: {
48564 duk__debug_handle_del_break(thr, heap);
48565 break;
48566 }
48567 case DUK_DBG_CMD_GETVAR: {
48568 duk__debug_handle_get_var(thr, heap);
48569 break;
48570 }
48571 case DUK_DBG_CMD_PUTVAR: {
48572 duk__debug_handle_put_var(thr, heap);
48573 break;
48574 }
48576 duk__debug_handle_get_call_stack(thr, heap);
48577 break;
48578 }
48579 case DUK_DBG_CMD_GETLOCALS: {
48580 duk__debug_handle_get_locals(thr, heap);
48581 break;
48582 }
48583 case DUK_DBG_CMD_EVAL: {
48584 duk__debug_handle_eval(thr, heap);
48585 break;
48586 }
48587 case DUK_DBG_CMD_DETACH: {
48588 /* The actual detached_cb call is postponed to message loop so
48589 * we don't need any special precautions here (just skip to EOM
48590 * on the already closed connection).
48591 */
48592 duk__debug_handle_detach(thr, heap);
48593 break;
48594 }
48595#if defined(DUK_USE_DEBUGGER_DUMPHEAP)
48596 case DUK_DBG_CMD_DUMPHEAP: {
48597 duk__debug_handle_dump_heap(thr, heap);
48598 break;
48599 }
48600#endif /* DUK_USE_DEBUGGER_DUMPHEAP */
48602 duk__debug_handle_get_bytecode(thr, heap);
48603 break;
48604 }
48606 duk__debug_handle_apprequest(thr, heap);
48607 break;
48608 }
48609#if defined(DUK_USE_DEBUGGER_INSPECT)
48611 duk__debug_handle_get_heap_obj_info(thr, heap);
48612 break;
48613 }
48615 duk__debug_handle_get_obj_prop_desc(thr, heap);
48616 break;
48617 }
48619 duk__debug_handle_get_obj_prop_desc_range(thr, heap);
48620 break;
48621 }
48622#endif /* DUK_USE_DEBUGGER_INSPECT */
48623 default: {
48624 DUK_D(DUK_DPRINT("debug command unsupported: %d", (int) cmd));
48625 duk_debug_write_error_eom(thr, DUK_DBG_ERR_UNSUPPORTED, "unsupported command");
48626 }
48627 } /* switch cmd */
48628 break;
48629 }
48630 case DUK_DBG_IB_REPLY: {
48631 DUK_D(DUK_DPRINT("debug reply, skipping"));
48632 break;
48633 }
48634 case DUK_DBG_IB_ERROR: {
48635 DUK_D(DUK_DPRINT("debug error, skipping"));
48636 break;
48637 }
48638 case DUK_DBG_IB_NOTIFY: {
48639 DUK_D(DUK_DPRINT("debug notify, skipping"));
48640 break;
48641 }
48642 default: {
48643 DUK_D(DUK_DPRINT("invalid initial byte, drop connection: %d", (int) x));
48644 goto fail;
48645 }
48646 } /* switch initial byte */
48647
48648 DUK_ASSERT(duk_get_top(thr) >= entry_top);
48649 duk_set_top(thr, entry_top);
48650 duk__debug_skip_to_eom(thr);
48651 return;
48652
48653fail:
48654 DUK_ASSERT(duk_get_top(thr) >= entry_top);
48655 duk_set_top(thr, entry_top);
48656 DUK__SET_CONN_BROKEN(thr, 1);
48657 return;
48658}
48659
48660DUK_LOCAL void duk__check_resend_status(duk_hthread *thr) {
48661 if (thr->heap->dbg_read_cb != NULL && thr->heap->dbg_state_dirty) {
48662 duk_debug_send_status(thr);
48663 thr->heap->dbg_state_dirty = 0;
48664 }
48665}
48666
48667DUK_INTERNAL duk_bool_t duk_debug_process_messages(duk_hthread *thr, duk_bool_t no_block) {
48668#if defined(DUK_USE_ASSERTIONS)
48669 duk_idx_t entry_top;
48670#endif
48671 duk_bool_t retval = 0;
48672
48673 DUK_ASSERT(thr != NULL);
48674 DUK_ASSERT(thr->heap != NULL);
48675#if defined(DUK_USE_ASSERTIONS)
48676 entry_top = duk_get_top(thr);
48677#endif
48678
48679 DUK_D(DUK_DPRINT("process debug messages: read_cb=%s, no_block=%ld, detaching=%ld, processing=%ld",
48680 thr->heap->dbg_read_cb ? "not NULL" : "NULL",
48681 (long) no_block,
48682 (long) thr->heap->dbg_detaching,
48683 (long) thr->heap->dbg_processing));
48684 DUK_DD(DUK_DDPRINT("top at entry: %ld", (long) duk_get_top(thr)));
48685
48686 /* thr->heap->dbg_detaching may be != 0 if a debugger write outside
48687 * the message loop caused a transport error and detach1() to run.
48688 */
48689 DUK_ASSERT(thr->heap->dbg_detaching == 0 || thr->heap->dbg_detaching == 1);
48690 DUK_ASSERT(thr->heap->dbg_processing == 0);
48691 thr->heap->dbg_processing = 1;
48692
48693 /* Ensure dirty state causes a Status even if never process any
48694 * messages. This is expected by the bytecode executor when in
48695 * the running state.
48696 */
48697 duk__check_resend_status(thr);
48698
48699 for (;;) {
48700 /* Process messages until we're no longer paused or we peek
48701 * and see there's nothing to read right now.
48702 */
48703 DUK_DD(DUK_DDPRINT("top at loop top: %ld", (long) duk_get_top(thr)));
48704 DUK_ASSERT(thr->heap->dbg_processing == 1);
48705
48706 while (thr->heap->dbg_read_cb == NULL && thr->heap->dbg_detaching) {
48707 /* Detach is pending; can be triggered from outside the
48708 * debugger loop (e.g. Status notify write error) or by
48709 * previous message handling. Call detached callback
48710 * here, in a controlled state, to ensure a possible
48711 * reattach inside the detached_cb is handled correctly.
48712 *
48713 * Recheck for detach in a while loop: an immediate
48714 * reattach involves a call to duk_debugger_attach()
48715 * which writes a debugger handshake line immediately
48716 * inside the API call. If the transport write fails
48717 * for that handshake, we can immediately end up in a
48718 * "transport broken, detaching" case several times here.
48719 * Loop back until we're either cleanly attached or
48720 * fully detached.
48721 *
48722 * NOTE: Reset dbg_processing = 1 forcibly, in case we
48723 * re-attached; duk_debugger_attach() sets dbg_processing
48724 * to 0 at the moment.
48725 */
48726
48727 DUK_D(DUK_DPRINT("detach pending (dbg_read_cb == NULL, dbg_detaching != 0), call detach2"));
48728
48729 duk__debug_do_detach2(thr->heap);
48730 thr->heap->dbg_processing = 1; /* may be set to 0 by duk_debugger_attach() inside callback */
48731
48732 DUK_D(DUK_DPRINT("after detach2 (and possible reattach): dbg_read_cb=%s, dbg_detaching=%ld",
48733 thr->heap->dbg_read_cb ? "not NULL" : "NULL",
48734 (long) thr->heap->dbg_detaching));
48735 }
48736 DUK_ASSERT(thr->heap->dbg_detaching == 0); /* true even with reattach */
48737 DUK_ASSERT(thr->heap->dbg_processing == 1); /* even after a detach and possible reattach */
48738
48739 if (thr->heap->dbg_read_cb == NULL) {
48740 DUK_D(DUK_DPRINT("debug connection broken (and not detaching), stop processing messages"));
48741 break;
48742 }
48743
48744 if (!DUK_HEAP_HAS_DEBUGGER_PAUSED(thr->heap) || no_block) {
48745 if (!duk_debug_read_peek(thr)) {
48746 /* Note: peek cannot currently trigger a detach
48747 * so the dbg_detaching == 0 assert outside the
48748 * loop is correct.
48749 */
48750 DUK_D(DUK_DPRINT("processing debug message, peek indicated no data, stop processing messages"));
48751 break;
48752 }
48753 DUK_D(DUK_DPRINT("processing debug message, peek indicated there is data, handle it"));
48754 } else {
48755 DUK_D(DUK_DPRINT("paused, process debug message, blocking if necessary"));
48756 }
48757
48758 duk__check_resend_status(thr);
48759 duk__debug_process_message(thr);
48760 duk__check_resend_status(thr);
48761
48762 retval = 1; /* processed one or more messages */
48763 }
48764
48765 DUK_ASSERT(thr->heap->dbg_detaching == 0);
48766 DUK_ASSERT(thr->heap->dbg_processing == 1);
48767 thr->heap->dbg_processing = 0;
48768
48769 /* As an initial implementation, read flush after exiting the message
48770 * loop. If transport is broken, this is a no-op (with debug logs).
48771 */
48772 duk_debug_read_flush(thr); /* this cannot initiate a detach */
48773 DUK_ASSERT(thr->heap->dbg_detaching == 0);
48774
48775 DUK_DD(DUK_DDPRINT("top at exit: %ld", (long) duk_get_top(thr)));
48776
48777#if defined(DUK_USE_ASSERTIONS)
48778 /* Easy to get wrong, so assert for it. */
48779 DUK_ASSERT(entry_top == duk_get_top(thr));
48780#endif
48781
48782 return retval;
48783}
48784
48785/*
48786 * Halt execution helper
48787 */
48788
48789/* Halt execution and enter a debugger message loop until execution is resumed
48790 * by the client. PC for the current activation may be temporarily decremented
48791 * so that the "current" instruction will be shown by the client. This helper
48792 * is callable from anywhere, also outside bytecode executor.
48793 */
48794
48795DUK_INTERNAL void duk_debug_halt_execution(duk_hthread *thr, duk_bool_t use_prev_pc) {
48796 duk_activation *act;
48797 duk_hcompfunc *fun;
48798 duk_instr_t *old_pc = NULL;
48799
48800 DUK_ASSERT(thr != NULL);
48801 DUK_ASSERT(thr->heap != NULL);
48802 DUK_ASSERT(duk_debug_is_attached(thr->heap));
48803 DUK_ASSERT(thr->heap->dbg_processing == 0);
48804 DUK_ASSERT(!duk_debug_is_paused(thr->heap));
48805
48806 duk_debug_set_paused(thr->heap);
48807
48808 act = thr->callstack_curr;
48809
48810 /* NOTE: act may be NULL if an error is thrown outside of any activation,
48811 * which may happen in the case of, e.g. syntax errors.
48812 */
48813
48814 /* Decrement PC if that was requested, this requires a PC sync. */
48815 if (act != NULL) {
48817 old_pc = act->curr_pc;
48818 fun = (duk_hcompfunc *) DUK_ACT_GET_FUNC(act);
48819
48820 /* Short circuit if is safe: if act->curr_pc != NULL, 'fun' is
48821 * guaranteed to be a non-NULL ECMAScript function.
48822 */
48823 DUK_ASSERT(act->curr_pc == NULL || (fun != NULL && DUK_HOBJECT_IS_COMPFUNC((duk_hobject *) fun)));
48824 if (use_prev_pc && act->curr_pc != NULL && act->curr_pc > DUK_HCOMPFUNC_GET_CODE_BASE(thr->heap, fun)) {
48825 act->curr_pc--;
48826 }
48827 }
48828
48829 /* Process debug messages until we are no longer paused. */
48830
48831 /* NOTE: This is a bit fragile. It's important to ensure that
48832 * duk_debug_process_messages() never throws an error or
48833 * act->curr_pc will never be reset.
48834 */
48835
48836 thr->heap->dbg_state_dirty = 1;
48837 while (DUK_HEAP_HAS_DEBUGGER_PAUSED(thr->heap)) {
48838 DUK_ASSERT(duk_debug_is_attached(thr->heap));
48839 DUK_ASSERT(thr->heap->dbg_processing == 0);
48840 duk_debug_process_messages(thr, 0 /*no_block*/);
48841 }
48842
48843 /* XXX: Decrementing and restoring act->curr_pc works now, but if the
48844 * debugger message loop gains the ability to adjust the current PC
48845 * (e.g. a forced jump) restoring the PC here will break. Another
48846 * approach would be to use a state flag for the "decrement 1 from
48847 * topmost activation's PC" and take it into account whenever dealing
48848 * with PC values.
48849 */
48850 if (act != NULL) {
48851 act->curr_pc = old_pc; /* restore PC */
48852 }
48853}
48854
48855/*
48856 * Breakpoint management
48857 */
48858
48859DUK_INTERNAL duk_small_int_t duk_debug_add_breakpoint(duk_hthread *thr, duk_hstring *filename, duk_uint32_t line) {
48860 duk_heap *heap;
48861 duk_breakpoint *b;
48862
48863 /* Caller must trigger recomputation of active breakpoint list. To
48864 * ensure stale values are not used if that doesn't happen, clear the
48865 * active breakpoint list here.
48866 */
48867
48868 DUK_ASSERT(thr != NULL);
48869 DUK_ASSERT(filename != NULL);
48870 heap = thr->heap;
48871 DUK_ASSERT(heap != NULL);
48872
48873 if (heap->dbg_breakpoint_count >= DUK_HEAP_MAX_BREAKPOINTS) {
48874 DUK_D(DUK_DPRINT("failed to add breakpoint for %O:%ld, all breakpoint slots used",
48875 (duk_heaphdr *) filename,
48876 (long) line));
48877 return -1;
48878 }
48879 heap->dbg_breakpoints_active[0] = (duk_breakpoint *) NULL;
48880 b = heap->dbg_breakpoints + (heap->dbg_breakpoint_count++);
48881 b->filename = filename;
48882 b->line = line;
48883 DUK_HSTRING_INCREF(thr, filename);
48884
48885 return (duk_small_int_t) (heap->dbg_breakpoint_count - 1); /* index */
48886}
48887
48888DUK_INTERNAL duk_bool_t duk_debug_remove_breakpoint(duk_hthread *thr, duk_small_uint_t breakpoint_index) {
48889 duk_heap *heap;
48890 duk_hstring *h;
48891 duk_breakpoint *b;
48892 duk_size_t move_size;
48893
48894 /* Caller must trigger recomputation of active breakpoint list. To
48895 * ensure stale values are not used if that doesn't happen, clear the
48896 * active breakpoint list here.
48897 */
48898
48899 DUK_ASSERT(thr != NULL);
48900 heap = thr->heap;
48901 DUK_ASSERT(heap != NULL);
48902 DUK_ASSERT(duk_debug_is_attached(thr->heap));
48903 DUK_ASSERT_DISABLE(breakpoint_index >= 0); /* unsigned */
48904
48905 if (breakpoint_index >= heap->dbg_breakpoint_count) {
48906 DUK_D(DUK_DPRINT("invalid breakpoint index: %ld", (long) breakpoint_index));
48907 return 0;
48908 }
48909 b = heap->dbg_breakpoints + breakpoint_index;
48910
48911 h = b->filename;
48912 DUK_ASSERT(h != NULL);
48913
48914 move_size = sizeof(duk_breakpoint) * (heap->dbg_breakpoint_count - breakpoint_index - 1);
48915 duk_memmove((void *) b, (const void *) (b + 1), (size_t) move_size);
48916
48917 heap->dbg_breakpoint_count--;
48918 heap->dbg_breakpoints_active[0] = (duk_breakpoint *) NULL;
48919
48920 DUK_HSTRING_DECREF(thr, h); /* side effects */
48921 DUK_UNREF(h); /* w/o refcounting */
48922
48923 /* Breakpoint entries above the used area are left as garbage. */
48924
48925 return 1;
48926}
48927
48928/*
48929 * Misc state management
48930 */
48931
48932DUK_INTERNAL duk_bool_t duk_debug_is_attached(duk_heap *heap) {
48933 return (heap->dbg_read_cb != NULL);
48934}
48935
48936DUK_INTERNAL duk_bool_t duk_debug_is_paused(duk_heap *heap) {
48937 return (DUK_HEAP_HAS_DEBUGGER_PAUSED(heap) != 0);
48938}
48939
48940DUK_INTERNAL void duk_debug_set_paused(duk_heap *heap) {
48941 if (duk_debug_is_paused(heap)) {
48942 DUK_D(DUK_DPRINT("trying to set paused state when already paused, ignoring"));
48943 } else {
48945 heap->dbg_state_dirty = 1;
48946 duk_debug_clear_pause_state(heap);
48947 DUK_ASSERT(heap->ms_running == 0); /* debugger can't be triggered within mark-and-sweep */
48948 heap->ms_running = 2; /* prevent mark-and-sweep, prevent refzero queueing */
48949 heap->ms_prevent_count++;
48950 DUK_ASSERT(heap->ms_prevent_count != 0); /* Wrap. */
48951 DUK_ASSERT(heap->heap_thread != NULL);
48952 }
48953}
48954
48955DUK_INTERNAL void duk_debug_clear_paused(duk_heap *heap) {
48956 if (duk_debug_is_paused(heap)) {
48958 heap->dbg_state_dirty = 1;
48959 duk_debug_clear_pause_state(heap);
48960 DUK_ASSERT(heap->ms_running == 2);
48961 DUK_ASSERT(heap->ms_prevent_count > 0);
48962 heap->ms_prevent_count--;
48963 heap->ms_running = 0;
48964 DUK_ASSERT(heap->heap_thread != NULL);
48965 } else {
48966 DUK_D(DUK_DPRINT("trying to clear paused state when not paused, ignoring"));
48967 }
48968}
48969
48970DUK_INTERNAL void duk_debug_clear_pause_state(duk_heap *heap) {
48971 heap->dbg_pause_flags = 0;
48972 heap->dbg_pause_act = NULL;
48973 heap->dbg_pause_startline = 0;
48974}
48975
48976#else /* DUK_USE_DEBUGGER_SUPPORT */
48977
48978/* No debugger support. */
48979
48980#endif /* DUK_USE_DEBUGGER_SUPPORT */
48981
48982/* automatic undefs */
48983#undef DUK__DBG_TPORT_ENTER
48984#undef DUK__DBG_TPORT_EXIT
48985#undef DUK__SET_CONN_BROKEN
48986/*
48987 * Augmenting errors at their creation site and their throw site.
48988 *
48989 * When errors are created, traceback data is added by built-in code
48990 * and a user error handler (if defined) can process or replace the
48991 * error. Similarly, when errors are thrown, a user error handler
48992 * (if defined) can process or replace the error.
48993 *
48994 * Augmentation and other processing at error creation time is nice
48995 * because an error is only created once, but it may be thrown and
48996 * rethrown multiple times. User error handler registered for processing
48997 * an error at its throw site must be careful to handle rethrowing in
48998 * a useful manner.
48999 *
49000 * Error augmentation may throw an internal error (e.g. alloc error).
49001 *
49002 * ECMAScript allows throwing any values, so all values cannot be
49003 * augmented. Currently, the built-in augmentation at error creation
49004 * only augments error values which are Error instances (= have the
49005 * built-in Error.prototype in their prototype chain) and are also
49006 * extensible. User error handlers have no limitations in this respect.
49007 */
49008
49009/* #include duk_internal.h -> already included */
49010
49011/*
49012 * Helper for calling a user error handler.
49013 *
49014 * 'thr' must be the currently active thread; the error handler is called
49015 * in its context. The valstack of 'thr' must have the error value on
49016 * top, and will be replaced by another error value based on the return
49017 * value of the error handler.
49018 *
49019 * The helper calls duk_handle_call() recursively in protected mode.
49020 * Before that call happens, no longjmps should happen; as a consequence,
49021 * we must assume that the valstack contains enough temporary space for
49022 * arguments and such.
49023 *
49024 * While the error handler runs, any errors thrown will not trigger a
49025 * recursive error handler call (this is implemented using a heap level
49026 * flag which will "follow" through any coroutines resumed inside the
49027 * error handler). If the error handler is not callable or throws an
49028 * error, the resulting error replaces the original error (for Duktape
49029 * internal errors, duk_error_throw.c further substitutes this error with
49030 * a DoubleError which is not ideal). This would be easy to change and
49031 * even signal to the caller.
49032 *
49033 * The user error handler is stored in 'Duktape.errCreate' or
49034 * 'Duktape.errThrow' depending on whether we're augmenting the error at
49035 * creation or throw time. There are several alternatives to this approach,
49036 * see doc/error-objects.rst for discussion.
49037 *
49038 * Note: since further longjmp()s may occur while calling the error handler
49039 * (for many reasons, e.g. a labeled 'break' inside the handler), the
49040 * caller can make no assumptions on the thr->heap->lj state after the
49041 * call (this affects especially duk_error_throw.c). This is not an issue
49042 * as long as the caller writes to the lj state only after the error handler
49043 * finishes.
49044 */
49045
49046#if defined(DUK_USE_ERRTHROW) || defined(DUK_USE_ERRCREATE)
49048 duk_tval *tv_hnd;
49049 duk_int_t rc;
49050
49051 DUK_ASSERT(thr != NULL);
49052 DUK_ASSERT(thr->heap != NULL);
49053 DUK_ASSERT_STRIDX_VALID(stridx_cb);
49054
49055 if (thr->heap->augmenting_error) {
49056 DUK_D(DUK_DPRINT("recursive call to error augmentation, ignore"));
49057 return;
49058 }
49059
49060 /*
49061 * Check whether or not we have an error handler.
49062 *
49063 * We must be careful of not triggering an error when looking up the
49064 * property. For instance, if the property is a getter, we don't want
49065 * to call it, only plain values are allowed. The value, if it exists,
49066 * is not checked. If the value is not a function, a TypeError happens
49067 * when it is called and that error replaces the original one.
49068 */
49069
49070 DUK_ASSERT_VALSTACK_SPACE(thr, 4); /* 3 entries actually needed below */
49071
49072 /* [ ... errval ] */
49073
49074 if (thr->builtins[DUK_BIDX_DUKTAPE] == NULL) {
49075 /* When creating built-ins, some of the built-ins may not be set
49076 * and we want to tolerate that when throwing errors.
49077 */
49078 DUK_DD(DUK_DDPRINT("error occurred when DUK_BIDX_DUKTAPE is NULL, ignoring"));
49079 return;
49080 }
49082 if (tv_hnd == NULL) {
49083 DUK_DD(DUK_DDPRINT("error handler does not exist or is not a plain value: %!T", (duk_tval *) tv_hnd));
49084 return;
49085 }
49086 DUK_DDD(DUK_DDDPRINT("error handler dump (callability not checked): %!T", (duk_tval *) tv_hnd));
49087 duk_push_tval(thr, tv_hnd);
49088
49089 /* [ ... errval errhandler ] */
49090
49091 duk_insert(thr, -2); /* -> [ ... errhandler errval ] */
49092 duk_push_undefined(thr);
49093 duk_insert(thr, -2); /* -> [ ... errhandler undefined(= this) errval ] */
49094
49095 /* [ ... errhandler undefined errval ] */
49096
49097 /*
49098 * heap->augmenting_error prevents recursive re-entry and also causes
49099 * call handling to use a larger (but not unbounded) call stack limit
49100 * for the duration of error augmentation.
49101 *
49102 * We ignore errors now: a success return and an error value both
49103 * replace the original error value. (This would be easy to change.)
49104 */
49105
49106 DUK_ASSERT(thr->heap->augmenting_error == 0);
49107 thr->heap->augmenting_error = 1;
49108
49109 rc = duk_pcall_method(thr, 1);
49110 DUK_UNREF(rc); /* no need to check now: both success and error are OK */
49111
49113 thr->heap->augmenting_error = 0;
49114
49115 /* [ ... errval ] */
49116}
49117#endif /* DUK_USE_ERRTHROW || DUK_USE_ERRCREATE */
49118
49119/*
49120 * Add ._Tracedata to an error on the stack top.
49121 */
49122
49123#if defined(DUK_USE_TRACEBACKS)
49125 duk_hthread *thr_callstack,
49126 const char *c_filename,
49127 duk_int_t c_line,
49128 duk_small_uint_t flags) {
49129 duk_activation *act;
49130 duk_int_t depth;
49131 duk_int_t arr_size;
49132 duk_tval *tv;
49133 duk_hstring *s;
49134 duk_uint32_t u32;
49135 duk_double_t d;
49136
49137 DUK_ASSERT(thr != NULL);
49138 DUK_ASSERT(thr_callstack != NULL);
49139
49140 /* [ ... error ] */
49141
49142 /*
49143 * The traceback format is pretty arcane in an attempt to keep it compact
49144 * and cheap to create. It may change arbitrarily from version to version.
49145 * It should be decoded/accessed through version specific accessors only.
49146 *
49147 * See doc/error-objects.rst.
49148 */
49149
49150 DUK_DDD(DUK_DDDPRINT("adding traceback to object: %!T", (duk_tval *) duk_get_tval(thr, -1)));
49151
49152 /* Preallocate array to correct size, so that we can just write out
49153 * the _Tracedata values into the array part.
49154 */
49155 act = thr->callstack_curr;
49157 DUK_ASSERT(thr_callstack->callstack_top <= DUK_INT_MAX); /* callstack limits */
49158 if (depth > (duk_int_t) thr_callstack->callstack_top) {
49159 depth = (duk_int_t) thr_callstack->callstack_top;
49160 }
49161 if (depth > 0) {
49162 if (flags & DUK_AUGMENT_FLAG_SKIP_ONE) {
49163 DUK_ASSERT(act != NULL);
49164 act = act->parent;
49165 depth--;
49166 }
49167 }
49168 arr_size = depth * 2;
49169 if (thr->compile_ctx != NULL && thr->compile_ctx->h_filename != NULL) {
49170 arr_size += 2;
49171 }
49172 if (c_filename) {
49173 /* We need the C filename to be interned before getting the
49174 * array part pointer to avoid any GC interference while the
49175 * array part is populated.
49176 */
49177 duk_push_string(thr, c_filename);
49178 arr_size += 2;
49179 }
49180
49181 /* XXX: Uninitialized would be OK. Maybe add internal primitive to
49182 * push bare duk_harray with size?
49183 */
49184 DUK_D(DUK_DPRINT("preallocated _Tracedata to %ld items", (long) arr_size));
49185 tv = duk_push_harray_with_size_outptr(thr, (duk_uint32_t) arr_size);
49186 duk_clear_prototype(thr, -1);
49188 DUK_ASSERT(arr_size == 0 || tv != NULL);
49189
49190 /* Compiler SyntaxErrors (and other errors) come first, and are
49191 * blamed by default (not flagged "noblame").
49192 */
49193 if (thr->compile_ctx != NULL && thr->compile_ctx->h_filename != NULL) {
49194 s = thr->compile_ctx->h_filename;
49195 DUK_TVAL_SET_STRING(tv, s);
49196 DUK_HSTRING_INCREF(thr, s);
49197 tv++;
49198
49199 u32 = (duk_uint32_t) thr->compile_ctx->curr_token.start_line; /* (flags<<32) + (line), flags = 0 */
49200 DUK_TVAL_SET_U32(tv, u32);
49201 tv++;
49202 }
49203
49204 /* Filename/line from C macros (__FILE__, __LINE__) are added as an
49205 * entry with a special format: (string, number). The number contains
49206 * the line and flags.
49207 */
49208
49209 /* [ ... error c_filename? arr ] */
49210
49211 if (c_filename) {
49213 s = DUK_TVAL_GET_STRING(thr->valstack_top - 2); /* interned c_filename */
49214 DUK_ASSERT(s != NULL);
49215 DUK_TVAL_SET_STRING(tv, s);
49216 DUK_HSTRING_INCREF(thr, s);
49217 tv++;
49218
49219 d = ((flags & DUK_AUGMENT_FLAG_NOBLAME_FILELINE) ?
49221 0.0) +
49222 (duk_double_t) c_line;
49223 DUK_TVAL_SET_DOUBLE(tv, d);
49224 tv++;
49225 }
49226
49227 /* Traceback depth doesn't take into account the filename/line
49228 * special handling above (intentional).
49229 */
49230 for (; depth-- > 0; act = act->parent) {
49231 duk_uint32_t pc;
49232 duk_tval *tv_src;
49233
49234 /* [... arr] */
49235
49236 DUK_ASSERT(act != NULL); /* depth check above, assumes book-keeping is correct */
49237 DUK_ASSERT_DISABLE(act->pc >= 0); /* unsigned */
49238
49239 /* Add function object. */
49240 tv_src = &act->tv_func; /* object (function) or lightfunc */
49242 DUK_TVAL_SET_TVAL(tv, tv_src);
49243 DUK_TVAL_INCREF(thr, tv);
49244 tv++;
49245
49246 /* Add a number containing: pc, activation flags.
49247 *
49248 * PC points to next instruction, find offending PC. Note that
49249 * PC == 0 for native code.
49250 */
49251 pc = (duk_uint32_t) duk_hthread_get_act_prev_pc(thr_callstack, act);
49252 DUK_ASSERT_DISABLE(pc >= 0); /* unsigned */
49253 DUK_ASSERT((duk_double_t) pc < DUK_DOUBLE_2TO32); /* assume PC is at most 32 bits and non-negative */
49254 d = ((duk_double_t) act->flags) * DUK_DOUBLE_2TO32 + (duk_double_t) pc;
49255 DUK_TVAL_SET_DOUBLE(tv, d);
49256 tv++;
49257 }
49258
49259#if defined(DUK_USE_ASSERTIONS)
49260 {
49261 duk_harray *a;
49262 a = (duk_harray *) duk_known_hobject(thr, -1);
49263 DUK_ASSERT(a != NULL);
49264 DUK_ASSERT((duk_uint32_t) (tv - DUK_HOBJECT_A_GET_BASE(thr->heap, (duk_hobject *) a)) == a->length);
49265 DUK_ASSERT(a->length == (duk_uint32_t) arr_size);
49267 }
49268#endif
49269
49270 /* [ ... error c_filename? arr ] */
49271
49272 if (c_filename) {
49273 duk_remove_m2(thr);
49274 }
49275
49276 /* [ ... error arr ] */
49277
49278 duk_xdef_prop_stridx_short_wec(thr, -2, DUK_STRIDX_INT_TRACEDATA); /* -> [ ... error ] */
49279}
49280#endif /* DUK_USE_TRACEBACKS */
49281
49282/*
49283 * Add .fileName and .lineNumber to an error on the stack top.
49284 */
49285
49286#if defined(DUK_USE_AUGMENT_ERROR_CREATE) && !defined(DUK_USE_TRACEBACKS)
49287DUK_LOCAL void duk__add_fileline(duk_hthread *thr,
49288 duk_hthread *thr_callstack,
49289 const char *c_filename,
49290 duk_int_t c_line,
49291 duk_small_uint_t flags) {
49292#if defined(DUK_USE_ASSERTIONS)
49293 duk_int_t entry_top;
49294#endif
49295
49296#if defined(DUK_USE_ASSERTIONS)
49297 entry_top = duk_get_top(thr);
49298#endif
49299
49300 /*
49301 * If tracebacks are disabled, 'fileName' and 'lineNumber' are added
49302 * as plain own properties. Since Error.prototype has accessors of
49303 * the same name, we need to define own properties directly (cannot
49304 * just use e.g. duk_put_prop_stridx). Existing properties are not
49305 * overwritten in case they already exist.
49306 */
49307
49308 if (thr->compile_ctx != NULL && thr->compile_ctx->h_filename != NULL) {
49309 /* Compiler SyntaxError (or other error) gets the primary blame.
49310 * Currently no flag to prevent blaming.
49311 */
49314 } else if (c_filename && (flags & DUK_AUGMENT_FLAG_NOBLAME_FILELINE) == 0) {
49315 /* C call site gets blamed next, unless flagged not to do so.
49316 * XXX: file/line is disabled in minimal builds, so disable this
49317 * too when appropriate.
49318 */
49319 duk_push_int(thr, c_line);
49320 duk_push_string(thr, c_filename);
49321 } else {
49322 /* Finally, blame the innermost callstack entry which has a
49323 * .fileName property.
49324 */
49325 duk_small_uint_t depth;
49326 duk_uint32_t ecma_line;
49327 duk_activation *act;
49328
49329 DUK_ASSERT(thr_callstack->callstack_top <= DUK_INT_MAX); /* callstack limits */
49331 if (depth > thr_callstack->callstack_top) {
49332 depth = thr_callstack->callstack_top;
49333 }
49334 for (act = thr_callstack->callstack_curr; depth-- > 0; act = act->parent) {
49335 duk_hobject *func;
49336 duk_uint32_t pc;
49337
49338 DUK_ASSERT(act != NULL);
49339 func = DUK_ACT_GET_FUNC(act);
49340 if (func == NULL) {
49341 /* Lightfunc, not blamed now. */
49342 continue;
49343 }
49344
49345 /* PC points to next instruction, find offending PC,
49346 * PC == 0 for native code.
49347 */
49349 thr,
49350 act); /* thr argument only used for thr->heap, so specific thread doesn't matter */
49351 DUK_UNREF(pc);
49352 DUK_ASSERT_DISABLE(pc >= 0); /* unsigned */
49353 DUK_ASSERT((duk_double_t) pc < DUK_DOUBLE_2TO32); /* assume PC is at most 32 bits and non-negative */
49354
49355 duk_push_hobject(thr, func);
49356
49357 /* [ ... error func ] */
49358
49360 if (!duk_is_string_notsymbol(thr, -1)) {
49361 duk_pop_2(thr);
49362 continue;
49363 }
49364
49365 /* [ ... error func fileName ] */
49366
49367 ecma_line = 0;
49368#if defined(DUK_USE_PC2LINE)
49369 if (DUK_HOBJECT_IS_COMPFUNC(func)) {
49370 ecma_line = duk_hobject_pc2line_query(thr, -2, (duk_uint_fast32_t) pc);
49371 } else {
49372 /* Native function, no relevant lineNumber. */
49373 }
49374#endif /* DUK_USE_PC2LINE */
49375 duk_push_u32(thr, ecma_line);
49376
49377 /* [ ... error func fileName lineNumber ] */
49378
49379 duk_replace(thr, -3);
49380
49381 /* [ ... error lineNumber fileName ] */
49382 goto define_props;
49383 }
49384
49385 /* No activation matches, use undefined for both .fileName and
49386 * .lineNumber (matches what we do with a _Tracedata based
49387 * no-match lookup.
49388 */
49389 duk_push_undefined(thr);
49390 duk_push_undefined(thr);
49391 }
49392
49393define_props:
49394 /* [ ... error lineNumber fileName ] */
49395#if defined(DUK_USE_ASSERTIONS)
49396 DUK_ASSERT(duk_get_top(thr) == entry_top + 2);
49397#endif
49400}
49401#endif /* DUK_USE_AUGMENT_ERROR_CREATE && !DUK_USE_TRACEBACKS */
49402
49403/*
49404 * Add line number to a compiler error.
49405 */
49406
49407#if defined(DUK_USE_AUGMENT_ERROR_CREATE)
49409 /* Append a "(line NNN)" to the "message" property of any error
49410 * thrown during compilation. Usually compilation errors are
49411 * SyntaxErrors but they can also be out-of-memory errors and
49412 * the like.
49413 */
49414
49415 /* [ ... error ] */
49416
49417 DUK_ASSERT(duk_is_object(thr, -1));
49418
49419 if (!(thr->compile_ctx != NULL && thr->compile_ctx->h_filename != NULL)) {
49420 return;
49421 }
49422
49423 DUK_DDD(DUK_DDDPRINT("compile error, before adding line info: %!T", (duk_tval *) duk_get_tval(thr, -1)));
49424
49426 duk_bool_t at_end;
49427
49428 /* Best guesstimate that error occurred at end of input, token
49429 * truncated by end of input, etc.
49430 */
49431#if 0
49432 at_end = (thr->compile_ctx->curr_token.start_offset + 1 >= thr->compile_ctx->lex.input_length);
49433 at_end = (thr->compile_ctx->lex.window[0].codepoint < 0 || thr->compile_ctx->lex.window[1].codepoint < 0);
49434#endif
49435 at_end = (thr->compile_ctx->lex.window[0].codepoint < 0);
49436
49437 DUK_D(DUK_DPRINT("syntax error, determined at_end=%ld; curr_token.start_offset=%ld, "
49438 "lex.input_length=%ld, window[0].codepoint=%ld, window[1].codepoint=%ld",
49439 (long) at_end,
49440 (long) thr->compile_ctx->curr_token.start_offset,
49441 (long) thr->compile_ctx->lex.input_length,
49442 (long) thr->compile_ctx->lex.window[0].codepoint,
49443 (long) thr->compile_ctx->lex.window[1].codepoint));
49444
49445 duk_push_sprintf(thr,
49446 " (line %ld%s)",
49447 (long) thr->compile_ctx->curr_token.start_line,
49448 at_end ? ", end of input" : "");
49449 duk_concat(thr, 2);
49451 } else {
49452 duk_pop(thr);
49454
49455 DUK_DDD(DUK_DDDPRINT("compile error, after adding line info: %!T", (duk_tval *) duk_get_tval(thr, -1)));
49456}
49457#endif /* DUK_USE_AUGMENT_ERROR_CREATE */
49458
49459/*
49460 * Augment an error being created using Duktape specific properties
49461 * like _Tracedata or .fileName/.lineNumber.
49462 */
49463
49464#if defined(DUK_USE_AUGMENT_ERROR_CREATE)
49466 duk_hthread *thr_callstack,
49467 const char *c_filename,
49468 duk_int_t c_line,
49469 duk_hobject *obj,
49470 duk_small_uint_t flags) {
49471#if defined(DUK_USE_ASSERTIONS)
49472 duk_int_t entry_top;
49473#endif
49474
49475#if defined(DUK_USE_ASSERTIONS)
49476 entry_top = duk_get_top(thr);
49477#endif
49478 DUK_ASSERT(obj != NULL);
49479
49480 DUK_UNREF(obj); /* unreferenced w/o tracebacks */
49481
49483
49484#if defined(DUK_USE_TRACEBACKS)
49485 /* If tracebacks are enabled, the '_Tracedata' property is the only
49486 * thing we need: 'fileName' and 'lineNumber' are virtual properties
49487 * which use '_Tracedata'. (Check _Tracedata only as own property.)
49488 */
49490 DUK_DDD(DUK_DDDPRINT("error value already has a '_Tracedata' property, not modifying it"));
49491 } else {
49492 duk__add_traceback(thr, thr_callstack, c_filename, c_line, flags);
49493 }
49494#else
49495 /* Without tracebacks the concrete .fileName and .lineNumber need
49496 * to be added directly.
49497 */
49498 duk__add_fileline(thr, thr_callstack, c_filename, c_line, flags);
49499#endif
49500
49501#if defined(DUK_USE_ASSERTIONS)
49502 DUK_ASSERT(duk_get_top(thr) == entry_top);
49503#endif
49504}
49505#endif /* DUK_USE_AUGMENT_ERROR_CREATE */
49506
49507/*
49508 * Augment an error at creation time with _Tracedata/fileName/lineNumber
49509 * and allow a user error handler (if defined) to process/replace the error.
49510 * The error to be augmented is at the stack top.
49512 * thr: thread containing the error value
49513 * thr_callstack: thread which should be used for generating callstack etc.
49514 * c_filename: C __FILE__ related to the error
49515 * c_line: C __LINE__ related to the error
49516 * flags & DUK_AUGMENT_FLAG_NOBLAME_FILELINE:
49517 * if true, don't fileName/line as error source, otherwise use traceback
49518 * (needed because user code filename/line are reported but internal ones
49519 * are not)
49520 */
49521
49522#if defined(DUK_USE_AUGMENT_ERROR_CREATE)
49524 duk_hthread *thr_callstack,
49525 const char *c_filename,
49526 duk_int_t c_line,
49527 duk_small_uint_t flags) {
49528 duk_hobject *obj;
49529
49530 DUK_ASSERT(thr != NULL);
49531 DUK_ASSERT(thr_callstack != NULL);
49532
49533 /* [ ... error ] */
49534
49535 /*
49536 * Criteria for augmenting:
49537 *
49538 * - augmentation enabled in build (naturally)
49539 * - error value internal prototype chain contains the built-in
49540 * Error prototype object (i.e. 'val instanceof Error')
49541 *
49542 * Additional criteria for built-in augmenting:
49543 *
49544 * - error value is an extensible object
49545 */
49546
49547 obj = duk_get_hobject(thr, -1);
49548 if (!obj) {
49549 DUK_DDD(DUK_DDDPRINT("value is not an object, skip both built-in and user augment"));
49550 return;
49551 }
49552 if (!duk_hobject_prototype_chain_contains(thr, obj, thr->builtins[DUK_BIDX_ERROR_PROTOTYPE], 1 /*ignore_loop*/)) {
49553 /* If the value has a prototype loop, it's critical not to
49554 * throw here. Instead, assume the value is not to be
49555 * augmented.
49556 */
49557 DUK_DDD(DUK_DDDPRINT("value is not an error instance, skip both built-in and user augment"));
49558 return;
49559 }
49560 if (DUK_HOBJECT_HAS_EXTENSIBLE(obj)) {
49561 DUK_DDD(DUK_DDDPRINT("error meets criteria, built-in augment"));
49562 duk__err_augment_builtin_create(thr, thr_callstack, c_filename, c_line, obj, flags);
49563 } else {
49564 DUK_DDD(DUK_DDDPRINT("error does not meet criteria, no built-in augment"));
49565 }
49566
49567 /* [ ... error ] */
49568
49569#if defined(DUK_USE_ERRCREATE)
49571#endif
49572}
49573#endif /* DUK_USE_AUGMENT_ERROR_CREATE */
49574
49575/*
49576 * Augment an error at throw time; allow a user error handler (if defined)
49577 * to process/replace the error. The error to be augmented is at the
49578 * stack top.
49579 */
49580
49581#if defined(DUK_USE_AUGMENT_ERROR_THROW)
49583#if defined(DUK_USE_ERRTHROW)
49585#endif /* DUK_USE_ERRTHROW */
49586}
49587#endif /* DUK_USE_AUGMENT_ERROR_THROW */
49588/*
49589 * Do a longjmp call, calling the fatal error handler if no
49590 * catchpoint exists.
49591 */
49592
49593/* #include duk_internal.h -> already included */
49594
49595#if defined(DUK_USE_PREFER_SIZE)
49596DUK_NORETURN(DUK_LOCAL_DECL void duk__uncaught_minimal(duk_hthread *thr));
49597DUK_LOCAL void duk__uncaught_minimal(duk_hthread *thr) {
49598 (void) duk_fatal(thr, "uncaught error");
49599 DUK_WO_NORETURN(return;);
49600}
49601#endif
49602
49603#if 0
49604DUK_NORETURN(DUK_LOCAL_DECL void duk__uncaught_readable(duk_hthread *thr));
49605DUK_LOCAL void duk__uncaught_readable(duk_hthread *thr) {
49606 const char *summary;
49608
49609 summary = duk_push_string_tval_readable(thr, &thr->heap->lj.value1);
49610 DUK_SNPRINTF(buf, sizeof(buf), "uncaught: %s", summary);
49611 buf[sizeof(buf) - 1] = (char) 0;
49612 (void) duk_fatal(thr, (const char *) buf);
49613 DUK_WO_NORETURN(return;);
49614}
49615#endif
49616
49617#if !defined(DUK_USE_PREFER_SIZE)
49620 const char *summary;
49621 char buf[DUK_USE_FATAL_MAXLEN];
49622
49623 summary = duk_push_string_tval_readable_error(thr, &thr->heap->lj.value1);
49624 DUK_ASSERT(summary != NULL);
49625 DUK_SNPRINTF(buf, sizeof(buf), "uncaught: %s", summary);
49626 buf[sizeof(buf) - 1] = (char) 0;
49627 (void) duk_fatal(thr, (const char *) buf);
49628 DUK_WO_NORETURN(return;);
49629}
49630#endif
49631
49633 DUK_ASSERT(thr != NULL);
49634 DUK_ASSERT(thr->heap != NULL);
49635
49636 DUK_DD(DUK_DDPRINT("longjmp error: type=%d iserror=%d value1=%!T value2=%!T",
49637 (int) thr->heap->lj.type,
49638 (int) thr->heap->lj.iserror,
49639 &thr->heap->lj.value1,
49640 &thr->heap->lj.value2));
49641
49642 /* Prevent finalizer execution during error handling. All error
49643 * handling sites will process pending finalizers once error handling
49644 * is complete and we're ready for the side effects. Does not prevent
49645 * refzero freeing or mark-and-sweep during error handling.
49646 *
49647 * NOTE: when we come here some calling code may have used DECREF
49648 * NORZ macros without an explicit DUK_REFZERO_CHECK_xxx() call.
49649 * We don't want to do it here because it would just check for
49650 * pending finalizers and we prevent that explicitly. Instead,
49651 * the error catcher will run the finalizers once error handling
49652 * is complete.
49653 */
49654
49656
49657 thr->heap->pf_prevent_count++;
49658 DUK_ASSERT(thr->heap->pf_prevent_count != 0); /* Wrap. */
49659
49660#if defined(DUK_USE_ASSERTIONS)
49661 /* XXX: set this immediately when longjmp state is set */
49662 DUK_ASSERT(thr->heap->error_not_allowed == 0); /* Detect error within critical section. */
49663 thr->heap->error_not_allowed = 1;
49664#endif
49665
49666 DUK_DD(DUK_DDPRINT("about to longjmp, pf_prevent_count=%ld", (long) thr->heap->pf_prevent_count));
49667
49668 /* If we don't have a jmpbuf_ptr, there is little we can do except
49669 * cause a fatal error. The caller's expectation is that we never
49670 * return.
49671 */
49672 if (!thr->heap->lj.jmpbuf_ptr) {
49673 DUK_D(DUK_DPRINT("uncaught error: type=%d iserror=%d value1=%!T value2=%!T",
49674 (int) thr->heap->lj.type,
49675 (int) thr->heap->lj.iserror,
49676 &thr->heap->lj.value1,
49677 &thr->heap->lj.value2));
49678
49679#if defined(DUK_USE_PREFER_SIZE)
49680 duk__uncaught_minimal(thr);
49681#else
49683#endif
49685 }
49686
49687#if defined(DUK_USE_CPP_EXCEPTIONS)
49688 throw duk_internal_exception(); /* dummy */
49689#else
49691#endif
49692
49694}
49695/*
49696 * Error helpers
49697 */
49698
49699/* #include duk_internal.h -> already included */
49700
49701/*
49702 * Helper to walk the thread chain and see if there is an active error
49703 * catcher. Protected calls or finally blocks aren't considered catching.
49704 */
49705
49706#if defined(DUK_USE_DEBUGGER_SUPPORT)
49707DUK_LOCAL duk_bool_t duk__have_active_catcher(duk_hthread *thr) {
49708 /* As noted above, a protected API call won't be counted as a
49709 * catcher. This is usually convenient, e.g. in the case of a top-
49710 * level duk_pcall(), but may not always be desirable. Perhaps add
49711 * an argument to treat them as catchers?
49712 */
49713
49714 duk_activation *act;
49715 duk_catcher *cat;
49716
49717 DUK_ASSERT(thr != NULL);
49718
49719 for (; thr != NULL; thr = thr->resumer) {
49720 for (act = thr->callstack_curr; act != NULL; act = act->parent) {
49721 for (cat = act->cat; cat != NULL; cat = cat->parent) {
49722 if (DUK_CAT_HAS_CATCH_ENABLED(cat)) {
49723 return 1; /* all we need to know */
49725 }
49726 }
49727 }
49728 return 0;
49729}
49730#endif /* DUK_USE_DEBUGGER_SUPPORT */
49731
49732/*
49733 * Get prototype object for an integer error code.
49734 */
49735
49737 switch (code) {
49738 case DUK_ERR_EVAL_ERROR:
49746 case DUK_ERR_TYPE_ERROR:
49748 case DUK_ERR_URI_ERROR:
49750 case DUK_ERR_ERROR:
49751 default:
49753 }
49754}
49755
49756/*
49757 * Helper for debugger throw notify and pause-on-uncaught integration.
49758 */
49759
49760#if defined(DUK_USE_DEBUGGER_SUPPORT)
49761DUK_INTERNAL void duk_err_check_debugger_integration(duk_hthread *thr) {
49762 duk_bool_t uncaught;
49763 duk_tval *tv_obj;
49764
49765 /* If something is thrown with the debugger attached and nobody will
49766 * catch it, execution is paused before the longjmp, turning over
49767 * control to the debug client. This allows local state to be examined
49768 * before the stack is unwound. Errors are not intercepted when debug
49769 * message loop is active (e.g. for Eval).
49770 */
49771
49772 DUK_ASSERT(thr != NULL);
49773 DUK_ASSERT(thr->heap != NULL);
49774
49775 /* XXX: Allow customizing the pause and notify behavior at runtime
49776 * using debugger runtime flags. For now the behavior is fixed using
49777 * config options.
49778 */
49779
49780 if (!duk_debug_is_attached(thr->heap) || thr->heap->dbg_processing || thr->heap->lj.type != DUK_LJ_TYPE_THROW ||
49781 thr->heap->creating_error) {
49782 DUK_D(DUK_DPRINT("skip debugger error integration; not attached, debugger processing, not THROW, or error thrown "
49783 "while creating error"));
49784 return;
49785 }
49786
49787 /* Don't intercept a DoubleError, we may have caused the initial double
49788 * fault and attempting to intercept it will cause us to be called
49789 * recursively and exhaust the C stack. (This should no longer happen
49790 * for the initial throw because DoubleError path doesn't do a debugger
49791 * integration check, but it might happen for rethrows.)
49792 */
49793 tv_obj = &thr->heap->lj.value1;
49794 if (DUK_TVAL_IS_OBJECT(tv_obj) && DUK_TVAL_GET_OBJECT(tv_obj) == thr->builtins[DUK_BIDX_DOUBLE_ERROR]) {
49795 DUK_D(DUK_DPRINT("built-in DoubleError instance (re)thrown, not intercepting"));
49796 return;
49797 }
49798
49799 uncaught = !duk__have_active_catcher(thr);
49800
49801 /* Debugger code expects the value at stack top. This also serves
49802 * as a backup: we need to store/restore the longjmp state because
49803 * when the debugger is paused Eval commands may be executed and
49804 * they can arbitrarily clobber the longjmp state.
49805 */
49806 duk_push_tval(thr, tv_obj);
49807
49808 /* Store and reset longjmp state. */
49810 DUK_TVAL_DECREF_NORZ(thr, tv_obj);
49811 DUK_ASSERT(DUK_TVAL_IS_UNDEFINED(&thr->heap->lj.value2)); /* Always for THROW type. */
49812 DUK_TVAL_SET_UNDEFINED(tv_obj);
49815
49816#if defined(DUK_USE_DEBUGGER_THROW_NOTIFY)
49817 /* Report it to the debug client */
49818 DUK_D(DUK_DPRINT("throw with debugger attached, report to client"));
49819 duk_debug_send_throw(thr, uncaught);
49820#endif
49821
49822 if (uncaught) {
49823 if (thr->heap->dbg_pause_flags & DUK_PAUSE_FLAG_UNCAUGHT_ERROR) {
49824 DUK_D(DUK_DPRINT("PAUSE TRIGGERED by uncaught error"));
49825 duk_debug_halt_execution(thr, 1 /*use_prev_pc*/);
49826 }
49827 } else {
49828 if (thr->heap->dbg_pause_flags & DUK_PAUSE_FLAG_CAUGHT_ERROR) {
49829 DUK_D(DUK_DPRINT("PAUSE TRIGGERED by caught error"));
49830 duk_debug_halt_execution(thr, 1 /*use_prev_pc*/);
49831 }
49832 }
49833
49834 /* Restore longjmp state. */
49836 thr->heap->lj.type = DUK_LJ_TYPE_THROW;
49837 tv_obj = DUK_GET_TVAL_NEGIDX(thr, -1);
49841 DUK_TVAL_INCREF(thr, tv_obj);
49843
49844 duk_pop(thr);
49845}
49846#endif /* DUK_USE_DEBUGGER_SUPPORT */
49847
49848/*
49849 * Helpers for setting up heap longjmp state.
49850 */
49851
49853 duk_heap *heap;
49854
49855 DUK_ASSERT(thr != NULL);
49856 heap = thr->heap;
49857 DUK_ASSERT(heap != NULL);
49858 DUK_ASSERT(tv_val != NULL);
49859
49861
49862 heap->lj.type = lj_type;
49863 DUK_TVAL_SET_TVAL(&heap->lj.value1, tv_val);
49864 DUK_TVAL_INCREF(thr, tv_val);
49865
49867}
49868/*
49869 * Create and throw an ECMAScript error object based on a code and a message.
49870 *
49871 * Used when we throw errors internally. ECMAScript generated error objects
49872 * are created by ECMAScript code, and the throwing is handled by the bytecode
49873 * executor.
49874 */
49875
49876/* #include duk_internal.h -> already included */
49877
49878/*
49879 * Create and throw an error (originating from Duktape internally)
49880 *
49881 * Push an error object on top of the stack, possibly throw augmenting
49882 * the error, and finally longjmp.
49883 *
49884 * If an error occurs while we're dealing with the current error, we might
49885 * enter an infinite recursion loop. This is prevented by detecting a
49886 * "double fault" through the heap->creating_error flag; the recursion
49887 * then stops at the second level.
49888 */
49889
49890#if defined(DUK_USE_VERBOSE_ERRORS)
49892 duk_errcode_t code,
49893 const char *msg,
49894 const char *filename,
49895 duk_int_t line) {
49896#else
49898#endif
49899#if defined(DUK_USE_VERBOSE_ERRORS)
49900 DUK_DD(DUK_DDPRINT("duk_err_create_and_throw(): code=%ld, msg=%s, filename=%s, line=%ld",
49901 (long) code,
49902 (const char *) msg,
49903 (const char *) filename,
49904 (long) line));
49905#else
49906 DUK_DD(DUK_DDPRINT("duk_err_create_and_throw(): code=%ld", (long) code));
49907#endif
49908
49909 DUK_ASSERT(thr != NULL);
49910
49911 /* Even though nested call is possible because we throw an error when
49912 * trying to create an error, the potential errors must happen before
49913 * the longjmp state is configured.
49914 */
49916
49917 /* Sync so that augmentation sees up-to-date activations, NULL
49918 * thr->ptr_curr_pc so that it's not used if side effects occur
49919 * in augmentation or longjmp handling.
49920 */
49922
49923 /*
49924 * Create and push an error object onto the top of stack.
49925 * The error is potentially augmented before throwing.
49926 *
49927 * If a "double error" occurs, use a fixed error instance
49928 * to avoid further trouble.
49929 */
49930
49931 if (thr->heap->creating_error) {
49932 duk_tval tv_val;
49933 duk_hobject *h_err;
49934
49935 thr->heap->creating_error = 0;
49936
49937 h_err = thr->builtins[DUK_BIDX_DOUBLE_ERROR];
49938 if (h_err != NULL) {
49939 DUK_D(DUK_DPRINT("double fault detected -> use built-in fixed 'double error' instance"));
49940 DUK_TVAL_SET_OBJECT(&tv_val, h_err);
49941 } else {
49942 DUK_D(DUK_DPRINT("double fault detected; there is no built-in fixed 'double error' instance "
49943 "-> use the error code as a number"));
49944 DUK_TVAL_SET_I32(&tv_val, (duk_int32_t) code);
49945 }
49946
49948
49949 /* No augmentation to avoid any allocations or side effects. */
49950 } else {
49951 /* Prevent infinite recursion. Extra call stack and C
49952 * recursion headroom (see GH-191) is added for augmentation.
49953 * That is now signalled by heap->augmenting error and taken
49954 * into account in call handling without an explicit limit bump.
49955 */
49956 thr->heap->creating_error = 1;
49957
49958 duk_require_stack(thr, 1);
49959
49960 /* XXX: usually unnecessary '%s' formatting here, but cannot
49961 * use 'msg' as a format string directly.
49962 */
49963#if defined(DUK_USE_VERBOSE_ERRORS)
49964 duk_push_error_object_raw(thr, code | DUK_ERRCODE_FLAG_NOBLAME_FILELINE, filename, line, "%s", (const char *) msg);
49965#else
49967#endif
49968
49969 /* Note that an alloc error may happen during error augmentation.
49970 * This may happen both when the original error is an alloc error
49971 * and when it's something else. Because any error in augmentation
49972 * must be handled correctly anyway, there's no special check for
49973 * avoiding it for alloc errors (this differs from Duktape 1.x).
49974 */
49975#if defined(DUK_USE_AUGMENT_ERROR_THROW)
49976 DUK_DDD(DUK_DDDPRINT("THROW ERROR (INTERNAL): %!iT (before throw augment)", (duk_tval *) duk_get_tval(thr, -1)));
49978#endif
49979
49981 thr->heap->creating_error = 0;
49982
49983 /* Error is now created and we assume no errors can occur any
49984 * more. Check for debugger Throw integration only when the
49985 * error is complete. If we enter debugger message loop,
49986 * creating_error must be 0 so that errors can be thrown in
49987 * the paused state, e.g. in Eval commands.
49988 */
49989#if defined(DUK_USE_DEBUGGER_SUPPORT)
49990 duk_err_check_debugger_integration(thr);
49991#endif
49992 }
49993
49994 /*
49995 * Finally, longjmp
49996 */
49997
49998 DUK_DDD(DUK_DDDPRINT("THROW ERROR (INTERNAL): %!iT, %!iT (after throw augment)",
49999 (duk_tval *) &thr->heap->lj.value1,
50000 (duk_tval *) &thr->heap->lj.value2));
50001
50002 duk_err_longjmp(thr);
50004}
50005
50006/*
50007 * Helper for C function call negative return values.
50008 */
50009
50011 DUK_ASSERT(thr != NULL);
50012 DUK_ASSERT(rc < 0);
50013
50014 /*
50015 * The __FILE__ and __LINE__ information is intentionally not used in the
50016 * creation of the error object, as it isn't useful in the tracedata. The
50017 * tracedata still contains the function which returned the negative return
50018 * code, and having the file/line of this function isn't very useful.
50019 *
50020 * The error messages for DUK_RET_xxx shorthand are intentionally very
50021 * minimal: they're only really useful for low memory targets.
50022 */
50023
50024 duk_error_raw(thr, -rc, NULL, 0, "error (rc %ld)", (long) rc);
50026}
50027/*
50028 * duk_hbuffer allocation and freeing.
50029 */
50030
50031/* #include duk_internal.h -> already included */
50032
50033/* Allocate a new duk_hbuffer of a certain type and return a pointer to it
50034 * (NULL on error). Write buffer data pointer to 'out_bufdata' (only if
50035 * allocation successful).
50036 */
50037DUK_INTERNAL duk_hbuffer *duk_hbuffer_alloc(duk_heap *heap, duk_size_t size, duk_small_uint_t flags, void **out_bufdata) {
50038 duk_hbuffer *res = NULL;
50039 duk_size_t header_size;
50040 duk_size_t alloc_size;
50041
50042 DUK_ASSERT(heap != NULL);
50043 DUK_ASSERT(out_bufdata != NULL);
50044
50045 DUK_DDD(DUK_DDDPRINT("allocate hbuffer"));
50046
50047 /* Size sanity check. Should not be necessary because caller is
50048 * required to check this, but we don't want to cause a segfault
50049 * if the size wraps either in duk_size_t computation or when
50050 * storing the size in a 16-bit field.
50051 */
50052 if (size > DUK_HBUFFER_MAX_BYTELEN) {
50053 DUK_D(DUK_DPRINT("hbuffer alloc failed: size too large: %ld", (long) size));
50054 return NULL; /* no need to write 'out_bufdata' */
50055 }
50056
50057 if (flags & DUK_BUF_FLAG_EXTERNAL) {
50058 header_size = sizeof(duk_hbuffer_external);
50059 alloc_size = sizeof(duk_hbuffer_external);
50060 } else if (flags & DUK_BUF_FLAG_DYNAMIC) {
50061 header_size = sizeof(duk_hbuffer_dynamic);
50062 alloc_size = sizeof(duk_hbuffer_dynamic);
50063 } else {
50064 header_size = sizeof(duk_hbuffer_fixed);
50065 alloc_size = sizeof(duk_hbuffer_fixed) + size;
50066 DUK_ASSERT(alloc_size >= sizeof(duk_hbuffer_fixed)); /* no wrapping */
50067 }
50068
50069 res = (duk_hbuffer *) DUK_ALLOC(heap, alloc_size);
50070 if (DUK_UNLIKELY(res == NULL)) {
50071 goto alloc_error;
50072 }
50073
50074 /* zero everything unless requested not to do so */
50075#if defined(DUK_USE_ZERO_BUFFER_DATA)
50076 duk_memzero((void *) res, (flags & DUK_BUF_FLAG_NOZERO) ? header_size : alloc_size);
50077#else
50078 duk_memzero((void *) res, header_size);
50079#endif
50080
50081 if (flags & DUK_BUF_FLAG_EXTERNAL) {
50083 h = (duk_hbuffer_external *) res;
50084 DUK_UNREF(h);
50085 *out_bufdata = NULL;
50086#if defined(DUK_USE_EXPLICIT_NULL_INIT)
50087#if defined(DUK_USE_HEAPPTR16)
50088/* the compressed pointer is zeroed which maps to NULL, so nothing to do. */
50089#else
50090 DUK_HBUFFER_EXTERNAL_SET_DATA_PTR(heap, h, NULL);
50091#endif
50092#endif
50094 } else if (flags & DUK_BUF_FLAG_DYNAMIC) {
50096 void *ptr;
50097
50098 if (size > 0) {
50099 DUK_ASSERT(!(flags & DUK_BUF_FLAG_EXTERNAL)); /* alloc external with size zero */
50100 DUK_DDD(DUK_DDDPRINT("dynamic buffer with nonzero size, alloc actual buffer"));
50101#if defined(DUK_USE_ZERO_BUFFER_DATA)
50102 ptr = DUK_ALLOC_ZEROED(heap, size);
50103#else
50104 ptr = DUK_ALLOC(heap, size);
50105#endif
50106 if (DUK_UNLIKELY(ptr == NULL)) {
50107 /* Because size > 0, NULL check is correct */
50108 goto alloc_error;
50109 }
50110 *out_bufdata = ptr;
50111
50113 } else {
50114 *out_bufdata = NULL;
50115#if defined(DUK_USE_EXPLICIT_NULL_INIT)
50116#if defined(DUK_USE_HEAPPTR16)
50117/* the compressed pointer is zeroed which maps to NULL, so nothing to do. */
50118#else
50119 DUK_HBUFFER_DYNAMIC_SET_DATA_PTR(heap, h, NULL);
50120#endif
50121#endif
50123 }
50124 } else {
50125 *out_bufdata = (void *) ((duk_hbuffer_fixed *) (void *) res + 1);
50126 }
50127
50128 DUK_HBUFFER_SET_SIZE(res, size);
50129
50131 if (flags & DUK_BUF_FLAG_DYNAMIC) {
50133 if (flags & DUK_BUF_FLAG_EXTERNAL) {
50135 }
50136 } else {
50138 }
50139 DUK_HEAP_INSERT_INTO_HEAP_ALLOCATED(heap, &res->hdr);
50140
50141 DUK_DDD(DUK_DDDPRINT("allocated hbuffer: %p", (void *) res));
50142 return res;
50143
50144alloc_error:
50145 DUK_DD(DUK_DDPRINT("hbuffer allocation failed"));
50146
50147 DUK_FREE(heap, res);
50148 return NULL; /* no need to write 'out_bufdata' */
50149}
50150
50151/* For indirect allocs. */
50152
50153DUK_INTERNAL void *duk_hbuffer_get_dynalloc_ptr(duk_heap *heap, void *ud) {
50155 DUK_UNREF(heap);
50156 return (void *) DUK_HBUFFER_DYNAMIC_GET_DATA_PTR(heap, buf);
50157}
50158/*
50159 * duk_hbuffer assertion helpers
50160 */
50161
50162/* #include duk_internal.h -> already included */
50163
50164#if defined(DUK_USE_ASSERTIONS)
50165
50166DUK_INTERNAL void duk_hbuffer_assert_valid(duk_hbuffer *h) {
50167 DUK_ASSERT(h != NULL);
50168}
50169
50170#endif /* DUK_USE_ASSERTIONS */
50171/*
50172 * duk_hbuffer operations such as resizing and inserting/appending data to
50173 * a dynamic buffer.
50174 */
50175
50176/* #include duk_internal.h -> already included */
50177
50178/*
50179 * Resizing
50180 */
50181
50183 void *res;
50184 duk_size_t prev_size;
50185
50186 DUK_ASSERT(thr != NULL);
50187 DUK_ASSERT(buf != NULL);
50190
50191 /*
50192 * Maximum size check
50193 */
50194
50195 if (new_size > DUK_HBUFFER_MAX_BYTELEN) {
50196 DUK_ERROR_RANGE(thr, "buffer too long");
50197 DUK_WO_NORETURN(return;);
50198 }
50199
50200 /*
50201 * Note: use indirect realloc variant just in case mark-and-sweep
50202 * (finalizers) might resize this same buffer during garbage
50203 * collection.
50204 */
50205
50206 res = DUK_REALLOC_INDIRECT(thr->heap, duk_hbuffer_get_dynalloc_ptr, (void *) buf, new_size);
50207 if (DUK_LIKELY(res != NULL || new_size == 0)) {
50208 /* 'res' may be NULL if new allocation size is 0. */
50209
50210 DUK_DDD(DUK_DDDPRINT("resized dynamic buffer %p:%ld -> %p:%ld",
50211 (void *) DUK_HBUFFER_DYNAMIC_GET_DATA_PTR(thr->heap, buf),
50212 (long) DUK_HBUFFER_DYNAMIC_GET_SIZE(buf),
50213 (void *) res,
50214 (long) new_size));
50215
50216 /*
50217 * The entire allocated buffer area, regardless of actual used
50218 * size, is kept zeroed in resizes for simplicity. If the buffer
50219 * is grown, zero the new part.
50220 */
50221
50222 prev_size = DUK_HBUFFER_DYNAMIC_GET_SIZE(buf);
50223 if (new_size > prev_size) {
50224 DUK_ASSERT(new_size - prev_size > 0);
50225#if defined(DUK_USE_ZERO_BUFFER_DATA)
50226 duk_memzero((void *) ((char *) res + prev_size), (duk_size_t) (new_size - prev_size));
50227#endif
50229
50230 DUK_HBUFFER_DYNAMIC_SET_SIZE(buf, new_size);
50231 DUK_HBUFFER_DYNAMIC_SET_DATA_PTR(thr->heap, buf, res);
50232 } else {
50234 DUK_WO_NORETURN(return;);
50235 }
50236
50237 DUK_ASSERT(res != NULL || new_size == 0);
50238}
50241 DUK_ASSERT(thr != NULL);
50242 DUK_ASSERT(buf != NULL);
50245
50246 duk_hbuffer_resize(thr, buf, 0);
50247}
50248/* #include duk_internal.h -> already included */
50249
50250#if defined(DUK_USE_BUFFEROBJECT_SUPPORT)
50252 duk_uint_t buf_size;
50253 duk_uint_t buf_avail;
50254
50255 DUK_ASSERT(h_bufobj != NULL);
50256 DUK_ASSERT(h_bufobj->buf != NULL);
50257
50258 buf_size = (duk_uint_t) DUK_HBUFFER_GET_SIZE(h_bufobj->buf);
50259 if (h_bufobj->offset > buf_size) {
50260 /* Slice starting point is beyond current length. */
50261 return 0;
50262 }
50263 buf_avail = buf_size - h_bufobj->offset;
50264
50265 return buf_avail >= len ? len : buf_avail;
50266}
50267#endif /* DUK_USE_BUFFEROBJECT_SUPPORT */
50268/*
50269 * duk_heap allocation and freeing.
50270 */
50271
50272/* #include duk_internal.h -> already included */
50273
50274#if defined(DUK_USE_ROM_STRINGS)
50275/* Fixed seed value used with ROM strings. */
50276#define DUK__FIXED_HASH_SEED 0xabcd1234
50277#endif
50278
50279/*
50280 * Free a heap object.
50281 *
50282 * Free heap object and its internal (non-heap) pointers. Assumes that
50283 * caller has removed the object from heap allocated list or the string
50284 * intern table, and any weak references (which strings may have) have
50285 * been already dealt with.
50286 */
50287
50289 DUK_ASSERT(heap != NULL);
50290 DUK_ASSERT(h != NULL);
50291
50292 DUK_FREE(heap, DUK_HOBJECT_GET_PROPS(heap, h));
50293
50294 if (DUK_HOBJECT_IS_COMPFUNC(h)) {
50295 duk_hcompfunc *f = (duk_hcompfunc *) h;
50296 DUK_UNREF(f);
50297 /* Currently nothing to free; 'data' is a heap object */
50298 } else if (DUK_HOBJECT_IS_NATFUNC(h)) {
50299 duk_hnatfunc *f = (duk_hnatfunc *) h;
50300 DUK_UNREF(f);
50301 /* Currently nothing to free */
50302 } else if (DUK_HOBJECT_IS_THREAD(h)) {
50303 duk_hthread *t = (duk_hthread *) h;
50304 duk_activation *act;
50305
50306 DUK_FREE(heap, t->valstack);
50307
50308 /* Don't free h->resumer because it exists in the heap.
50309 * Callstack entries also contain function pointers which
50310 * are not freed for the same reason. They are decref
50311 * finalized and the targets are freed if necessary based
50312 * on their refcount (or reachability).
50313 */
50314 for (act = t->callstack_curr; act != NULL;) {
50315 duk_activation *act_next;
50316 duk_catcher *cat;
50317
50318 for (cat = act->cat; cat != NULL;) {
50319 duk_catcher *cat_next;
50320
50321 cat_next = cat->parent;
50322 DUK_FREE(heap, (void *) cat);
50323 cat = cat_next;
50324 }
50325
50326 act_next = act->parent;
50327 DUK_FREE(heap, (void *) act);
50328 act = act_next;
50329 }
50330
50331 /* XXX: with 'caller' property the callstack would need
50332 * to be unwound to update the 'caller' properties of
50333 * functions in the callstack.
50334 */
50335 } else if (DUK_HOBJECT_IS_BOUNDFUNC(h)) {
50336 duk_hboundfunc *f = (duk_hboundfunc *) (void *) h;
50337
50338 DUK_FREE(heap, f->args);
50339 }
50340
50341 DUK_FREE(heap, (void *) h);
50342}
50343
50345 DUK_ASSERT(heap != NULL);
50346 DUK_ASSERT(h != NULL);
50347
50350 DUK_DDD(DUK_DDDPRINT("free dynamic buffer %p", (void *) DUK_HBUFFER_DYNAMIC_GET_DATA_PTR(heap, g)));
50352 }
50353 DUK_FREE(heap, (void *) h);
50354}
50355
50357 DUK_ASSERT(heap != NULL);
50358 DUK_ASSERT(h != NULL);
50359
50360 DUK_UNREF(heap);
50362
50363#if defined(DUK_USE_HSTRING_EXTDATA) && defined(DUK_USE_EXTSTR_FREE)
50364 if (DUK_HSTRING_HAS_EXTDATA(h)) {
50365 DUK_DDD(
50366 DUK_DDDPRINT("free extstr: hstring %!O, extdata: %p", h, DUK_HSTRING_GET_EXTDATA((duk_hstring_external *) h)));
50367 DUK_USE_EXTSTR_FREE(heap->heap_udata, (const void *) DUK_HSTRING_GET_EXTDATA((duk_hstring_external *) h));
50368 }
50369#endif
50370 DUK_FREE(heap, (void *) h);
50371}
50372
50374 DUK_ASSERT(heap);
50375 DUK_ASSERT(hdr);
50376
50377 DUK_DDD(DUK_DDDPRINT("free heaphdr %p, htype %ld", (void *) hdr, (long) DUK_HEAPHDR_GET_TYPE(hdr)));
50378
50379 switch (DUK_HEAPHDR_GET_TYPE(hdr)) {
50380 case DUK_HTYPE_STRING:
50381 duk_free_hstring(heap, (duk_hstring *) hdr);
50382 break;
50383 case DUK_HTYPE_OBJECT:
50384 duk_free_hobject(heap, (duk_hobject *) hdr);
50385 break;
50386 default:
50388 duk_free_hbuffer(heap, (duk_hbuffer *) hdr);
50389 }
50390}
50391
50392/*
50393 * Free the heap.
50395 * Frees heap-related non-heap-tracked allocations such as the
50396 * string intern table; then frees the heap allocated objects;
50397 * and finally frees the heap structure itself. Reference counts
50398 * and GC markers are ignored (and not updated) in this process,
50399 * and finalizers won't be called.
50400 *
50401 * The heap pointer and heap object pointers must not be used
50402 * after this call.
50403 */
50404
50405#if defined(DUK_USE_CACHE_ACTIVATION)
50407 duk_activation *act;
50408 duk_activation *act_next;
50409 duk_size_t count_act = 0;
50410
50411 for (act = heap->activation_free; act != NULL;) {
50412 act_next = act->parent;
50413 DUK_FREE(heap, (void *) act);
50414 act = act_next;
50415#if defined(DUK_USE_DEBUG)
50416 count_act++;
50417#endif
50418 }
50419 heap->activation_free = NULL; /* needed when called from mark-and-sweep */
50420 return count_act;
50421}
50422#endif /* DUK_USE_CACHE_ACTIVATION */
50423
50424#if defined(DUK_USE_CACHE_CATCHER)
50426 duk_catcher *cat;
50427 duk_catcher *cat_next;
50428 duk_size_t count_cat = 0;
50429
50430 for (cat = heap->catcher_free; cat != NULL;) {
50431 cat_next = cat->parent;
50432 DUK_FREE(heap, (void *) cat);
50433 cat = cat_next;
50434#if defined(DUK_USE_DEBUG)
50435 count_cat++;
50436#endif
50437 }
50438 heap->catcher_free = NULL; /* needed when called from mark-and-sweep */
50439
50440 return count_cat;
50441}
50442#endif /* DUK_USE_CACHE_CATCHER */
50443
50445 duk_size_t count_act = 0;
50446 duk_size_t count_cat = 0;
50447
50448#if defined(DUK_USE_CACHE_ACTIVATION)
50449 count_act = duk__heap_free_activation_freelist(heap);
50450#endif
50451#if defined(DUK_USE_CACHE_CATCHER)
50452 count_cat = duk__heap_free_catcher_freelist(heap);
50453#endif
50454 DUK_UNREF(heap);
50455 DUK_UNREF(count_act);
50456 DUK_UNREF(count_cat);
50457
50458 DUK_D(
50459 DUK_DPRINT("freed %ld activation freelist entries, %ld catcher freelist entries", (long) count_act, (long) count_cat));
50460}
50461
50463 duk_heaphdr *curr;
50464 duk_heaphdr *next;
50465
50466 curr = heap->heap_allocated;
50467 while (curr) {
50468 /* We don't log or warn about freeing zero refcount objects
50469 * because they may happen with finalizer processing.
50470 */
50471
50472 DUK_DDD(DUK_DDDPRINT("FINALFREE (allocated): %!iO", (duk_heaphdr *) curr));
50473 next = DUK_HEAPHDR_GET_NEXT(heap, curr);
50474 duk_heap_free_heaphdr_raw(heap, curr);
50475 curr = next;
50476 }
50477}
50478
50479#if defined(DUK_USE_FINALIZER_SUPPORT)
50481 duk_heaphdr *curr;
50483
50484 curr = heap->finalize_list;
50485 while (curr) {
50486 DUK_DDD(DUK_DDDPRINT("FINALFREE (finalize_list): %!iO", (duk_heaphdr *) curr));
50487 next = DUK_HEAPHDR_GET_NEXT(heap, curr);
50489 curr = next;
50490 }
50491}
50492#endif /* DUK_USE_FINALIZER_SUPPORT */
50493
50495 /* strings are only tracked by stringtable */
50497}
50498
50499#if defined(DUK_USE_FINALIZER_SUPPORT)
50501 duk_heaphdr *curr;
50502 duk_uint_t round_no;
50503 duk_size_t count_all;
50504 duk_size_t count_finalized;
50505 duk_size_t curr_limit;
50506
50507 DUK_ASSERT(heap != NULL);
50508
50509#if defined(DUK_USE_REFERENCE_COUNTING)
50510 DUK_ASSERT(heap->refzero_list == NULL); /* refzero not running -> must be empty */
50511#endif
50512 DUK_ASSERT(heap->finalize_list == NULL); /* mark-and-sweep last pass */
50513
50514 if (heap->heap_thread == NULL) {
50515 /* May happen when heap allocation fails right off. There
50516 * cannot be any finalizable objects in this case.
50517 */
50518 DUK_D(DUK_DPRINT("no heap_thread in heap destruct, assume no finalizable objects"));
50519 return;
50520 }
50521
50522 /* Prevent finalize_list processing and mark-and-sweep entirely.
50523 * Setting ms_running != 0 also prevents refzero handling from moving
50524 * objects away from the heap_allocated list. The flag name is a bit
50525 * misleading here.
50526 *
50527 * Use a distinct value for ms_running here (== 2) so that assertions
50528 * can detect this situation separate from the normal runtime
50529 * mark-and-sweep case. This allows better assertions (GH-2030).
50530 */
50531 DUK_ASSERT(heap->pf_prevent_count == 0);
50532 DUK_ASSERT(heap->ms_running == 0);
50533 DUK_ASSERT(heap->ms_prevent_count == 0);
50534 heap->pf_prevent_count = 1;
50535 heap->ms_running = 2; /* Use distinguishable value. */
50536 heap->ms_prevent_count = 1; /* Bump, because mark-and-sweep assumes it's bumped when ms_running is set. */
50537
50538 curr_limit = 0; /* suppress warning, not used */
50539 for (round_no = 0;; round_no++) {
50540 curr = heap->heap_allocated;
50541 count_all = 0;
50542 count_finalized = 0;
50543 while (curr) {
50544 count_all++;
50545 if (DUK_HEAPHDR_IS_OBJECT(curr)) {
50546 /* Only objects in heap_allocated may have finalizers. Check that
50547 * the object itself has a _Finalizer property (own or inherited)
50548 * so that we don't execute finalizers for e.g. Proxy objects.
50549 */
50550 DUK_ASSERT(curr != NULL);
50551
50552 if (DUK_HOBJECT_HAS_FINALIZER_FAST(heap, (duk_hobject *) curr)) {
50553 if (!DUK_HEAPHDR_HAS_FINALIZED((duk_heaphdr *) curr)) {
50554 DUK_ASSERT(
50555 DUK_HEAP_HAS_FINALIZER_NORESCUE(heap)); /* maps to finalizer 2nd argument */
50556 duk_heap_run_finalizer(heap, (duk_hobject *) curr);
50557 count_finalized++;
50558 }
50559 }
50560 }
50561 curr = DUK_HEAPHDR_GET_NEXT(heap, curr);
50562 }
50563
50564 /* Each round of finalizer execution may spawn new finalizable objects
50565 * which is normal behavior for some applications. Allow multiple
50566 * rounds of finalization, but use a shrinking limit based on the
50567 * first round to detect the case where a runaway finalizer creates
50568 * an unbounded amount of new finalizable objects. Finalizer rescue
50569 * is not supported: the semantics are unclear because most of the
50570 * objects being finalized here are already reachable. The finalizer
50571 * is given a boolean to indicate that rescue is not possible.
50572 *
50573 * See discussion in: https://github.com/svaarala/duktape/pull/473
50574 */
50575
50576 if (round_no == 0) {
50577 /* Cannot wrap: each object is at least 8 bytes so count is
50578 * at most 1/8 of that.
50579 */
50580 curr_limit = count_all * 2;
50581 } else {
50582 curr_limit = (curr_limit * 3) / 4; /* Decrease by 25% every round */
50583 }
50584 DUK_D(DUK_DPRINT("finalizer round %ld complete, %ld objects, tried to execute %ld finalizers, current limit is %ld",
50585 (long) round_no,
50586 (long) count_all,
50587 (long) count_finalized,
50588 (long) curr_limit));
50589
50590 if (count_finalized == 0) {
50591 DUK_D(DUK_DPRINT("no more finalizable objects, forced finalization finished"));
50592 break;
50593 }
50594 if (count_finalized >= curr_limit) {
50595 DUK_D(DUK_DPRINT("finalizer count above limit, potentially runaway finalizer; skip remaining finalizers"));
50596 break;
50597 }
50598 }
50599
50600 DUK_ASSERT(heap->ms_running == 2);
50601 DUK_ASSERT(heap->pf_prevent_count == 1);
50602 heap->ms_running = 0;
50603 heap->pf_prevent_count = 0;
50604}
50605#endif /* DUK_USE_FINALIZER_SUPPORT */
50606
50608 DUK_D(DUK_DPRINT("free heap: %p", (void *) heap));
50609
50610#if defined(DUK_USE_DEBUG)
50611 duk_heap_strtable_dump(heap);
50612#endif
50613
50614#if defined(DUK_USE_DEBUGGER_SUPPORT)
50615 /* Detach a debugger if attached (can be called multiple times)
50616 * safely.
50617 */
50618 /* XXX: Add a flag to reject an attempt to re-attach? Otherwise
50619 * the detached callback may immediately reattach.
50620 */
50621 duk_debug_do_detach(heap);
50622#endif
50623
50624 /* Execute finalizers before freeing the heap, even for reachable
50625 * objects. This gives finalizers the chance to free any native
50626 * resources like file handles, allocations made outside Duktape,
50627 * etc. This is quite tricky to get right, so that all finalizer
50628 * guarantees are honored.
50629 *
50630 * Run mark-and-sweep a few times just in case (unreachable object
50631 * finalizers run already here). The last round must rescue objects
50632 * from the previous round without running any more finalizers. This
50633 * ensures rescued objects get their FINALIZED flag cleared so that
50634 * their finalizer is called once more in forced finalization to
50635 * satisfy finalizer guarantees. However, we don't want to run any
50636 * more finalizers because that'd required one more loop, and so on.
50637 *
50638 * XXX: this perhaps requires an execution time limit.
50639 */
50640 DUK_D(DUK_DPRINT("execute finalizers before freeing heap"));
50641 DUK_ASSERT(heap->pf_skip_finalizers == 0);
50642 DUK_D(DUK_DPRINT("forced gc #1 in heap destruction"));
50643 duk_heap_mark_and_sweep(heap, 0);
50644 DUK_D(DUK_DPRINT("forced gc #2 in heap destruction"));
50645 duk_heap_mark_and_sweep(heap, 0);
50646 DUK_D(DUK_DPRINT("forced gc #3 in heap destruction (don't run finalizers)"));
50647 heap->pf_skip_finalizers = 1;
50648 duk_heap_mark_and_sweep(heap, 0); /* Skip finalizers; queue finalizable objects to heap_allocated. */
50649
50650 /* There are never objects in refzero_list at this point, or at any
50651 * point beyond a DECREF (even a DECREF_NORZ). Since Duktape 2.1
50652 * refzero_list processing is side effect free, so it is always
50653 * processed to completion by a DECREF initially triggering a zero
50654 * refcount.
50655 */
50656#if defined(DUK_USE_REFERENCE_COUNTING)
50657 DUK_ASSERT(heap->refzero_list == NULL); /* Always processed to completion inline. */
50658#endif
50659#if defined(DUK_USE_FINALIZER_SUPPORT)
50660 DUK_ASSERT(heap->finalize_list == NULL); /* Last mark-and-sweep with skip_finalizers. */
50661#endif
50662
50663#if defined(DUK_USE_FINALIZER_SUPPORT)
50664 DUK_D(DUK_DPRINT("run finalizers for remaining finalizable objects"));
50665 DUK_HEAP_SET_FINALIZER_NORESCUE(heap); /* Rescue no longer supported. */
50667#endif /* DUK_USE_FINALIZER_SUPPORT */
50668
50669 /* Note: heap->heap_thread, heap->curr_thread, and heap->heap_object
50670 * are on the heap allocated list.
50671 */
50672
50673 DUK_D(DUK_DPRINT("freeing temporary freelists"));
50675
50676 DUK_D(DUK_DPRINT("freeing heap_allocated of heap: %p", (void *) heap));
50677 duk__free_allocated(heap);
50678
50679#if defined(DUK_USE_REFERENCE_COUNTING)
50680 DUK_ASSERT(heap->refzero_list == NULL); /* Always processed to completion inline. */
50681#endif
50682
50683#if defined(DUK_USE_FINALIZER_SUPPORT)
50684 DUK_D(DUK_DPRINT("freeing finalize_list of heap: %p", (void *) heap));
50686#endif
50687
50688 DUK_D(DUK_DPRINT("freeing string table of heap: %p", (void *) heap));
50690
50691 DUK_D(DUK_DPRINT("freeing heap structure: %p", (void *) heap));
50692 heap->free_func(heap->heap_udata, heap);
50693}
50694
50695/*
50696 * Allocate a heap.
50697 *
50698 * String table is initialized with built-in strings from genbuiltins.py,
50699 * either by dynamically creating the strings or by referring to ROM strings.
50700 */
50701
50702#if defined(DUK_USE_ROM_STRINGS)
50704#if defined(DUK_USE_ASSERTIONS)
50706#endif
50707
50708 DUK_UNREF(heap);
50709
50710 /* With ROM-based strings, heap->strs[] and thr->strs[] are omitted
50711 * so nothing to initialize for strs[].
50712 */
50713
50714#if defined(DUK_USE_ASSERTIONS)
50715 for (i = 0; i < sizeof(duk_rom_strings_lookup) / sizeof(const duk_hstring *); i++) {
50716 const duk_hstring *h;
50717 duk_uint32_t hash;
50718
50719 h = duk_rom_strings_lookup[i];
50720 while (h != NULL) {
50721 hash = duk_heap_hashstring(heap, (const duk_uint8_t *) DUK_HSTRING_GET_DATA(h), DUK_HSTRING_GET_BYTELEN(h));
50722 DUK_DD(DUK_DDPRINT("duk_rom_strings_lookup[%d] -> hash 0x%08lx, computed 0x%08lx",
50723 (int) i,
50724 (unsigned long) DUK_HSTRING_GET_HASH(h),
50725 (unsigned long) hash));
50726 DUK_ASSERT(hash == (duk_uint32_t) DUK_HSTRING_GET_HASH(h));
50727
50728 h = (const duk_hstring *) h->hdr.h_next;
50729 }
50730 }
50731#endif
50732 return 1;
50733}
50734#else /* DUK_USE_ROM_STRINGS */
50735
50737 duk_bitdecoder_ctx bd_ctx;
50738 duk_bitdecoder_ctx *bd = &bd_ctx; /* convenience */
50740
50741 duk_memzero(&bd_ctx, sizeof(bd_ctx));
50742 bd->data = (const duk_uint8_t *) duk_strings_data;
50744
50745 for (i = 0; i < DUK_HEAP_NUM_STRINGS; i++) {
50746 duk_uint8_t tmp[DUK_STRDATA_MAX_STRLEN];
50747 duk_small_uint_t len;
50748 duk_hstring *h;
50749
50750 len = duk_bd_decode_bitpacked_string(bd, tmp);
50751
50752 /* No need to length check string: it will never exceed even
50753 * the 16-bit length maximum.
50754 */
50755 DUK_ASSERT(len <= 0xffffUL);
50756 DUK_DDD(DUK_DDDPRINT("intern built-in string %ld", (long) i));
50757 h = duk_heap_strtable_intern(heap, tmp, len);
50758 if (!h) {
50759 goto failed;
50760 }
50762
50763 /* Special flags checks. Since these strings are always
50764 * reachable and a string cannot appear twice in the string
50765 * table, there's no need to check/set these flags elsewhere.
50766 * The 'internal' flag is set by string intern code.
50767 */
50768 if (i == DUK_STRIDX_EVAL || i == DUK_STRIDX_LC_ARGUMENTS) {
50770 }
50775 }
50776 }
50777
50778 DUK_DDD(DUK_DDDPRINT("interned: %!O", (duk_heaphdr *) h));
50779
50780 /* XXX: The incref macro takes a thread pointer but doesn't
50781 * use it right now.
50782 */
50783 DUK_HSTRING_INCREF(_never_referenced_, h);
50784
50785#if defined(DUK_USE_HEAPPTR16)
50786 heap->strs16[i] = DUK_USE_HEAPPTR_ENC16(heap->heap_udata, (void *) h);
50787#else
50788 heap->strs[i] = h;
50789#endif
50790 }
50791
50792 return 1;
50793
50794failed:
50795 return 0;
50796}
50797#endif /* DUK_USE_ROM_STRINGS */
50798
50800 duk_hthread *thr;
50801
50802 DUK_D(DUK_DPRINT("heap init: alloc heap thread"));
50804 if (thr == NULL) {
50805 DUK_D(DUK_DPRINT("failed to alloc heap_thread"));
50806 return 0;
50807 }
50809#if defined(DUK_USE_ROM_STRINGS)
50810 /* No strs[] pointer. */
50811#else /* DUK_USE_ROM_STRINGS */
50812#if defined(DUK_USE_HEAPPTR16)
50813 thr->strs16 = heap->strs16;
50814#else
50815 thr->strs = heap->strs;
50816#endif
50817#endif /* DUK_USE_ROM_STRINGS */
50818
50819 heap->heap_thread = thr;
50820 DUK_HTHREAD_INCREF(thr, thr); /* Note: first argument not really used */
50821
50822 /* 'thr' is now reachable */
50823
50824 DUK_D(DUK_DPRINT("heap init: init heap thread stacks"));
50825 if (!duk_hthread_init_stacks(heap, thr)) {
50826 return 0;
50827 }
50828
50829 /* XXX: this may now fail, and is not handled correctly */
50831
50832 /* default prototype */
50834
50835 return 1;
50836}
50837
50838#if defined(DUK_USE_DEBUG)
50839#define DUK__DUMPSZ(t) \
50840 do { \
50841 DUK_D(DUK_DPRINT("" #t "=%ld", (long) sizeof(t))); \
50842 } while (0)
50843
50844/* These is not 100% because format would need to be non-portable "long long".
50845 * Also print out as doubles to catch cases where the "long" type is not wide
50846 * enough; the limits will then not be printed accurately but the magnitude
50847 * will be correct.
50848 */
50849#define DUK__DUMPLM_SIGNED_RAW(t, a, b) \
50850 do { \
50851 DUK_D(DUK_DPRINT(t "=[%ld,%ld]=[%lf,%lf]", (long) (a), (long) (b), (double) (a), (double) (b))); \
50852 } while (0)
50853#define DUK__DUMPLM_UNSIGNED_RAW(t, a, b) \
50854 do { \
50855 DUK_D(DUK_DPRINT(t "=[%lu,%lu]=[%lf,%lf]", (unsigned long) (a), (unsigned long) (b), (double) (a), (double) (b))); \
50856 } while (0)
50857#define DUK__DUMPLM_SIGNED(t) \
50858 do { \
50859 DUK__DUMPLM_SIGNED_RAW("DUK_" #t "_{MIN,MAX}", DUK_##t##_MIN, DUK_##t##_MAX); \
50860 } while (0)
50861#define DUK__DUMPLM_UNSIGNED(t) \
50862 do { \
50863 DUK__DUMPLM_UNSIGNED_RAW("DUK_" #t "_{MIN,MAX}", DUK_##t##_MIN, DUK_##t##_MAX); \
50864 } while (0)
50865
50866DUK_LOCAL void duk__dump_type_sizes(void) {
50867 DUK_D(DUK_DPRINT("sizeof()"));
50868
50869 /* basic platform types */
50870 DUK__DUMPSZ(char);
50871 DUK__DUMPSZ(short);
50872 DUK__DUMPSZ(int);
50873 DUK__DUMPSZ(long);
50874 DUK__DUMPSZ(double);
50875 DUK__DUMPSZ(void *);
50876 DUK__DUMPSZ(size_t);
50877
50878 /* basic types from duk_features.h */
50879 DUK__DUMPSZ(duk_uint8_t);
50880 DUK__DUMPSZ(duk_int8_t);
50881 DUK__DUMPSZ(duk_uint16_t);
50882 DUK__DUMPSZ(duk_int16_t);
50883 DUK__DUMPSZ(duk_uint32_t);
50884 DUK__DUMPSZ(duk_int32_t);
50885 DUK__DUMPSZ(duk_uint64_t);
50886 DUK__DUMPSZ(duk_int64_t);
50887 DUK__DUMPSZ(duk_uint_least8_t);
50888 DUK__DUMPSZ(duk_int_least8_t);
50889 DUK__DUMPSZ(duk_uint_least16_t);
50890 DUK__DUMPSZ(duk_int_least16_t);
50891 DUK__DUMPSZ(duk_uint_least32_t);
50892 DUK__DUMPSZ(duk_int_least32_t);
50893#if defined(DUK_USE_64BIT_OPS)
50894 DUK__DUMPSZ(duk_uint_least64_t);
50895 DUK__DUMPSZ(duk_int_least64_t);
50896#endif
50897 DUK__DUMPSZ(duk_uint_fast8_t);
50898 DUK__DUMPSZ(duk_int_fast8_t);
50899 DUK__DUMPSZ(duk_uint_fast16_t);
50900 DUK__DUMPSZ(duk_int_fast16_t);
50901 DUK__DUMPSZ(duk_uint_fast32_t);
50902 DUK__DUMPSZ(duk_int_fast32_t);
50903#if defined(DUK_USE_64BIT_OPS)
50904 DUK__DUMPSZ(duk_uint_fast64_t);
50905 DUK__DUMPSZ(duk_int_fast64_t);
50906#endif
50907 DUK__DUMPSZ(duk_uintptr_t);
50908 DUK__DUMPSZ(duk_intptr_t);
50909 DUK__DUMPSZ(duk_uintmax_t);
50910 DUK__DUMPSZ(duk_intmax_t);
50911 DUK__DUMPSZ(duk_double_t);
50912
50913 /* important chosen base types */
50914 DUK__DUMPSZ(duk_int_t);
50915 DUK__DUMPSZ(duk_uint_t);
50916 DUK__DUMPSZ(duk_int_fast_t);
50917 DUK__DUMPSZ(duk_uint_fast_t);
50918 DUK__DUMPSZ(duk_small_int_t);
50919 DUK__DUMPSZ(duk_small_uint_t);
50920 DUK__DUMPSZ(duk_small_int_fast_t);
50921 DUK__DUMPSZ(duk_small_uint_fast_t);
50922
50923 /* some derived types */
50924 DUK__DUMPSZ(duk_codepoint_t);
50925 DUK__DUMPSZ(duk_ucodepoint_t);
50926 DUK__DUMPSZ(duk_idx_t);
50927 DUK__DUMPSZ(duk_errcode_t);
50928 DUK__DUMPSZ(duk_uarridx_t);
50929
50930 /* tval */
50931 DUK__DUMPSZ(duk_double_union);
50932 DUK__DUMPSZ(duk_tval);
50933
50934 /* structs from duk_forwdecl.h */
50935 DUK__DUMPSZ(duk_jmpbuf); /* just one 'int' for C++ exceptions */
50936 DUK__DUMPSZ(duk_heaphdr);
50937 DUK__DUMPSZ(duk_heaphdr_string);
50938 DUK__DUMPSZ(duk_hstring);
50939 DUK__DUMPSZ(duk_hstring_external);
50940 DUK__DUMPSZ(duk_hobject);
50941 DUK__DUMPSZ(duk_harray);
50942 DUK__DUMPSZ(duk_hcompfunc);
50943 DUK__DUMPSZ(duk_hnatfunc);
50944 DUK__DUMPSZ(duk_hdecenv);
50945 DUK__DUMPSZ(duk_hobjenv);
50946 DUK__DUMPSZ(duk_hthread);
50947#if defined(DUK_USE_BUFFEROBJECT_SUPPORT)
50948 DUK__DUMPSZ(duk_hbufobj);
50949#endif
50950 DUK__DUMPSZ(duk_hproxy);
50951 DUK__DUMPSZ(duk_hbuffer);
50952 DUK__DUMPSZ(duk_hbuffer_fixed);
50953 DUK__DUMPSZ(duk_hbuffer_dynamic);
50954 DUK__DUMPSZ(duk_hbuffer_external);
50955 DUK__DUMPSZ(duk_propaccessor);
50956 DUK__DUMPSZ(duk_propvalue);
50957 DUK__DUMPSZ(duk_propdesc);
50958 DUK__DUMPSZ(duk_heap);
50959 DUK__DUMPSZ(duk_activation);
50960 DUK__DUMPSZ(duk_catcher);
50961 DUK__DUMPSZ(duk_strcache_entry);
50962 DUK__DUMPSZ(duk_litcache_entry);
50963 DUK__DUMPSZ(duk_ljstate);
50964 DUK__DUMPSZ(duk_fixedbuffer);
50965 DUK__DUMPSZ(duk_bitdecoder_ctx);
50966 DUK__DUMPSZ(duk_bitencoder_ctx);
50967 DUK__DUMPSZ(duk_token);
50968 DUK__DUMPSZ(duk_re_token);
50969 DUK__DUMPSZ(duk_lexer_point);
50970 DUK__DUMPSZ(duk_lexer_ctx);
50971 DUK__DUMPSZ(duk_compiler_instr);
50972 DUK__DUMPSZ(duk_compiler_func);
50973 DUK__DUMPSZ(duk_compiler_ctx);
50974 DUK__DUMPSZ(duk_re_matcher_ctx);
50975 DUK__DUMPSZ(duk_re_compiler_ctx);
50976}
50977DUK_LOCAL void duk__dump_type_limits(void) {
50978 DUK_D(DUK_DPRINT("limits"));
50979
50980 /* basic types */
50981 DUK__DUMPLM_SIGNED(INT8);
50982 DUK__DUMPLM_UNSIGNED(UINT8);
50983 DUK__DUMPLM_SIGNED(INT_FAST8);
50984 DUK__DUMPLM_UNSIGNED(UINT_FAST8);
50985 DUK__DUMPLM_SIGNED(INT_LEAST8);
50986 DUK__DUMPLM_UNSIGNED(UINT_LEAST8);
50987 DUK__DUMPLM_SIGNED(INT16);
50988 DUK__DUMPLM_UNSIGNED(UINT16);
50989 DUK__DUMPLM_SIGNED(INT_FAST16);
50990 DUK__DUMPLM_UNSIGNED(UINT_FAST16);
50991 DUK__DUMPLM_SIGNED(INT_LEAST16);
50992 DUK__DUMPLM_UNSIGNED(UINT_LEAST16);
50993 DUK__DUMPLM_SIGNED(INT32);
50994 DUK__DUMPLM_UNSIGNED(UINT32);
50995 DUK__DUMPLM_SIGNED(INT_FAST32);
50996 DUK__DUMPLM_UNSIGNED(UINT_FAST32);
50997 DUK__DUMPLM_SIGNED(INT_LEAST32);
50998 DUK__DUMPLM_UNSIGNED(UINT_LEAST32);
50999#if defined(DUK_USE_64BIT_OPS)
51000 DUK__DUMPLM_SIGNED(INT64);
51001 DUK__DUMPLM_UNSIGNED(UINT64);
51002 DUK__DUMPLM_SIGNED(INT_FAST64);
51003 DUK__DUMPLM_UNSIGNED(UINT_FAST64);
51004 DUK__DUMPLM_SIGNED(INT_LEAST64);
51005 DUK__DUMPLM_UNSIGNED(UINT_LEAST64);
51006#endif
51007 DUK__DUMPLM_SIGNED(INTPTR);
51008 DUK__DUMPLM_UNSIGNED(UINTPTR);
51009 DUK__DUMPLM_SIGNED(INTMAX);
51010 DUK__DUMPLM_UNSIGNED(UINTMAX);
51011
51012 /* derived types */
51013 DUK__DUMPLM_SIGNED(INT);
51014 DUK__DUMPLM_UNSIGNED(UINT);
51015 DUK__DUMPLM_SIGNED(INT_FAST);
51016 DUK__DUMPLM_UNSIGNED(UINT_FAST);
51017 DUK__DUMPLM_SIGNED(SMALL_INT);
51018 DUK__DUMPLM_UNSIGNED(SMALL_UINT);
51019 DUK__DUMPLM_SIGNED(SMALL_INT_FAST);
51020 DUK__DUMPLM_UNSIGNED(SMALL_UINT_FAST);
51021}
51022
51023DUK_LOCAL void duk__dump_misc_options(void) {
51024 DUK_D(DUK_DPRINT("DUK_VERSION: %ld", (long) DUK_VERSION));
51025 DUK_D(DUK_DPRINT("DUK_GIT_DESCRIBE: %s", DUK_GIT_DESCRIBE));
51026 DUK_D(DUK_DPRINT("OS string: %s", DUK_USE_OS_STRING));
51027 DUK_D(DUK_DPRINT("architecture string: %s", DUK_USE_ARCH_STRING));
51028 DUK_D(DUK_DPRINT("compiler string: %s", DUK_USE_COMPILER_STRING));
51029 DUK_D(DUK_DPRINT("debug level: %ld", (long) DUK_USE_DEBUG_LEVEL));
51030#if defined(DUK_USE_PACKED_TVAL)
51031 DUK_D(DUK_DPRINT("DUK_USE_PACKED_TVAL: yes"));
51032#else
51033 DUK_D(DUK_DPRINT("DUK_USE_PACKED_TVAL: no"));
51034#endif
51035#if defined(DUK_USE_VARIADIC_MACROS)
51036 DUK_D(DUK_DPRINT("DUK_USE_VARIADIC_MACROS: yes"));
51037#else
51038 DUK_D(DUK_DPRINT("DUK_USE_VARIADIC_MACROS: no"));
51039#endif
51040#if defined(DUK_USE_INTEGER_LE)
51041 DUK_D(DUK_DPRINT("integer endianness: little"));
51042#elif defined(DUK_USE_INTEGER_ME)
51043 DUK_D(DUK_DPRINT("integer endianness: mixed"));
51044#elif defined(DUK_USE_INTEGER_BE)
51045 DUK_D(DUK_DPRINT("integer endianness: big"));
51046#else
51047 DUK_D(DUK_DPRINT("integer endianness: ???"));
51048#endif
51049#if defined(DUK_USE_DOUBLE_LE)
51050 DUK_D(DUK_DPRINT("IEEE double endianness: little"));
51051#elif defined(DUK_USE_DOUBLE_ME)
51052 DUK_D(DUK_DPRINT("IEEE double endianness: mixed"));
51053#elif defined(DUK_USE_DOUBLE_BE)
51054 DUK_D(DUK_DPRINT("IEEE double endianness: big"));
51055#else
51056 DUK_D(DUK_DPRINT("IEEE double endianness: ???"));
51057#endif
51058}
51059#endif /* DUK_USE_DEBUG */
51060
51063 duk_realloc_function realloc_func,
51064 duk_free_function free_func,
51065 void *heap_udata,
51066 duk_fatal_function fatal_func) {
51067 duk_heap *res = NULL;
51068 duk_uint32_t st_initsize;
51069
51070 DUK_D(DUK_DPRINT("allocate heap"));
51071
51072 /*
51073 * Random config sanity asserts
51074 */
51075
51077
51078 DUK_ASSERT((DUK_HTYPE_STRING & 0x01U) == 0);
51079 DUK_ASSERT((DUK_HTYPE_BUFFER & 0x01U) == 0);
51080 DUK_ASSERT((DUK_HTYPE_OBJECT & 0x01U) == 1); /* DUK_HEAPHDR_IS_OBJECT() relies ont his. */
51081
51082 /*
51083 * Debug dump type sizes
51084 */
51085
51086#if defined(DUK_USE_DEBUG)
51087 duk__dump_misc_options();
51088 duk__dump_type_sizes();
51089 duk__dump_type_limits();
51090#endif
51091
51092 /*
51093 * If selftests enabled, run them as early as possible.
51094 */
51095
51096#if defined(DUK_USE_SELF_TESTS)
51097 DUK_D(DUK_DPRINT("run self tests"));
51098 if (duk_selftest_run_tests(alloc_func, realloc_func, free_func, heap_udata) > 0) {
51099 fatal_func(heap_udata, "self test(s) failed");
51100 }
51101 DUK_D(DUK_DPRINT("self tests passed"));
51102#endif
51103
51104 /*
51105 * Important assert-like checks that should be enabled even
51106 * when assertions are otherwise not enabled.
51107 */
51108
51109#if defined(DUK_USE_EXEC_REGCONST_OPTIMIZE)
51110 /* Can't check sizeof() using preprocessor so explicit check.
51111 * This will be optimized away in practice; unfortunately a
51112 * warning is generated on some compilers as a result.
51113 */
51114#if defined(DUK_USE_PACKED_TVAL)
51115 if (sizeof(duk_tval) != 8) {
51116#else
51117 if (sizeof(duk_tval) != 16) {
51118#endif
51119 fatal_func(heap_udata, "sizeof(duk_tval) not 8 or 16, cannot use DUK_USE_EXEC_REGCONST_OPTIMIZE option");
51120 }
51121#endif /* DUK_USE_EXEC_REGCONST_OPTIMIZE */
51122
51123 /*
51124 * Computed values (e.g. INFINITY)
51125 */
51126
51127#if defined(DUK_USE_COMPUTED_NAN)
51128 do {
51129 /* Workaround for some exotic platforms where NAN is missing
51130 * and the expression (0.0 / 0.0) does NOT result in a NaN.
51131 * Such platforms use the global 'duk_computed_nan' which must
51132 * be initialized at runtime. Use 'volatile' to ensure that
51133 * the compiler will actually do the computation and not try
51134 * to do constant folding which might result in the original
51135 * problem.
51136 */
51137 volatile double dbl1 = 0.0;
51138 volatile double dbl2 = 0.0;
51139 duk_computed_nan = dbl1 / dbl2;
51140 } while (0);
51141#endif
51142
51143#if defined(DUK_USE_COMPUTED_INFINITY)
51144 do {
51145 /* Similar workaround for INFINITY. */
51146 volatile double dbl1 = 1.0;
51147 volatile double dbl2 = 0.0;
51148 duk_computed_infinity = dbl1 / dbl2;
51149 } while (0);
51150#endif
51151
51152 /*
51153 * Allocate heap struct
51154 *
51155 * Use a raw call, all macros expect the heap to be initialized
51156 */
51157
51158#if defined(DUK_USE_INJECT_HEAP_ALLOC_ERROR) && (DUK_USE_INJECT_HEAP_ALLOC_ERROR == 1)
51159 goto failed;
51160#endif
51161 DUK_D(DUK_DPRINT("alloc duk_heap object"));
51162 res = (duk_heap *) alloc_func(heap_udata, sizeof(duk_heap));
51163 if (!res) {
51164 goto failed;
51165 }
51166
51167 /*
51168 * Zero the struct, and start initializing roughly in order
51169 */
51170
51171 duk_memzero(res, sizeof(*res));
51172#if defined(DUK_USE_ASSERTIONS)
51173 res->heap_initializing = 1;
51174#endif
51175
51176 /* explicit NULL inits */
51177#if defined(DUK_USE_EXPLICIT_NULL_INIT)
51178 res->heap_udata = NULL;
51179 res->heap_allocated = NULL;
51180#if defined(DUK_USE_REFERENCE_COUNTING)
51181 res->refzero_list = NULL;
51182#endif
51183#if defined(DUK_USE_FINALIZER_SUPPORT)
51184 res->finalize_list = NULL;
51185#if defined(DUK_USE_ASSERTIONS)
51186 res->currently_finalizing = NULL;
51187#endif
51188#endif
51189#if defined(DUK_USE_CACHE_ACTIVATION)
51190 res->activation_free = NULL;
51191#endif
51192#if defined(DUK_USE_CACHE_CATCHER)
51193 res->catcher_free = NULL;
51194#endif
51195 res->heap_thread = NULL;
51196 res->curr_thread = NULL;
51197 res->heap_object = NULL;
51198#if defined(DUK_USE_STRTAB_PTRCOMP)
51199 res->strtable16 = NULL;
51200#else
51201 res->strtable = NULL;
51202#endif
51203#if defined(DUK_USE_ROM_STRINGS)
51204 /* no res->strs[] */
51205#else /* DUK_USE_ROM_STRINGS */
51206#if defined(DUK_USE_HEAPPTR16)
51207 /* res->strs16[] is zeroed and zero decodes to NULL, so no NULL inits. */
51208#else
51209 {
51211 for (i = 0; i < DUK_HEAP_NUM_STRINGS; i++) {
51212 res->strs[i] = NULL;
51213 }
51214 }
51215#endif
51216#endif /* DUK_USE_ROM_STRINGS */
51217#if defined(DUK_USE_DEBUGGER_SUPPORT)
51218 res->dbg_read_cb = NULL;
51219 res->dbg_write_cb = NULL;
51220 res->dbg_peek_cb = NULL;
51221 res->dbg_read_flush_cb = NULL;
51222 res->dbg_write_flush_cb = NULL;
51223 res->dbg_request_cb = NULL;
51224 res->dbg_udata = NULL;
51225 res->dbg_pause_act = NULL;
51226#endif
51227#endif /* DUK_USE_EXPLICIT_NULL_INIT */
51228
51229 res->alloc_func = alloc_func;
51230 res->realloc_func = realloc_func;
51231 res->free_func = free_func;
51232 res->heap_udata = heap_udata;
51233 res->fatal_func = fatal_func;
51234
51235 /* XXX: for now there's a pointer packing zero assumption, i.e.
51236 * NULL <=> compressed pointer 0. If this is removed, may need
51237 * to precompute e.g. null16 here.
51238 */
51239
51240 /* res->ms_trigger_counter == 0 -> now causes immediate GC; which is OK */
51241
51242 /* Prevent mark-and-sweep and finalizer execution until heap is completely
51243 * initialized.
51244 */
51245 DUK_ASSERT(res->ms_prevent_count == 0);
51246 DUK_ASSERT(res->pf_prevent_count == 0);
51247 res->ms_prevent_count = 1;
51248 res->pf_prevent_count = 1;
51249 DUK_ASSERT(res->ms_running == 0);
51250
51251 res->call_recursion_depth = 0;
51253
51254 /* XXX: use the pointer as a seed for now: mix in time at least */
51255
51256 /* The casts through duk_uintptr_t is to avoid the following GCC warning:
51257 *
51258 * warning: cast from pointer to integer of different size [-Wpointer-to-int-cast]
51259 *
51260 * This still generates a /Wp64 warning on VS2010 when compiling for x86.
51261 */
51262#if defined(DUK_USE_ROM_STRINGS)
51263 /* XXX: make a common DUK_USE_ option, and allow custom fixed seed? */
51264 DUK_D(DUK_DPRINT("using rom strings, force heap hash_seed to fixed value 0x%08lx", (long) DUK__FIXED_HASH_SEED));
51265 res->hash_seed = (duk_uint32_t) DUK__FIXED_HASH_SEED;
51266#else /* DUK_USE_ROM_STRINGS */
51267 res->hash_seed = (duk_uint32_t) (duk_uintptr_t) res;
51268#if !defined(DUK_USE_STRHASH_DENSE)
51269 res->hash_seed ^= 5381; /* Bernstein hash init value is normally 5381; XOR it in in case pointer low bits are 0 */
51270#endif
51271#endif /* DUK_USE_ROM_STRINGS */
51272
51273#if defined(DUK_USE_EXPLICIT_NULL_INIT)
51274 res->lj.jmpbuf_ptr = NULL;
51275#endif
51276 DUK_ASSERT(res->lj.type == DUK_LJ_TYPE_UNKNOWN); /* zero */
51277 DUK_ASSERT(res->lj.iserror == 0);
51280
51282
51283 /*
51284 * Init stringtable: fixed variant
51285 */
51286
51287 st_initsize = DUK_USE_STRTAB_MINSIZE;
51288#if defined(DUK_USE_STRTAB_PTRCOMP)
51289 res->strtable16 = (duk_uint16_t *) alloc_func(heap_udata, sizeof(duk_uint16_t) * st_initsize);
51290 if (res->strtable16 == NULL) {
51291 goto failed;
51292 }
51293#else
51294 res->strtable = (duk_hstring **) alloc_func(heap_udata, sizeof(duk_hstring *) * st_initsize);
51295 if (res->strtable == NULL) {
51296 goto failed;
51297 }
51298#endif
51299 res->st_size = st_initsize;
51300 res->st_mask = st_initsize - 1;
51301#if (DUK_USE_STRTAB_MINSIZE != DUK_USE_STRTAB_MAXSIZE)
51302 DUK_ASSERT(res->st_count == 0);
51303#endif
51304
51305#if defined(DUK_USE_STRTAB_PTRCOMP)
51306 /* zero assumption */
51307 duk_memzero(res->strtable16, sizeof(duk_uint16_t) * st_initsize);
51308#else
51309#if defined(DUK_USE_EXPLICIT_NULL_INIT)
51310 {
51311 duk_uint32_t i;
51312 for (i = 0; i < st_initsize; i++) {
51313 res->strtable[i] = NULL;
51314 }
51315 }
51316#else
51317 duk_memzero(res->strtable, sizeof(duk_hstring *) * st_initsize);
51318#endif /* DUK_USE_EXPLICIT_NULL_INIT */
51319#endif /* DUK_USE_STRTAB_PTRCOMP */
51320
51321 /*
51322 * Init stringcache
51323 */
51324
51325#if defined(DUK_USE_EXPLICIT_NULL_INIT)
51326 {
51327 duk_uint_t i;
51328 for (i = 0; i < DUK_HEAP_STRCACHE_SIZE; i++) {
51329 res->strcache[i].h = NULL;
51330 }
51331 }
51332#endif
51333
51334 /*
51335 * Init litcache
51336 */
51337#if defined(DUK_USE_LITCACHE_SIZE)
51340#if defined(DUK_USE_EXPLICIT_NULL_INIT)
51341 {
51342 duk_uint_t i;
51343 for (i = 0; i < DUK_USE_LITCACHE_SIZE; i++) {
51344 res->litcache[i].addr = NULL;
51345 res->litcache[i].h = NULL;
51346 }
51347 }
51348#endif
51349#endif /* DUK_USE_LITCACHE_SIZE */
51350
51351 /* XXX: error handling is incomplete. It would be cleanest if
51352 * there was a setjmp catchpoint, so that all init code could
51353 * freely throw errors. If that were the case, the return code
51354 * passing here could be removed.
51355 */
51356
51357 /*
51358 * Init built-in strings
51359 */
51360
51361#if defined(DUK_USE_INJECT_HEAP_ALLOC_ERROR) && (DUK_USE_INJECT_HEAP_ALLOC_ERROR == 2)
51362 goto failed;
51363#endif
51364 DUK_D(DUK_DPRINT("heap init: initialize heap strings"));
51365 if (!duk__init_heap_strings(res)) {
51366 goto failed;
51367 }
51368
51369 /*
51370 * Init the heap thread
51371 */
51372
51373#if defined(DUK_USE_INJECT_HEAP_ALLOC_ERROR) && (DUK_USE_INJECT_HEAP_ALLOC_ERROR == 3)
51374 goto failed;
51375#endif
51376 DUK_D(DUK_DPRINT("heap init: initialize heap thread"));
51377 if (!duk__init_heap_thread(res)) {
51378 goto failed;
51379 }
51380
51381 /*
51382 * Init the heap object
51383 */
51384
51385#if defined(DUK_USE_INJECT_HEAP_ALLOC_ERROR) && (DUK_USE_INJECT_HEAP_ALLOC_ERROR == 4)
51386 goto failed;
51387#endif
51388 DUK_D(DUK_DPRINT("heap init: initialize heap object"));
51389 DUK_ASSERT(res->heap_thread != NULL);
51393 if (res->heap_object == NULL) {
51394 goto failed;
51395 }
51397
51398 /*
51399 * Odds and ends depending on the heap thread
51400 */
51401
51402#if !defined(DUK_USE_GET_RANDOM_DOUBLE)
51403#if defined(DUK_USE_PREFER_SIZE) || !defined(DUK_USE_64BIT_OPS)
51404 res->rnd_state = (duk_uint32_t) duk_time_get_ecmascript_time(res->heap_thread);
51406#else
51407 res->rnd_state[0] = (duk_uint64_t) duk_time_get_ecmascript_time(res->heap_thread);
51408 DUK_ASSERT(res->rnd_state[1] == 0); /* Not filled here, filled in by seed preparation. */
51409#if 0 /* Manual test values matching misc/xoroshiro128plus_test.c. */
51410 res->rnd_state[0] = DUK_U64_CONSTANT(0xdeadbeef12345678);
51411 res->rnd_state[1] = DUK_U64_CONSTANT(0xcafed00d12345678);
51412#endif
51414 /* Mix in heap pointer: this ensures that if two Duktape heaps are
51415 * created on the same millisecond, they get a different PRNG
51416 * sequence (unless e.g. virtual memory addresses cause also the
51417 * heap object pointer to be the same).
51418 */
51419 {
51420 duk_uint64_t tmp_u64;
51421 tmp_u64 = 0;
51422 duk_memcpy((void *) &tmp_u64,
51423 (const void *) &res,
51424 (size_t) (sizeof(void *) >= sizeof(duk_uint64_t) ? sizeof(duk_uint64_t) : sizeof(void *)));
51425 res->rnd_state[1] ^= tmp_u64;
51426 }
51427 do {
51429 for (i = 0; i < 10; i++) {
51430 /* Throw away a few initial random numbers just in
51431 * case. Probably unnecessary due to SplitMix64
51432 * preparation.
51433 */
51434 (void) duk_util_tinyrandom_get_double(res->heap_thread);
51435 }
51436 } while (0);
51437#endif
51438#endif
51439
51440 /*
51441 * Allow finalizer and mark-and-sweep processing.
51442 */
51443
51444 DUK_D(DUK_DPRINT("heap init: allow finalizer/mark-and-sweep processing"));
51445 DUK_ASSERT(res->ms_prevent_count == 1);
51446 DUK_ASSERT(res->pf_prevent_count == 1);
51447 res->ms_prevent_count = 0;
51448 res->pf_prevent_count = 0;
51449 DUK_ASSERT(res->ms_running == 0);
51450#if defined(DUK_USE_ASSERTIONS)
51451 res->heap_initializing = 0;
51452#endif
51453
51454 /*
51455 * All done.
51456 */
51457
51458 DUK_D(DUK_DPRINT("allocated heap: %p", (void *) res));
51459 return res;
51460
51461failed:
51462 DUK_D(DUK_DPRINT("heap allocation failed"));
51463
51464 if (res != NULL) {
51465 /* Assumes that allocated pointers and alloc funcs are valid
51466 * if res exists.
51467 */
51468 DUK_ASSERT(res->ms_prevent_count == 1);
51469 DUK_ASSERT(res->pf_prevent_count == 1);
51470 DUK_ASSERT(res->ms_running == 0);
51471 if (res->heap_thread != NULL) {
51472 res->ms_prevent_count = 0;
51473 res->pf_prevent_count = 0;
51474 }
51475#if defined(DUK_USE_ASSERTIONS)
51476 res->heap_initializing = 0;
51477#endif
51478
51479 DUK_ASSERT(res->alloc_func != NULL);
51480 DUK_ASSERT(res->realloc_func != NULL);
51481 DUK_ASSERT(res->free_func != NULL);
51482 duk_heap_free(res);
51483 }
51484
51485 return NULL;
51486}
51487
51488/* automatic undefs */
51489#undef DUK__DUMPLM_SIGNED
51490#undef DUK__DUMPLM_SIGNED_RAW
51491#undef DUK__DUMPLM_UNSIGNED
51492#undef DUK__DUMPLM_UNSIGNED_RAW
51493#undef DUK__DUMPSZ
51494#undef DUK__FIXED_HASH_SEED
51495/*
51496 * Finalizer handling.
51497 */
51498
51499/* #include duk_internal.h -> already included */
51500
51501#if defined(DUK_USE_FINALIZER_SUPPORT)
51502
51503/*
51504 * Fake torture finalizer.
51505 */
51506
51507#if defined(DUK_USE_FINALIZER_TORTURE)
51508DUK_LOCAL duk_ret_t duk__fake_global_finalizer(duk_hthread *thr) {
51509 DUK_DD(DUK_DDPRINT("fake global torture finalizer executed"));
51510
51511 /* Require a lot of stack to force a value stack grow/shrink. */
51512 duk_require_stack(thr, 100000);
51513
51514 /* Force a reallocation with pointer change for value stack
51515 * to maximize side effects.
51516 */
51517 duk_hthread_valstack_torture_realloc(thr);
51518
51519 /* Inner function call, error throw. */
51521 "(function dummy() {\n"
51522 " dummy.prototype = null; /* break reference loop */\n"
51523 " try {\n"
51524 " throw 'fake-finalizer-dummy-error';\n"
51525 " } catch (e) {\n"
51526 " void e;\n"
51527 " }\n"
51528 "})()");
51529
51530 /* The above creates garbage (e.g. a function instance). Because
51531 * the function/prototype reference loop is broken, it gets collected
51532 * immediately by DECREF. If Function.prototype has a _Finalizer
51533 * property (happens in some test cases), the garbage gets queued to
51534 * finalize_list. This still won't cause an infinite loop because
51535 * the torture finalizer is called once per finalize_list run and
51536 * the garbage gets handled in the same run. (If the garbage needs
51537 * mark-and-sweep collection, an infinite loop might ensue.)
51538 */
51539 return 0;
51540}
51541
51542DUK_LOCAL void duk__run_global_torture_finalizer(duk_hthread *thr) {
51543 DUK_ASSERT(thr != NULL);
51544
51545 /* Avoid fake finalization when callstack limit is near. Otherwise
51546 * a callstack limit error will be created, then refzero'ed. The
51547 * +5 headroom is conservative.
51548 */
51549 if (thr->heap->call_recursion_depth + 5 >= thr->heap->call_recursion_limit ||
51551 DUK_D(DUK_DPRINT("skip global torture finalizer, too little headroom for call recursion or call stack size"));
51552 return;
51553 }
51554
51555 /* Run fake finalizer. Avoid creating unnecessary garbage. */
51556 duk_push_c_function(thr, duk__fake_global_finalizer, 0 /*nargs*/);
51557 (void) duk_pcall(thr, 0 /*nargs*/);
51558 duk_pop(thr);
51559}
51560#endif /* DUK_USE_FINALIZER_TORTURE */
51561
51562/*
51563 * Process the finalize_list to completion.
51564 *
51565 * An object may be placed on finalize_list by either refcounting or
51566 * mark-and-sweep. The refcount of objects placed by refcounting will be
51567 * zero; the refcount of objects placed by mark-and-sweep is > 0. In both
51568 * cases the refcount is bumped by 1 artificially so that a REFZERO event
51569 * can never happen while an object is waiting for finalization. Without
51570 * this bump a REFZERO could now happen because user code may call
51571 * duk_push_heapptr() and then pop a value even when it's on finalize_list.
51572 *
51573 * List processing assumes refcounts are kept up-to-date at all times, so
51574 * that once the finalizer returns, a zero refcount is a reliable reason to
51575 * free the object immediately rather than place it back to the heap. This
51576 * is the case because we run outside of refzero_list processing so that
51577 * DECREF cascades are handled fully inline.
51578 *
51579 * For mark-and-sweep queued objects (had_zero_refcount false) the object
51580 * may be freed immediately if its refcount is zero after the finalizer call
51581 * (i.e. finalizer removed the reference loop for the object). If not, the
51582 * next mark-and-sweep will collect the object unless it has become reachable
51583 * (i.e. rescued) by that time and its refcount hasn't fallen to zero before
51584 * that. Mark-and-sweep detects these objects because their FINALIZED flag
51585 * is set.
51586 *
51587 * There's an inherent limitation for mark-and-sweep finalizer rescuing: an
51588 * object won't get refinalized if (1) it's rescued, but (2) becomes
51589 * unreachable before mark-and-sweep has had time to notice it. The next
51590 * mark-and-sweep round simply doesn't have any information of whether the
51591 * object has been unreachable the whole time or not (the only way to get
51592 * that information would be a mark-and-sweep pass for *every finalized
51593 * object*). This is awkward for the application because the mark-and-sweep
51594 * round is not generally visible or under full application control.
51595 *
51596 * For refcount queued objects (had_zero_refcount true) the object is either
51597 * immediately freed or rescued, and waiting for a mark-and-sweep round is not
51598 * necessary (or desirable); FINALIZED is cleared when a rescued object is
51599 * queued back to heap_allocated. The object is eligible for finalization
51600 * again (either via refcounting or mark-and-sweep) immediately after being
51601 * rescued. If a refcount finalized object is placed into an unreachable
51602 * reference loop by its finalizer, it will get collected by mark-and-sweep
51603 * and currently the finalizer will execute again.
51604 *
51605 * There's a special case where:
51606 *
51607 * - Mark-and-sweep queues an object to finalize_list for finalization.
51608 * - The finalizer is executed, FINALIZED is set, and object is queued
51609 * back to heap_allocated, waiting for a new mark-and-sweep round.
51610 * - The object's refcount drops to zero before mark-and-sweep has a
51611 * chance to run another round and make a rescue/free decision.
51612 *
51613 * This is now handled by refzero code: if an object has a finalizer but
51614 * FINALIZED is already set, the object is freed without finalizer processing.
51615 * The outcome is the same as if mark-and-sweep was executed at that point;
51616 * mark-and-sweep would also free the object without another finalizer run.
51617 * This could also be changed so that the refzero-triggered finalizer *IS*
51618 * executed: being refzero collected implies someone has operated on the
51619 * object so it hasn't been totally unreachable the whole time. This would
51620 * risk a finalizer loop however.
51621 */
51622
51624 duk_heaphdr *curr;
51625#if defined(DUK_USE_DEBUG)
51626 duk_size_t count = 0;
51627#endif
51628
51629 DUK_DDD(DUK_DDDPRINT("duk_heap_process_finalize_list: %p", (void *) heap));
51630
51631 if (heap->pf_prevent_count != 0) {
51632 DUK_DDD(DUK_DDDPRINT("skip finalize_list processing: pf_prevent_count != 0"));
51633 return;
51634 }
51635
51636 /* Heap alloc prevents mark-and-sweep before heap_thread is ready. */
51637 DUK_ASSERT(heap != NULL);
51638 DUK_ASSERT(heap->heap_thread != NULL);
51639 DUK_ASSERT(heap->heap_thread->valstack != NULL);
51640#if defined(DUK_USE_REFERENCE_COUNTING)
51641 DUK_ASSERT(heap->refzero_list == NULL);
51642#endif
51643
51644 DUK_ASSERT(heap->pf_prevent_count == 0);
51645 heap->pf_prevent_count = 1;
51646
51647 /* Mark-and-sweep no longer needs to be prevented when running
51648 * finalizers: mark-and-sweep skips any rescue decisions if there
51649 * are any objects in finalize_list when mark-and-sweep is entered.
51650 * This protects finalized objects from incorrect rescue decisions
51651 * caused by finalize_list being a reachability root and only
51652 * partially processed. Freeing decisions are not postponed.
51653 */
51654
51655 /* When finalizer torture is enabled, make a fake finalizer call with
51656 * maximum side effects regardless of whether finalize_list is empty.
51657 */
51658#if defined(DUK_USE_FINALIZER_TORTURE)
51659 duk__run_global_torture_finalizer(heap->heap_thread);
51660#endif
51661
51662 /* Process finalize_list until it becomes empty. There's currently no
51663 * protection against a finalizer always creating more garbage.
51664 */
51665 while ((curr = heap->finalize_list) != NULL) {
51666#if defined(DUK_USE_REFERENCE_COUNTING)
51667 duk_bool_t queue_back;
51668#endif
51669
51670 DUK_DD(DUK_DDPRINT("processing finalize_list entry: %p -> %!iO", (void *) curr, curr));
51671
51672 DUK_ASSERT(DUK_HEAPHDR_GET_TYPE(curr) == DUK_HTYPE_OBJECT); /* Only objects have finalizers. */
51676 curr)); /* All objects on finalize_list will have this flag (except object being finalized right now). */
51677 DUK_ASSERT(!DUK_HEAPHDR_HAS_FINALIZED(curr)); /* Queueing code ensures. */
51678 DUK_ASSERT(!DUK_HEAPHDR_HAS_READONLY(curr)); /* ROM objects never get freed (or finalized). */
51679
51680#if defined(DUK_USE_ASSERTIONS)
51681 DUK_ASSERT(heap->currently_finalizing == NULL);
51682 heap->currently_finalizing = curr;
51683#endif
51684
51685 /* Clear FINALIZABLE for object being finalized, so that
51686 * duk_push_heapptr() can properly ignore the object.
51687 */
51689
51690 if (DUK_LIKELY(!heap->pf_skip_finalizers)) {
51691 /* Run the finalizer, duk_heap_run_finalizer() sets
51692 * and checks for FINALIZED to prevent the finalizer
51693 * from executing multiple times per finalization cycle.
51694 * (This safeguard shouldn't be actually needed anymore).
51695 */
51696
51697#if defined(DUK_USE_REFERENCE_COUNTING)
51698 duk_bool_t had_zero_refcount;
51699#endif
51700
51701 /* The object's refcount is >0 throughout so it won't be
51702 * refzero processed prematurely.
51703 */
51704#if defined(DUK_USE_REFERENCE_COUNTING)
51706 had_zero_refcount = (DUK_HEAPHDR_GET_REFCOUNT(curr) == 1); /* Preincremented on finalize_list insert. */
51707#endif
51708
51710 duk_heap_run_finalizer(heap, (duk_hobject *) curr); /* must never longjmp */
51712 /* XXX: assert that object is still in finalize_list
51713 * when duk_push_heapptr() allows automatic rescue.
51714 */
51715
51716#if defined(DUK_USE_REFERENCE_COUNTING)
51717 DUK_DD(DUK_DDPRINT("refcount after finalizer (includes bump): %ld", (long) DUK_HEAPHDR_GET_REFCOUNT(curr)));
51718 if (DUK_HEAPHDR_GET_REFCOUNT(curr) == 1) { /* Only artificial bump in refcount? */
51719#if defined(DUK_USE_DEBUG)
51720 if (had_zero_refcount) {
51722 "finalized object's refcount is zero -> free immediately (refcount queued)"));
51723 } else {
51725 "finalized object's refcount is zero -> free immediately (mark-and-sweep queued)"));
51726 }
51727#endif
51728 queue_back = 0;
51729 } else
51730#endif
51731 {
51732#if defined(DUK_USE_REFERENCE_COUNTING)
51733 queue_back = 1;
51734 if (had_zero_refcount) {
51735 /* When finalization is triggered
51736 * by refzero and we queue the object
51737 * back, clear FINALIZED right away
51738 * so that the object can be refinalized
51739 * immediately if necessary.
51740 */
51742 }
51743#endif
51744 }
51745 } else {
51746 /* Used during heap destruction: don't actually run finalizers
51747 * because we're heading into forced finalization. Instead,
51748 * queue finalizable objects back to the heap_allocated list.
51749 */
51750 DUK_D(DUK_DPRINT("skip finalizers flag set, queue object to heap_allocated without finalizing"));
51752#if defined(DUK_USE_REFERENCE_COUNTING)
51753 queue_back = 1;
51754#endif
51755 }
51756
51757 /* Dequeue object from finalize_list. Note that 'curr' may no
51758 * longer be finalize_list head because new objects may have
51759 * been queued to the list. As a result we can't optimize for
51760 * the single-linked heap case and must scan the list for
51761 * removal, typically the scan is very short however.
51762 */
51764
51765 /* Queue back to heap_allocated or free immediately. */
51766#if defined(DUK_USE_REFERENCE_COUNTING)
51767 if (queue_back) {
51768 /* FINALIZED is only cleared if object originally
51769 * queued for finalization by refcounting. For
51770 * mark-and-sweep FINALIZED is left set, so that
51771 * next mark-and-sweep round can make a rescue/free
51772 * decision.
51773 */
51775 DUK_HEAPHDR_PREDEC_REFCOUNT(curr); /* Remove artificial refcount bump. */
51778 } else {
51779 /* No need to remove the refcount bump here. */
51780 DUK_ASSERT(DUK_HEAPHDR_GET_TYPE(curr) == DUK_HTYPE_OBJECT); /* currently, always the case */
51781 DUK_DD(DUK_DDPRINT("refcount finalize after finalizer call: %!O", curr));
51783 duk_free_hobject(heap, (duk_hobject *) curr);
51784 DUK_DD(DUK_DDPRINT("freed hobject after finalization: %p", (void *) curr));
51785 }
51786#else /* DUK_USE_REFERENCE_COUNTING */
51789#endif /* DUK_USE_REFERENCE_COUNTING */
51790
51791#if defined(DUK_USE_DEBUG)
51792 count++;
51793#endif
51794
51795#if defined(DUK_USE_ASSERTIONS)
51796 DUK_ASSERT(heap->currently_finalizing != NULL);
51797 heap->currently_finalizing = NULL;
51798#endif
51799 }
51800
51801 /* finalize_list will always be processed completely. */
51802 DUK_ASSERT(heap->finalize_list == NULL);
51803
51804#if 0
51805 /* While NORZ macros are used above, this is unnecessary because the
51806 * only pending side effects are now finalizers, and finalize_list is
51807 * empty.
51808 */
51810#endif
51811
51812 /* Prevent count may be bumped while finalizers run, but should always
51813 * be reliably unbumped by the time we get here.
51814 */
51815 DUK_ASSERT(heap->pf_prevent_count == 1);
51816 heap->pf_prevent_count = 0;
51817
51818#if defined(DUK_USE_DEBUG)
51819 DUK_DD(DUK_DDPRINT("duk_heap_process_finalize_list: %ld finalizers called", (long) count));
51820#endif
51821}
51822
51823/*
51824 * Run an duk_hobject finalizer. Must never throw an uncaught error
51825 * (but may throw caught errors).
51826 *
51827 * There is no return value. Any return value or error thrown by
51828 * the finalizer is ignored (although errors are debug logged).
51829 *
51830 * Notes:
51831 *
51832 * - The finalizer thread 'top' assertions are there because it is
51833 * critical that strict stack policy is observed (i.e. no cruft
51834 * left on the finalizer stack).
51835 */
51836
51838 DUK_ASSERT(thr != NULL);
51839 DUK_UNREF(udata);
51840
51841 DUK_DDD(DUK_DDDPRINT("protected finalization helper running"));
51842
51843 /* [... obj] */
51844
51845 /* _Finalizer property is read without checking if the value is
51846 * callable or even exists. This is intentional, and handled
51847 * by throwing an error which is caught by the safe call wrapper.
51848 *
51849 * XXX: Finalizer lookup should traverse the prototype chain (to allow
51850 * inherited finalizers) but should not invoke accessors or proxy object
51851 * behavior. At the moment this lookup will invoke proxy behavior, so
51852 * caller must ensure that this function is not called if the target is
51853 * a Proxy.
51854 */
51855 duk_get_prop_stridx_short(thr, -1, DUK_STRIDX_INT_FINALIZER); /* -> [... obj finalizer] */
51856 duk_dup_m2(thr);
51858 DUK_DDD(DUK_DDDPRINT("calling finalizer"));
51859 duk_call(thr, 2); /* [ ... obj finalizer obj heapDestruct ] -> [ ... obj retval ] */
51860 DUK_DDD(DUK_DDDPRINT("finalizer returned successfully"));
51861 return 0;
51862
51863 /* Note: we rely on duk_safe_call() to fix up the stack for the caller,
51864 * so we don't need to pop stuff here. There is no return value;
51865 * caller determines rescued status based on object refcount.
51866 */
51867}
51868
51870 duk_hthread *thr;
51871 duk_ret_t rc;
51872#if defined(DUK_USE_ASSERTIONS)
51873 duk_idx_t entry_top;
51874#endif
51875
51876 DUK_DD(DUK_DDPRINT("running duk_hobject finalizer for object: %p", (void *) obj));
51877
51878 DUK_ASSERT(heap != NULL);
51879 DUK_ASSERT(heap->heap_thread != NULL);
51880 thr = heap->heap_thread;
51881 DUK_ASSERT(obj != NULL);
51883
51884#if defined(DUK_USE_ASSERTIONS)
51885 entry_top = duk_get_top(thr);
51886#endif
51887 /*
51888 * Get and call the finalizer. All of this must be wrapped
51889 * in a protected call, because even getting the finalizer
51890 * may trigger an error (getter may throw one, for instance).
51891 */
51892
51893 /* ROM objects could inherit a finalizer, but they are never deemed
51894 * unreachable by mark-and-sweep, and their refcount never falls to 0.
51895 */
51897
51898 /* Duktape 2.1: finalize_list never contains objects with FINALIZED
51899 * set, so no need to check here.
51900 */
51902#if 0
51904 DUK_D(DUK_DPRINT("object already finalized, avoid running finalizer twice: %!O", obj));
51905 return;
51906 }
51907#endif
51908 DUK_HEAPHDR_SET_FINALIZED((duk_heaphdr *) obj); /* ensure never re-entered until rescue cycle complete */
51909
51910#if defined(DUK_USE_ES6_PROXY)
51911 if (DUK_HOBJECT_IS_PROXY(obj)) {
51912 /* This may happen if duk_set_finalizer() or Duktape.fin() is
51913 * called for a Proxy object. In such cases the fast finalizer
51914 * flag will be set on the Proxy, not the target, and neither
51915 * will be finalized.
51916 */
51917 DUK_D(DUK_DPRINT("object is a Proxy, skip finalizer call"));
51918 return;
51919 }
51920#endif /* DUK_USE_ES6_PROXY */
51921
51922 duk_push_hobject(thr, obj); /* this also increases refcount by one */
51923 rc = duk_safe_call(thr, duk__finalize_helper, NULL /*udata*/, 0 /*nargs*/, 1 /*nrets*/); /* -> [... obj retval/error] */
51924 DUK_ASSERT_TOP(thr, entry_top + 2); /* duk_safe_call discipline */
51925
51926 if (rc != DUK_EXEC_SUCCESS) {
51927 /* Note: we ask for one return value from duk_safe_call to get this
51928 * error debugging here.
51929 */
51930 DUK_D(DUK_DPRINT("wrapped finalizer call failed for object %p (ignored); error: %!T",
51931 (void *) obj,
51932 (duk_tval *) duk_get_tval(thr, -1)));
51933 }
51934 duk_pop_2(thr); /* -> [...] */
51935
51936 DUK_ASSERT_TOP(thr, entry_top);
51937}
51938
51939#else /* DUK_USE_FINALIZER_SUPPORT */
51940
51941/* nothing */
51942
51943#endif /* DUK_USE_FINALIZER_SUPPORT */
51944/*
51945 * String hash computation (interning).
51946 *
51947 * String hashing is performance critical because a string hash is computed
51948 * for all new strings which are candidates to be added to the string table.
51949 * However, strings actually added to the string table go through a codepoint
51950 * length calculation which dominates performance because it goes through
51951 * every byte of the input string (but only for strings added).
51952 *
51953 * The string hash algorithm should be fast, but on the other hand provide
51954 * good enough hashes to ensure both string table and object property table
51955 * hash tables work reasonably well (i.e., there aren't too many collisions
51956 * with real world inputs). Unless the hash is cryptographic, it's always
51957 * possible to craft inputs with maximal hash collisions.
51958 *
51959 * NOTE: The hash algorithms must match tools/dukutil.py:duk_heap_hashstring()
51960 * for ROM string support!
51961 */
51962
51963/* #include duk_internal.h -> already included */
51964
51965#if defined(DUK_USE_STRHASH_DENSE)
51966/* Constants for duk_hashstring(). */
51967#define DUK__STRHASH_SHORTSTRING 4096L
51968#define DUK__STRHASH_MEDIUMSTRING (256L * 1024L)
51969#define DUK__STRHASH_BLOCKSIZE 256L
51970
51971DUK_INTERNAL duk_uint32_t duk_heap_hashstring(duk_heap *heap, const duk_uint8_t *str, duk_size_t len) {
51972 duk_uint32_t hash;
51973
51974 /* Use Murmurhash2 directly for short strings, and use "block skipping"
51975 * for long strings: hash an initial part and then sample the rest of
51976 * the string with reasonably sized chunks. An initial offset for the
51977 * sampling is computed based on a hash of the initial part of the string;
51978 * this is done to (usually) avoid the case where all long strings have
51979 * certain offset ranges which are never sampled.
51980 *
51981 * Skip should depend on length and bound the total time to roughly
51982 * logarithmic. With current values:
51983 *
51984 * 1M string => 256 * 241 = 61696 bytes (0.06M) of hashing
51985 * 1G string => 256 * 16321 = 4178176 bytes (3.98M) of hashing
51986 *
51987 * XXX: It would be better to compute the skip offset more "smoothly"
51988 * instead of having a few boundary values.
51989 */
51990
51991 /* note: mixing len into seed improves hashing when skipping */
51992 duk_uint32_t str_seed = heap->hash_seed ^ ((duk_uint32_t) len);
51993
51994 if (len <= DUK__STRHASH_SHORTSTRING) {
51995 hash = duk_util_hashbytes(str, len, str_seed);
51996 } else {
51997 duk_size_t off;
51998 duk_size_t skip;
51999
52000 if (len <= DUK__STRHASH_MEDIUMSTRING) {
52001 skip = (duk_size_t) (16 * DUK__STRHASH_BLOCKSIZE + DUK__STRHASH_BLOCKSIZE);
52002 } else {
52003 skip = (duk_size_t) (256 * DUK__STRHASH_BLOCKSIZE + DUK__STRHASH_BLOCKSIZE);
52004 }
52005
52006 hash = duk_util_hashbytes(str, (duk_size_t) DUK__STRHASH_SHORTSTRING, str_seed);
52007 off = DUK__STRHASH_SHORTSTRING + (skip * (hash % 256)) / 256;
52008
52009 /* XXX: inefficient loop */
52010 while (off < len) {
52011 duk_size_t left = len - off;
52012 duk_size_t now = (duk_size_t) (left > DUK__STRHASH_BLOCKSIZE ? DUK__STRHASH_BLOCKSIZE : left);
52013 hash ^= duk_util_hashbytes(str + off, now, str_seed);
52014 off += skip;
52016 }
52017
52018#if defined(DUK_USE_STRHASH16)
52019 /* Truncate to 16 bits here, so that a computed hash can be compared
52020 * against a hash stored in a 16-bit field.
52021 */
52022 hash &= 0x0000ffffUL;
52023#endif
52024 return hash;
52025}
52026#else /* DUK_USE_STRHASH_DENSE */
52027DUK_INTERNAL duk_uint32_t duk_heap_hashstring(duk_heap *heap, const duk_uint8_t *str, duk_size_t len) {
52028 duk_uint32_t hash;
52029 duk_size_t step;
52030 duk_size_t off;
52031
52032 /* Slightly modified "Bernstein hash" from:
52033 *
52034 * http://eternallyconfuzzled.com/tuts/algorithms/jsw_tut_hashing.aspx
52035 *
52036 * Modifications: string skipping and reverse direction similar to
52037 * Lua 5.1.5, and different hash initializer.
52038 *
52039 * The reverse direction ensures last byte it always included in the
52040 * hash which is a good default as changing parts of the string are
52041 * more often in the suffix than in the prefix.
52042 */
52043
52044 hash = heap->hash_seed ^ ((duk_uint32_t) len); /* Bernstein hash init value is normally 5381 */
52045 step = (len >> DUK_USE_STRHASH_SKIP_SHIFT) + 1;
52046 for (off = len; off >= step; off -= step) {
52047 DUK_ASSERT(off >= 1); /* off >= step, and step >= 1 */
52048 hash = (hash * 33) + str[off - 1];
52049 }
52050
52051#if defined(DUK_USE_STRHASH16)
52052 /* Truncate to 16 bits here, so that a computed hash can be compared
52053 * against a hash stored in a 16-bit field.
52054 */
52055 hash &= 0x0000ffffUL;
52056#endif
52057 return hash;
52058}
52059#endif /* DUK_USE_STRHASH_DENSE */
52060
52061/* automatic undefs */
52062#undef DUK__STRHASH_BLOCKSIZE
52063#undef DUK__STRHASH_MEDIUMSTRING
52064#undef DUK__STRHASH_SHORTSTRING
52065/*
52066 * Mark-and-sweep garbage collection.
52067 */
52069/* #include duk_internal.h -> already included */
52070
52075
52076/*
52077 * Marking functions for heap types: mark children recursively.
52078 */
52081 DUK_UNREF(heap);
52082 DUK_UNREF(h);
52083
52084 DUK_DDD(DUK_DDDPRINT("duk__mark_hstring: %p", (void *) h));
52085 DUK_ASSERT(h);
52087
52088 /* nothing to process */
52089}
52090
52093
52094 DUK_DDD(DUK_DDDPRINT("duk__mark_hobject: %p", (void *) h));
52095
52096 DUK_ASSERT(h);
52098
52099 /* XXX: use advancing pointers instead of index macros -> faster and smaller? */
52100
52101 for (i = 0; i < (duk_uint_fast32_t) DUK_HOBJECT_GET_ENEXT(h); i++) {
52102 duk_hstring *key = DUK_HOBJECT_E_GET_KEY(heap, h, i);
52103 if (key == NULL) {
52104 continue;
52105 }
52107 if (DUK_HOBJECT_E_SLOT_IS_ACCESSOR(heap, h, i)) {
52108 duk__mark_heaphdr(heap, (duk_heaphdr *) DUK_HOBJECT_E_GET_VALUE_PTR(heap, h, i)->a.get);
52109 duk__mark_heaphdr(heap, (duk_heaphdr *) DUK_HOBJECT_E_GET_VALUE_PTR(heap, h, i)->a.set);
52110 } else {
52111 duk__mark_tval(heap, &DUK_HOBJECT_E_GET_VALUE_PTR(heap, h, i)->v);
52112 }
52113 }
52114
52115 for (i = 0; i < (duk_uint_fast32_t) DUK_HOBJECT_GET_ASIZE(h); i++) {
52117 }
52118
52119 /* Hash part is a 'weak reference' and does not contribute. */
52120
52122
52123 /* Fast path for objects which don't have a subclass struct, or have a
52124 * subclass struct but nothing that needs marking in the subclass struct.
52125 */
52126 if (DUK_HOBJECT_HAS_FASTREFS(h)) {
52128 return;
52129 }
52131
52132 /* XXX: reorg, more common first */
52133 if (DUK_HOBJECT_IS_COMPFUNC(h)) {
52134 duk_hcompfunc *f = (duk_hcompfunc *) h;
52135 duk_tval *tv, *tv_end;
52136 duk_hobject **fn, **fn_end;
52137
52139
52140 /* 'data' is reachable through every compiled function which
52141 * contains a reference.
52142 */
52143
52147
52148 if (DUK_HCOMPFUNC_GET_DATA(heap, f) != NULL) {
52149 tv = DUK_HCOMPFUNC_GET_CONSTS_BASE(heap, f);
52150 tv_end = DUK_HCOMPFUNC_GET_CONSTS_END(heap, f);
52151 while (tv < tv_end) {
52152 duk__mark_tval(heap, tv);
52153 tv++;
52154 }
52155
52156 fn = DUK_HCOMPFUNC_GET_FUNCS_BASE(heap, f);
52157 fn_end = DUK_HCOMPFUNC_GET_FUNCS_END(heap, f);
52158 while (fn < fn_end) {
52160 fn++;
52161 }
52162 } else {
52163 /* May happen in some out-of-memory corner cases. */
52164 DUK_D(DUK_DPRINT("duk_hcompfunc 'data' is NULL, skipping marking"));
52165 }
52166 } else if (DUK_HOBJECT_IS_DECENV(h)) {
52167 duk_hdecenv *e = (duk_hdecenv *) h;
52169 duk__mark_heaphdr(heap, (duk_heaphdr *) e->thread);
52170 duk__mark_heaphdr(heap, (duk_heaphdr *) e->varmap);
52171 } else if (DUK_HOBJECT_IS_OBJENV(h)) {
52172 duk_hobjenv *e = (duk_hobjenv *) h;
52175#if defined(DUK_USE_BUFFEROBJECT_SUPPORT)
52176 } else if (DUK_HOBJECT_IS_BUFOBJ(h)) {
52177 duk_hbufobj *b = (duk_hbufobj *) h;
52179 duk__mark_heaphdr(heap, (duk_heaphdr *) b->buf);
52181#endif /* DUK_USE_BUFFEROBJECT_SUPPORT */
52182 } else if (DUK_HOBJECT_IS_BOUNDFUNC(h)) {
52183 duk_hboundfunc *f = (duk_hboundfunc *) (void *) h;
52185 duk__mark_tval(heap, &f->target);
52186 duk__mark_tval(heap, &f->this_binding);
52187 duk__mark_tvals(heap, f->args, f->nargs);
52188#if defined(DUK_USE_ES6_PROXY)
52189 } else if (DUK_HOBJECT_IS_PROXY(h)) {
52190 duk_hproxy *p = (duk_hproxy *) h;
52194#endif /* DUK_USE_ES6_PROXY */
52195 } else if (DUK_HOBJECT_IS_THREAD(h)) {
52196 duk_hthread *t = (duk_hthread *) h;
52197 duk_activation *act;
52198 duk_tval *tv;
52199
52201
52202 tv = t->valstack;
52203 while (tv < t->valstack_top) {
52204 duk__mark_tval(heap, tv);
52205 tv++;
52206 }
52207
52208 for (act = t->callstack_curr; act != NULL; act = act->parent) {
52210 duk__mark_heaphdr(heap, (duk_heaphdr *) act->var_env);
52211 duk__mark_heaphdr(heap, (duk_heaphdr *) act->lex_env);
52212#if defined(DUK_USE_NONSTD_FUNC_CALLER_PROPERTY)
52213 duk__mark_heaphdr(heap, (duk_heaphdr *) act->prev_caller);
52214#endif
52215#if 0 /* nothing now */
52216 for (cat = act->cat; cat != NULL; cat = cat->parent) {
52217 }
52218#endif
52219 }
52220
52222
52223 for (i = 0; i < DUK_NUM_BUILTINS; i++) {
52224 duk__mark_heaphdr(heap, (duk_heaphdr *) t->builtins[i]);
52226 } else {
52227 /* We may come here if the object should have a FASTREFS flag
52228 * but it's missing for some reason. Assert for never getting
52229 * here; however, other than performance, this is harmless.
52230 */
52231 DUK_D(DUK_DPRINT("missing FASTREFS flag for: %!iO", h));
52232 DUK_ASSERT(0);
52233 }
52234}
52235
52236/* Mark any duk_heaphdr type. Recursion tracking happens only here. */
52238 DUK_DDD(
52239 DUK_DDDPRINT("duk__mark_heaphdr %p, type %ld", (void *) h, (h != NULL ? (long) DUK_HEAPHDR_GET_TYPE(h) : (long) -1)));
52240
52241 /* XXX: add non-null variant? */
52242 if (h == NULL) {
52243 return;
52244 }
52245
52248
52249#if defined(DUK_USE_ASSERTIONS) && defined(DUK_USE_REFERENCE_COUNTING)
52250 if (!DUK_HEAPHDR_HAS_READONLY(h)) {
52251 h->h_assert_refcount++; /* Comparison refcount: bump even if already reachable. */
52252 }
52253#endif
52255 DUK_DDD(DUK_DDDPRINT("already marked reachable, skip"));
52256 return;
52257 }
52258#if defined(DUK_USE_ROM_OBJECTS)
52259 /* READONLY objects always have REACHABLE set, so the check above
52260 * will prevent READONLY objects from being marked here.
52261 */
52263#endif
52264
52266
52268 DUK_D(DUK_DPRINT("mark-and-sweep recursion limit reached, marking as temproot: %p", (void *) h));
52271 return;
52272 }
52273
52274 heap->ms_recursion_depth++;
52275 DUK_ASSERT(heap->ms_recursion_depth != 0); /* Wrap. */
52276
52277 switch (DUK_HEAPHDR_GET_TYPE(h)) {
52278 case DUK_HTYPE_STRING:
52279 duk__mark_hstring(heap, (duk_hstring *) h);
52280 break;
52281 case DUK_HTYPE_OBJECT:
52282 duk__mark_hobject(heap, (duk_hobject *) h);
52283 break;
52285 /* nothing to mark */
52286 break;
52287 default:
52288 DUK_D(DUK_DPRINT("attempt to mark heaphdr %p with invalid htype %ld", (void *) h, (long) DUK_HEAPHDR_GET_TYPE(h)));
52290 }
52291
52292 DUK_ASSERT(heap->ms_recursion_depth > 0);
52293 heap->ms_recursion_depth--;
52294}
52295
52296DUK_LOCAL void duk__mark_tval(duk_heap *heap, duk_tval *tv) {
52297 DUK_DDD(DUK_DDDPRINT("duk__mark_tval %p", (void *) tv));
52298 if (tv == NULL) {
52299 return;
52300 }
52303 duk_heaphdr *h;
52304 h = DUK_TVAL_GET_HEAPHDR(tv);
52305 DUK_ASSERT(h != NULL);
52307 }
52308}
52309
52311 DUK_ASSERT(count == 0 || tv != NULL);
52312
52313 while (count-- > 0) {
52316 duk_heaphdr *h;
52317 h = DUK_TVAL_GET_HEAPHDR(tv);
52318 DUK_ASSERT(h != NULL);
52320 }
52321 tv++;
52322 }
52323}
52324
52325/* Mark any duk_heaphdr type, caller guarantees a non-NULL pointer. */
52327 /* For now, just call the generic handler. Change when call sites
52328 * are changed too.
52329 */
52330 duk__mark_heaphdr(heap, h);
52331}
52332
52333/*
52334 * Mark the heap.
52335 */
52336
52339
52340 DUK_DD(DUK_DDPRINT("duk__mark_roots_heap: %p", (void *) heap));
52341
52342 duk__mark_heaphdr(heap, (duk_heaphdr *) heap->heap_thread);
52343 duk__mark_heaphdr(heap, (duk_heaphdr *) heap->heap_object);
52344
52345 for (i = 0; i < DUK_HEAP_NUM_STRINGS; i++) {
52346 duk_hstring *h = DUK_HEAP_GET_STRING(heap, i);
52347 duk__mark_heaphdr(heap, (duk_heaphdr *) h);
52348 }
52349
52350 duk__mark_tval(heap, &heap->lj.value1);
52351 duk__mark_tval(heap, &heap->lj.value2);
52352
52353#if defined(DUK_USE_DEBUGGER_SUPPORT)
52354 for (i = 0; i < heap->dbg_breakpoint_count; i++) {
52355 duk__mark_heaphdr(heap, (duk_heaphdr *) heap->dbg_breakpoints[i].filename);
52356 }
52357#endif
52358}
52359
52360/*
52361 * Mark unreachable, finalizable objects.
52362 *
52363 * Such objects will be moved aside and their finalizers run later. They
52364 * have to be treated as reachability roots for their properties etc to
52365 * remain allocated. This marking is only done for unreachable values which
52366 * would be swept later.
52367 *
52368 * Objects are first marked FINALIZABLE and only then marked as reachability
52369 * roots; otherwise circular references might be handled inconsistently.
52370 */
52371
52372#if defined(DUK_USE_FINALIZER_SUPPORT)
52374 duk_heaphdr *hdr;
52375 duk_size_t count_finalizable = 0;
52376
52377 DUK_DD(DUK_DDPRINT("duk__mark_finalizable: %p", (void *) heap));
52378
52379 DUK_ASSERT(heap->heap_thread != NULL);
52380
52381 hdr = heap->heap_allocated;
52382 while (hdr != NULL) {
52383 /* A finalizer is looked up from the object and up its
52384 * prototype chain (which allows inherited finalizers).
52385 * The finalizer is checked for using a duk_hobject flag
52386 * which is kept in sync with the presence and callability
52387 * of a _Finalizer hidden symbol.
52388 */
52389
52392 /* heaphdr:
52393 * - is not reachable
52394 * - is an object
52395 * - is not a finalized object waiting for rescue/keep decision
52396 * - has a finalizer
52397 */
52398
52399 DUK_DD(DUK_DDPRINT("unreachable heap object will be "
52400 "finalized -> mark as finalizable "
52401 "and treat as a reachability root: %p",
52402 (void *) hdr));
52405 count_finalizable++;
52406 }
52407
52408 hdr = DUK_HEAPHDR_GET_NEXT(heap, hdr);
52409 }
52410
52411 if (count_finalizable == 0) {
52412 return;
52413 }
52414
52415 DUK_DD(DUK_DDPRINT("marked %ld heap objects as finalizable, now mark them reachable", (long) count_finalizable));
52416
52417 hdr = heap->heap_allocated;
52418 while (hdr != NULL) {
52419 if (DUK_HEAPHDR_HAS_FINALIZABLE(hdr)) {
52420 duk__mark_heaphdr_nonnull(heap, hdr);
52421 }
52422
52423 hdr = DUK_HEAPHDR_GET_NEXT(heap, hdr);
52424 }
52425
52426 /* Caller will finish the marking process if we hit a recursion limit. */
52427}
52428#endif /* DUK_USE_FINALIZER_SUPPORT */
52429
52430/*
52431 * Mark objects on finalize_list.
52432 */
52433
52434#if defined(DUK_USE_FINALIZER_SUPPORT)
52436 duk_heaphdr *hdr;
52437#if defined(DUK_USE_DEBUG)
52438 duk_size_t count_finalize_list = 0;
52439#endif
52440
52441 DUK_DD(DUK_DDPRINT("duk__mark_finalize_list: %p", (void *) heap));
52442
52443 hdr = heap->finalize_list;
52444 while (hdr != NULL) {
52445 duk__mark_heaphdr_nonnull(heap, hdr);
52446 hdr = DUK_HEAPHDR_GET_NEXT(heap, hdr);
52447#if defined(DUK_USE_DEBUG)
52448 count_finalize_list++;
52449#endif
52450 }
52451
52452#if defined(DUK_USE_DEBUG)
52453 if (count_finalize_list > 0) {
52454 DUK_D(DUK_DPRINT("marked %ld objects on the finalize_list as reachable (previous finalizer run skipped)",
52455 (long) count_finalize_list));
52456 }
52457#endif
52458}
52459#endif /* DUK_USE_FINALIZER_SUPPORT */
52460
52461/*
52462 * Fallback marking handler if recursion limit is reached.
52463 *
52464 * Iterates 'temproots' until recursion limit is no longer hit. Temproots
52465 * can be in heap_allocated or finalize_list; refzero_list is now always
52466 * empty for mark-and-sweep. A temproot may occur in finalize_list now if
52467 * there are objects on the finalize_list and user code creates a reference
52468 * from an object in heap_allocated to the object in finalize_list (which is
52469 * now allowed), and it happened to coincide with the recursion depth limit.
52470 *
52471 * This is a slow scan, but guarantees that we finish with a bounded C stack.
52472 *
52473 * Note that nodes may have been marked as temproots before this scan begun,
52474 * OR they may have been marked during the scan (as we process nodes
52475 * recursively also during the scan). This is intended behavior.
52476 */
52477
52478#if defined(DUK_USE_DEBUG)
52480#else
52482#endif
52483 DUK_ASSERT(hdr != NULL);
52484
52485 if (!DUK_HEAPHDR_HAS_TEMPROOT(hdr)) {
52486 DUK_DDD(DUK_DDDPRINT("not a temp root: %p", (void *) hdr));
52487 return;
52488 }
52489
52490 DUK_DDD(DUK_DDDPRINT("found a temp root: %p", (void *) hdr));
52492 DUK_HEAPHDR_CLEAR_REACHABLE(hdr); /* Done so that duk__mark_heaphdr() works correctly. */
52493#if defined(DUK_USE_ASSERTIONS) && defined(DUK_USE_REFERENCE_COUNTING)
52494 hdr->h_assert_refcount--; /* Same node visited twice. */
52495#endif
52496 duk__mark_heaphdr_nonnull(heap, hdr);
52497
52498#if defined(DUK_USE_DEBUG)
52499 (*count)++;
52500#endif
52501}
52502
52504 duk_heaphdr *hdr;
52505#if defined(DUK_USE_DEBUG)
52507#endif
52508
52509 DUK_DD(DUK_DDPRINT("duk__mark_temproots_by_heap_scan: %p", (void *) heap));
52510
52512 DUK_DD(DUK_DDPRINT("recursion limit reached, doing heap scan to continue from temproots"));
52513
52514#if defined(DUK_USE_DEBUG)
52515 count = 0;
52516#endif
52518
52519 hdr = heap->heap_allocated;
52520 while (hdr) {
52521#if defined(DUK_USE_DEBUG)
52522 duk__handle_temproot(heap, hdr, &count);
52523#else
52524 duk__handle_temproot(heap, hdr);
52525#endif
52526 hdr = DUK_HEAPHDR_GET_NEXT(heap, hdr);
52527 }
52528
52529#if defined(DUK_USE_FINALIZER_SUPPORT)
52530 hdr = heap->finalize_list;
52531 while (hdr) {
52532#if defined(DUK_USE_DEBUG)
52533 duk__handle_temproot(heap, hdr, &count);
52534#else
52535 duk__handle_temproot(heap, hdr);
52536#endif
52537 hdr = DUK_HEAPHDR_GET_NEXT(heap, hdr);
52538 }
52539#endif
52540
52541#if defined(DUK_USE_DEBUG)
52542 DUK_DD(DUK_DDPRINT("temproot mark heap scan processed %ld temp roots", (long) count));
52543#endif
52544 }
52546
52547/*
52548 * Finalize refcounts for heap elements just about to be freed.
52549 * This must be done for all objects before freeing to avoid any
52550 * stale pointer dereferences.
52551 *
52552 * Note that this must deduce the set of objects to be freed
52553 * identically to duk__sweep_heap().
52554 */
52555
52556#if defined(DUK_USE_REFERENCE_COUNTING)
52558 duk_heaphdr *hdr;
52559
52560 DUK_ASSERT(heap->heap_thread != NULL);
52561
52562 DUK_DD(DUK_DDPRINT("duk__finalize_refcounts: heap=%p", (void *) heap));
52563
52564 hdr = heap->heap_allocated;
52565 while (hdr) {
52566 if (!DUK_HEAPHDR_HAS_REACHABLE(hdr)) {
52567 /*
52568 * Unreachable object about to be swept. Finalize target refcounts
52569 * (objects which the unreachable object points to) without doing
52570 * refzero processing. Recursive decrefs are also prevented when
52571 * refzero processing is disabled.
52572 *
52573 * Value cannot be a finalizable object, as they have been made
52574 * temporarily reachable for this round.
52575 */
52576
52577 DUK_DDD(DUK_DDDPRINT("unreachable object, refcount finalize before sweeping: %p", (void *) hdr));
52578
52579 /* Finalize using heap->heap_thread; DECREF has a
52580 * suppress check for mark-and-sweep which is based
52581 * on heap->ms_running.
52582 */
52584 }
52585
52586 hdr = DUK_HEAPHDR_GET_NEXT(heap, hdr);
52587 }
52588}
52589#endif /* DUK_USE_REFERENCE_COUNTING */
52590
52592 * Clear (reachable) flags of finalize_list.
52593 *
52594 * We could mostly do in the sweep phase when we move objects from the
52595 * heap into the finalize_list. However, if a finalizer run is skipped
52596 * during a mark-and-sweep, the objects on the finalize_list will be marked
52597 * reachable during the next mark-and-sweep. Since they're already on the
52598 * finalize_list, no-one will be clearing their REACHABLE flag so we do it
52599 * here. (This now overlaps with the sweep handling in a harmless way.)
52600 */
52601
52602#if defined(DUK_USE_FINALIZER_SUPPORT)
52604 duk_heaphdr *hdr;
52605
52606 DUK_DD(DUK_DDPRINT("duk__clear_finalize_list_flags: %p", (void *) heap));
52607
52608 hdr = heap->finalize_list;
52609 while (hdr) {
52611#if defined(DUK_USE_ASSERTIONS)
52612 DUK_ASSERT(DUK_HEAPHDR_HAS_FINALIZABLE(hdr) || (heap->currently_finalizing == hdr));
52613#endif
52614 /* DUK_HEAPHDR_FLAG_FINALIZED may be set. */
52616 hdr = DUK_HEAPHDR_GET_NEXT(heap, hdr);
52617 }
52618}
52619#endif /* DUK_USE_FINALIZER_SUPPORT */
52620
52621/*
52622 * Sweep stringtable.
52623 */
52624
52625DUK_LOCAL void duk__sweep_stringtable(duk_heap *heap, duk_size_t *out_count_keep) {
52626 duk_hstring *h;
52627 duk_hstring *prev;
52628 duk_uint32_t i;
52629#if defined(DUK_USE_DEBUG)
52630 duk_size_t count_free = 0;
52631#endif
52632 duk_size_t count_keep = 0;
52633
52634 DUK_DD(DUK_DDPRINT("duk__sweep_stringtable: %p", (void *) heap));
52635
52636#if defined(DUK_USE_STRTAB_PTRCOMP)
52637 if (heap->strtable16 == NULL) {
52638#else
52639 if (heap->strtable == NULL) {
52640#endif
52641 goto done;
52642 }
52643
52644 for (i = 0; i < heap->st_size; i++) {
52645#if defined(DUK_USE_STRTAB_PTRCOMP)
52646 h = DUK_USE_HEAPPTR_DEC16(heap->heap_udata, heap->strtable16[i]);
52647#else
52648 h = heap->strtable[i];
52649#endif
52650 prev = NULL;
52651 while (h != NULL) {
52652 duk_hstring *next;
52653 next = h->hdr.h_next;
52654
52657 count_keep++;
52658 prev = h;
52659 } else {
52660#if defined(DUK_USE_DEBUG)
52661 count_free++;
52662#endif
52663
52664 /* For pinned strings the refcount has been
52665 * bumped. We could unbump it here before
52666 * freeing, but that's actually not necessary
52667 * except for assertions.
52668 */
52669#if 0
52674 }
52675#endif
52676#if defined(DUK_USE_REFERENCE_COUNTING)
52677 /* Non-zero refcounts should not happen for unreachable strings,
52678 * because we refcount finalize all unreachable objects which
52679 * should have decreased unreachable string refcounts to zero
52680 * (even for cycles). However, pinned strings have a +1 bump.
52681 */
52683 0U);
52684#endif
52685
52686 /* Deal with weak references first. */
52688
52689 /* Remove the string from the string table. */
52691
52692 /* Free inner references (these exist e.g. when external
52693 * strings are enabled) and the struct itself.
52694 */
52695 duk_free_hstring(heap, (duk_hstring *) h);
52696
52697 /* Don't update 'prev'; it should be last string kept. */
52698 }
52699
52700 h = next;
52701 }
52702 }
52704done:
52705#if defined(DUK_USE_DEBUG)
52706 DUK_D(DUK_DPRINT("mark-and-sweep sweep stringtable: %ld freed, %ld kept", (long) count_free, (long) count_keep));
52707#endif
52708 *out_count_keep = count_keep;
52709}
52710
52711/*
52712 * Sweep heap.
52713 */
52714
52715DUK_LOCAL void duk__sweep_heap(duk_heap *heap, duk_small_uint_t flags, duk_size_t *out_count_keep) {
52716 duk_heaphdr *prev; /* last element that was left in the heap */
52717 duk_heaphdr *curr;
52718 duk_heaphdr *next;
52719#if defined(DUK_USE_DEBUG)
52720 duk_size_t count_free = 0;
52721 duk_size_t count_finalize = 0;
52722 duk_size_t count_rescue = 0;
52723#endif
52724 duk_size_t count_keep = 0;
52725
52726 DUK_DD(DUK_DDPRINT("duk__sweep_heap: %p", (void *) heap));
52727
52728 prev = NULL;
52729 curr = heap->heap_allocated;
52730 heap->heap_allocated = NULL;
52731 while (curr) {
52732 /* Strings and ROM objects are never placed on the heap allocated list. */
52735
52736 next = DUK_HEAPHDR_GET_NEXT(heap, curr);
52737
52738 if (DUK_HEAPHDR_HAS_REACHABLE(curr)) {
52739 /*
52740 * Reachable object:
52741 * - If FINALIZABLE -> actually unreachable (but marked
52742 * artificially reachable), queue to finalize_list.
52743 * - If !FINALIZABLE but FINALIZED -> rescued after
52744 * finalizer execution.
52745 * - Otherwise just a normal, reachable object.
52746 *
52747 * Objects which are kept are queued to heap_allocated
52748 * tail (we're essentially filtering heap_allocated in
52749 * practice).
52750 */
52751
52752#if defined(DUK_USE_FINALIZER_SUPPORT)
52756 DUK_DD(DUK_DDPRINT("sweep; reachable, finalizable --> move to finalize_list: %p", (void *) curr));
52757
52758#if defined(DUK_USE_REFERENCE_COUNTING)
52760 curr); /* Bump refcount so that refzero never occurs when pending a finalizer call. */
52761#endif
52763#if defined(DUK_USE_DEBUG)
52764 count_finalize++;
52765#endif
52766 } else
52767#endif /* DUK_USE_FINALIZER_SUPPORT */
52768 {
52772
52773 if (flags & DUK_MS_FLAG_POSTPONE_RESCUE) {
52774 DUK_DD(DUK_DDPRINT("sweep; reachable, finalized, but postponing rescue decisions "
52775 "--> keep object (with FINALIZED set): %!iO",
52776 curr));
52777 count_keep++;
52778 } else {
52779 DUK_DD(DUK_DDPRINT("sweep; reachable, finalized --> rescued after finalization: %p",
52780 (void *) curr));
52781#if defined(DUK_USE_FINALIZER_SUPPORT)
52783#endif
52784#if defined(DUK_USE_DEBUG)
52785 count_rescue++;
52786#endif
52787 }
52788 } else {
52789 DUK_DD(DUK_DDPRINT("sweep; reachable --> keep: %!iO", curr));
52790 count_keep++;
52791 }
52792
52793 if (prev != NULL) {
52794 DUK_ASSERT(heap->heap_allocated != NULL);
52795 DUK_HEAPHDR_SET_NEXT(heap, prev, curr);
52796 } else {
52797 DUK_ASSERT(heap->heap_allocated == NULL);
52798 heap->heap_allocated = curr;
52799 }
52800#if defined(DUK_USE_DOUBLE_LINKED_HEAP)
52801 DUK_HEAPHDR_SET_PREV(heap, curr, prev);
52802#endif
52803 DUK_HEAPHDR_ASSERT_LINKS(heap, prev);
52804 DUK_HEAPHDR_ASSERT_LINKS(heap, curr);
52805 prev = curr;
52806 }
52807
52808 /*
52809 * Shrink check for value stacks here. We're inside
52810 * ms_prevent_count protection which prevents recursive
52811 * mark-and-sweep and refzero finalizers, so there are
52812 * no side effects that would affect the heap lists.
52813 */
52815 duk_hthread *thr_curr = (duk_hthread *) curr;
52816 DUK_DD(DUK_DDPRINT("value stack shrink check for thread: %!O", curr));
52817 duk_valstack_shrink_check_nothrow(thr_curr, flags & DUK_MS_FLAG_EMERGENCY /*snug*/);
52818 }
52819
52821 /* Keep FINALIZED if set, used if rescue decisions are postponed. */
52822 /* Keep FINALIZABLE for objects on finalize_list. */
52824 } else {
52825 /*
52826 * Unreachable object:
52827 * - If FINALIZED, object was finalized but not
52828 * rescued. This doesn't affect freeing.
52829 * - Otherwise normal unreachable object.
52830 *
52831 * There's no guard preventing a FINALIZED object
52832 * from being freed while finalizers execute: the
52833 * artificial finalize_list reachability roots can't
52834 * cause an incorrect free decision (but can cause
52835 * an incorrect rescue decision).
52836 */
52837
52838#if defined(DUK_USE_REFERENCE_COUNTING)
52839 /* Non-zero refcounts should not happen because we refcount
52840 * finalize all unreachable objects which should cancel out
52841 * refcounts (even for cycles).
52842 */
52844#endif
52846
52847#if defined(DUK_USE_DEBUG)
52848 if (DUK_HEAPHDR_HAS_FINALIZED(curr)) {
52849 DUK_DD(DUK_DDPRINT("sweep; unreachable, finalized --> finalized object not rescued: %p",
52850 (void *) curr));
52851 } else {
52852 DUK_DD(DUK_DDPRINT("sweep; not reachable --> free: %p", (void *) curr));
52853 }
52854
52855#endif
52856
52857 /* Note: object cannot be a finalizable unreachable object, as
52858 * they have been marked temporarily reachable for this round,
52859 * and are handled above.
52860 */
52861
52862#if defined(DUK_USE_DEBUG)
52863 count_free++;
52864#endif
52865
52866 /* Weak refs should be handled here, but no weak refs for
52867 * any non-string objects exist right now.
52868 */
52869
52870 /* Free object and all auxiliary (non-heap) allocs. */
52871 duk_heap_free_heaphdr_raw(heap, curr);
52872 }
52873
52874 curr = next;
52875 }
52876
52877 if (prev != NULL) {
52878 DUK_HEAPHDR_SET_NEXT(heap, prev, NULL);
52879 }
52880 DUK_HEAPHDR_ASSERT_LINKS(heap, prev);
52881
52882#if defined(DUK_USE_DEBUG)
52883 DUK_D(DUK_DPRINT("mark-and-sweep sweep objects (non-string): %ld freed, %ld kept, %ld rescued, %ld queued for finalization",
52884 (long) count_free,
52885 (long) count_keep,
52886 (long) count_rescue,
52887 (long) count_finalize));
52888#endif
52889 *out_count_keep = count_keep;
52890}
52891
52892/*
52893 * Litcache helpers.
52894 */
52895
52896#if defined(DUK_USE_LITCACHE_SIZE)
52898 duk_uint_t i;
52900
52901 e = heap->litcache;
52902 for (i = 0; i < DUK_USE_LITCACHE_SIZE; i++) {
52903 e->addr = NULL;
52904 /* e->h does not need to be invalidated: when e->addr is
52905 * NULL, e->h is considered garbage.
52907 e++;
52908 }
52909}
52910#endif /* DUK_USE_LITCACHE_SIZE */
52911
52912/*
52913 * Object compaction.
52914 *
52915 * Compaction is assumed to never throw an error.
52916 */
52917
52919 duk_hobject *obj;
52920 /* XXX: for threads, compact stacks? */
52921
52922 DUK_UNREF(udata);
52923 obj = duk_known_hobject(thr, -1);
52925 return 0;
52926}
52927
52928#if defined(DUK_USE_DEBUG)
52930 duk_hthread *thr,
52931 duk_heaphdr *start,
52932 duk_size_t *p_count_check,
52933 duk_size_t *p_count_compact,
52934 duk_size_t *p_count_bytes_saved) {
52935#else
52937#endif
52938 duk_heaphdr *curr;
52939#if defined(DUK_USE_DEBUG)
52940 duk_size_t old_size, new_size;
52941#endif
52942 duk_hobject *obj;
52943
52944 DUK_UNREF(heap);
52945
52946 curr = start;
52947 while (curr) {
52948 DUK_DDD(DUK_DDDPRINT("mark-and-sweep compact: %p", (void *) curr));
52949
52951 goto next;
52952 }
52953 obj = (duk_hobject *) curr;
52954
52955#if defined(DUK_USE_DEBUG)
52956 old_size =
52958#endif
52959
52960 DUK_DD(DUK_DDPRINT("compact object: %p", (void *) obj));
52961 duk_push_hobject(thr, obj);
52962 /* XXX: disable error handlers for duration of compaction? */
52964
52965#if defined(DUK_USE_DEBUG)
52966 new_size =
52968#endif
52969
52970#if defined(DUK_USE_DEBUG)
52971 (*p_count_compact)++;
52972 (*p_count_bytes_saved) += (duk_size_t) (old_size - new_size);
52973#endif
52974
52975 next:
52976 curr = DUK_HEAPHDR_GET_NEXT(heap, curr);
52977#if defined(DUK_USE_DEBUG)
52978 (*p_count_check)++;
52979#endif
52980 }
52981}
52982
52984 /* XXX: which lists should participate? to be finalized? */
52985#if defined(DUK_USE_DEBUG)
52986 duk_size_t count_check = 0;
52987 duk_size_t count_compact = 0;
52988 duk_size_t count_bytes_saved = 0;
52989#endif
52990
52991 DUK_DD(DUK_DDPRINT("duk__compact_objects: %p", (void *) heap));
52992
52993 DUK_ASSERT(heap->heap_thread != NULL);
52994
52995#if defined(DUK_USE_DEBUG)
52996 duk__compact_object_list(heap, heap->heap_thread, heap->heap_allocated, &count_check, &count_compact, &count_bytes_saved);
52997#if defined(DUK_USE_FINALIZER_SUPPORT)
52998 duk__compact_object_list(heap, heap->heap_thread, heap->finalize_list, &count_check, &count_compact, &count_bytes_saved);
52999#endif
53000#else
53002#if defined(DUK_USE_FINALIZER_SUPPORT)
53004#endif
53005#endif
53006#if defined(DUK_USE_REFERENCE_COUNTING)
53007 DUK_ASSERT(heap->refzero_list == NULL); /* Always handled to completion inline in DECREF. */
53008#endif
53009
53010#if defined(DUK_USE_DEBUG)
53011 DUK_D(DUK_DPRINT("mark-and-sweep compact objects: %ld checked, %ld compaction attempts, %ld bytes saved by compaction",
53012 (long) count_check,
53013 (long) count_compact,
53014 (long) count_bytes_saved));
53015#endif
53016}
53017
53018/*
53019 * Assertion helpers.
53020 */
53021
53022#if defined(DUK_USE_ASSERTIONS)
53023typedef void (*duk__gc_heaphdr_assert)(duk_heap *heap, duk_heaphdr *h);
53024typedef void (*duk__gc_hstring_assert)(duk_heap *heap, duk_hstring *h);
53025
53026DUK_LOCAL void duk__assert_walk_list(duk_heap *heap, duk_heaphdr *start, duk__gc_heaphdr_assert func) {
53027 duk_heaphdr *curr;
53028 for (curr = start; curr != NULL; curr = DUK_HEAPHDR_GET_NEXT(heap, curr)) {
53029 func(heap, curr);
53030 }
53031}
53032
53033DUK_LOCAL void duk__assert_walk_strtable(duk_heap *heap, duk__gc_hstring_assert func) {
53034 duk_uint32_t i;
53035
53036 for (i = 0; i < heap->st_size; i++) {
53037 duk_hstring *h;
53038
53039#if defined(DUK_USE_STRTAB_PTRCOMP)
53040 h = DUK_USE_HEAPPTR_DEC16(heap->heap_udata, heap->strtable16[i]);
53041#else
53042 h = heap->strtable[i];
53043#endif
53044 while (h != NULL) {
53045 func(heap, h);
53046 h = h->hdr.h_next;
53047 }
53048 }
53049}
53050
53051DUK_LOCAL void duk__assert_heaphdr_flags_cb(duk_heap *heap, duk_heaphdr *h) {
53052 DUK_UNREF(heap);
53056 /* may have FINALIZED */
53057}
53058DUK_LOCAL void duk__assert_heaphdr_flags(duk_heap *heap) {
53059 duk__assert_walk_list(heap, heap->heap_allocated, duk__assert_heaphdr_flags_cb);
53060#if defined(DUK_USE_REFERENCE_COUNTING)
53061 DUK_ASSERT(heap->refzero_list == NULL); /* Always handled to completion inline in DECREF. */
53062#endif
53063 /* XXX: Assertions for finalize_list? */
53064}
53065
53066DUK_LOCAL void duk__assert_validity_cb1(duk_heap *heap, duk_heaphdr *h) {
53067 DUK_UNREF(heap);
53069 duk_heaphdr_assert_valid_subclassed(h);
53070}
53071DUK_LOCAL void duk__assert_validity_cb2(duk_heap *heap, duk_hstring *h) {
53072 DUK_UNREF(heap);
53074 duk_heaphdr_assert_valid_subclassed((duk_heaphdr *) h);
53075}
53076DUK_LOCAL void duk__assert_validity(duk_heap *heap) {
53077 duk__assert_walk_list(heap, heap->heap_allocated, duk__assert_validity_cb1);
53078#if defined(DUK_USE_FINALIZER_SUPPORT)
53079 duk__assert_walk_list(heap, heap->finalize_list, duk__assert_validity_cb1);
53080#endif
53081#if defined(DUK_USE_REFERENCE_COUNTING)
53082 duk__assert_walk_list(heap, heap->refzero_list, duk__assert_validity_cb1);
53083#endif
53084 duk__assert_walk_strtable(heap, duk__assert_validity_cb2);
53085}
53086
53087#if defined(DUK_USE_REFERENCE_COUNTING)
53088DUK_LOCAL void duk__assert_valid_refcounts_cb(duk_heap *heap, duk_heaphdr *h) {
53089 /* Cannot really assert much w.r.t. refcounts now. */
53090
53091 DUK_UNREF(heap);
53093 /* An object may be in heap_allocated list with a zero
53094 * refcount if it has just been finalized and is waiting
53095 * to be collected by the next cycle.
53096 * (This doesn't currently happen however.)
53097 */
53098 } else if (DUK_HEAPHDR_GET_REFCOUNT(h) == 0) {
53099 /* An object may be in heap_allocated list with a zero
53100 * refcount also if it is a temporary object created
53101 * during debugger paused state. It will get collected
53102 * by mark-and-sweep based on its reachability status
53103 * (presumably not reachable because refcount is 0).
53104 */
53105 }
53106 DUK_ASSERT_DISABLE(DUK_HEAPHDR_GET_REFCOUNT(h) >= 0); /* Unsigned. */
53107}
53108DUK_LOCAL void duk__assert_valid_refcounts(duk_heap *heap) {
53109 duk__assert_walk_list(heap, heap->heap_allocated, duk__assert_valid_refcounts_cb);
53110}
53111
53112DUK_LOCAL void duk__clear_assert_refcounts_cb1(duk_heap *heap, duk_heaphdr *h) {
53113 DUK_UNREF(heap);
53114 h->h_assert_refcount = 0;
53115}
53116DUK_LOCAL void duk__clear_assert_refcounts_cb2(duk_heap *heap, duk_hstring *h) {
53117 DUK_UNREF(heap);
53118 ((duk_heaphdr *) h)->h_assert_refcount = 0;
53119}
53120DUK_LOCAL void duk__clear_assert_refcounts(duk_heap *heap) {
53121 duk__assert_walk_list(heap, heap->heap_allocated, duk__clear_assert_refcounts_cb1);
53122#if defined(DUK_USE_FINALIZER_SUPPORT)
53123 duk__assert_walk_list(heap, heap->finalize_list, duk__clear_assert_refcounts_cb1);
53124#endif
53125#if defined(DUK_USE_REFERENCE_COUNTING)
53126 duk__assert_walk_list(heap, heap->refzero_list, duk__clear_assert_refcounts_cb1);
53127#endif
53128 duk__assert_walk_strtable(heap, duk__clear_assert_refcounts_cb2);
53129}
53130
53131DUK_LOCAL void duk__check_refcount_heaphdr(duk_heaphdr *hdr) {
53132 duk_bool_t count_ok;
53133 duk_size_t expect_refc;
53134
53135 /* The refcount check only makes sense for reachable objects on
53136 * heap_allocated or string table, after the sweep phase. Prior to
53137 * sweep phase refcounts will include references that are not visible
53138 * via reachability roots.
53139 *
53140 * Because we're called after the sweep phase, all heap objects on
53141 * heap_allocated are reachable. REACHABLE flags have already been
53142 * cleared so we can't check them.
53143 */
53144
53145 /* ROM objects have intentionally incorrect refcount (1), but we won't
53146 * check them.
53147 */
53149
53150 expect_refc = hdr->h_assert_refcount;
53152 expect_refc++;
53153 }
53154 count_ok = ((duk_size_t) DUK_HEAPHDR_GET_REFCOUNT(hdr) == expect_refc);
53155 if (!count_ok) {
53156 DUK_D(DUK_DPRINT("refcount mismatch for: %p: header=%ld counted=%ld --> %!iO",
53157 (void *) hdr,
53158 (long) DUK_HEAPHDR_GET_REFCOUNT(hdr),
53159 (long) hdr->h_assert_refcount,
53160 hdr));
53161 DUK_ASSERT(0);
53162 }
53163}
53164
53165DUK_LOCAL void duk__check_assert_refcounts_cb1(duk_heap *heap, duk_heaphdr *h) {
53166 DUK_UNREF(heap);
53167 duk__check_refcount_heaphdr(h);
53168}
53169DUK_LOCAL void duk__check_assert_refcounts_cb2(duk_heap *heap, duk_hstring *h) {
53170 DUK_UNREF(heap);
53171 duk__check_refcount_heaphdr((duk_heaphdr *) h);
53172}
53173DUK_LOCAL void duk__check_assert_refcounts(duk_heap *heap) {
53174 duk__assert_walk_list(heap, heap->heap_allocated, duk__check_assert_refcounts_cb1);
53175#if defined(DUK_USE_FINALIZER_SUPPORT)
53176 duk__assert_walk_list(heap, heap->finalize_list, duk__check_assert_refcounts_cb1);
53177#endif
53178 /* XXX: Assert anything for refzero_list? */
53179 duk__assert_walk_strtable(heap, duk__check_assert_refcounts_cb2);
53180}
53181#endif /* DUK_USE_REFERENCE_COUNTING */
53182
53183#if defined(DUK_USE_LITCACHE_SIZE)
53184DUK_LOCAL void duk__assert_litcache_nulls(duk_heap *heap) {
53185 duk_uint_t i;
53187
53188 e = heap->litcache;
53189 for (i = 0; i < DUK_USE_LITCACHE_SIZE; i++) {
53190 /* Entry addresses were NULLed before mark-and-sweep, check
53191 * that they're still NULL afterwards to ensure no pointers
53192 * were recorded through any side effects.
53193 */
53194 DUK_ASSERT(e->addr == NULL);
53195 }
53196}
53197#endif /* DUK_USE_LITCACHE_SIZE */
53198#endif /* DUK_USE_ASSERTIONS */
53199
53200/*
53201 * Stats dump.
53202 */
53203
53204#if defined(DUK_USE_DEBUG)
53205DUK_LOCAL void duk__dump_stats(duk_heap *heap) {
53206 DUK_D(DUK_DPRINT("stats executor: opcodes=%ld, interrupt=%ld, throw=%ld",
53207 (long) heap->stats_exec_opcodes,
53208 (long) heap->stats_exec_interrupt,
53209 (long) heap->stats_exec_throw));
53210 DUK_D(DUK_DPRINT("stats call: all=%ld, tailcall=%ld, ecmatoecma=%ld",
53211 (long) heap->stats_call_all,
53212 (long) heap->stats_call_tailcall,
53213 (long) heap->stats_call_ecmatoecma));
53214 DUK_D(DUK_DPRINT("stats safecall: all=%ld, nothrow=%ld, throw=%ld",
53215 (long) heap->stats_safecall_all,
53216 (long) heap->stats_safecall_nothrow,
53217 (long) heap->stats_safecall_throw));
53218 DUK_D(DUK_DPRINT("stats mark-and-sweep: try_count=%ld, skip_count=%ld, emergency_count=%ld",
53219 (long) heap->stats_ms_try_count,
53220 (long) heap->stats_ms_skip_count,
53221 (long) heap->stats_ms_emergency_count));
53222 DUK_D(DUK_DPRINT("stats stringtable: intern_hit=%ld, intern_miss=%ld, "
53223 "resize_check=%ld, resize_grow=%ld, resize_shrink=%ld, "
53224 "litcache_hit=%ld, litcache_miss=%ld, litcache_pin=%ld",
53225 (long) heap->stats_strtab_intern_hit,
53226 (long) heap->stats_strtab_intern_miss,
53227 (long) heap->stats_strtab_resize_check,
53228 (long) heap->stats_strtab_resize_grow,
53229 (long) heap->stats_strtab_resize_shrink,
53230 (long) heap->stats_strtab_litcache_hit,
53231 (long) heap->stats_strtab_litcache_miss,
53232 (long) heap->stats_strtab_litcache_pin));
53233 DUK_D(DUK_DPRINT("stats object: realloc_props=%ld, abandon_array=%ld",
53234 (long) heap->stats_object_realloc_props,
53235 (long) heap->stats_object_abandon_array));
53236 DUK_D(DUK_DPRINT("stats getownpropdesc: count=%ld, hit=%ld, miss=%ld",
53237 (long) heap->stats_getownpropdesc_count,
53238 (long) heap->stats_getownpropdesc_hit,
53239 (long) heap->stats_getownpropdesc_miss));
53240 DUK_D(DUK_DPRINT("stats getpropdesc: count=%ld, hit=%ld, miss=%ld",
53241 (long) heap->stats_getpropdesc_count,
53242 (long) heap->stats_getpropdesc_hit,
53243 (long) heap->stats_getpropdesc_miss));
53244 DUK_D(DUK_DPRINT("stats getprop: all=%ld, arrayidx=%ld, bufobjidx=%ld, "
53245 "bufferidx=%ld, bufferlen=%ld, stringidx=%ld, stringlen=%ld, "
53246 "proxy=%ld, arguments=%ld",
53247 (long) heap->stats_getprop_all,
53248 (long) heap->stats_getprop_arrayidx,
53249 (long) heap->stats_getprop_bufobjidx,
53250 (long) heap->stats_getprop_bufferidx,
53251 (long) heap->stats_getprop_bufferlen,
53252 (long) heap->stats_getprop_stringidx,
53253 (long) heap->stats_getprop_stringlen,
53254 (long) heap->stats_getprop_proxy,
53255 (long) heap->stats_getprop_arguments));
53256 DUK_D(DUK_DPRINT("stats putprop: all=%ld, arrayidx=%ld, bufobjidx=%ld, "
53257 "bufferidx=%ld, proxy=%ld",
53258 (long) heap->stats_putprop_all,
53259 (long) heap->stats_putprop_arrayidx,
53260 (long) heap->stats_putprop_bufobjidx,
53261 (long) heap->stats_putprop_bufferidx,
53262 (long) heap->stats_putprop_proxy));
53263 DUK_D(DUK_DPRINT("stats getvar: all=%ld", (long) heap->stats_getvar_all));
53264 DUK_D(DUK_DPRINT("stats putvar: all=%ld", (long) heap->stats_putvar_all));
53265 DUK_D(DUK_DPRINT("stats envrec: delayedcreate=%ld, create=%ld, newenv=%ld, oldenv=%ld, pushclosure=%ld",
53266 (long) heap->stats_envrec_delayedcreate,
53267 (long) heap->stats_envrec_create,
53268 (long) heap->stats_envrec_newenv,
53269 (long) heap->stats_envrec_oldenv,
53270 (long) heap->stats_envrec_pushclosure));
53271}
53272#endif /* DUK_USE_DEBUG */
53273
53274/*
53275 * Main mark-and-sweep function.
53276 *
53277 * 'flags' represents the features requested by the caller. The current
53278 * heap->ms_base_flags is ORed automatically into the flags; the base flags
53279 * mask typically prevents certain mark-and-sweep operation to avoid trouble.
53280 */
53281
53283 duk_size_t count_keep_obj;
53284 duk_size_t count_keep_str;
53285#if defined(DUK_USE_VOLUNTARY_GC)
53286 duk_size_t tmp;
53287#endif
53288 duk_bool_t entry_creating_error;
53289
53290 DUK_STATS_INC(heap, stats_ms_try_count);
53291#if defined(DUK_USE_DEBUG)
53292 if (flags & DUK_MS_FLAG_EMERGENCY) {
53293 DUK_STATS_INC(heap, stats_ms_emergency_count);
53294 }
53295#endif
53296
53297 /* If debugger is paused, garbage collection is disabled by default.
53298 * This is achieved by bumping ms_prevent_count when becoming paused.
53299 */
53301
53302 /* Prevention/recursion check as soon as possible because we may
53303 * be called a number of times when voluntary mark-and-sweep is
53304 * pending.
53305 */
53306 if (heap->ms_prevent_count != 0) {
53307 DUK_DD(DUK_DDPRINT("reject recursive mark-and-sweep"));
53308 DUK_STATS_INC(heap, stats_ms_skip_count);
53309 return;
53310 }
53311 DUK_ASSERT(heap->ms_running == 0); /* ms_prevent_count is bumped when ms_running is set */
53312
53313 /* Heap_thread is used during mark-and-sweep for refcount finalization
53314 * (it's also used for finalizer execution once mark-and-sweep is
53315 * complete). Heap allocation code ensures heap_thread is set and
53316 * properly initialized before setting ms_prevent_count to 0.
53317 */
53318 DUK_ASSERT(heap->heap_thread != NULL);
53319 DUK_ASSERT(heap->heap_thread->valstack != NULL);
53320
53321 DUK_D(DUK_DPRINT("garbage collect (mark-and-sweep) starting, requested flags: 0x%08lx, effective flags: 0x%08lx",
53322 (unsigned long) flags,
53323 (unsigned long) (flags | heap->ms_base_flags)));
53324
53325 flags |= heap->ms_base_flags;
53326#if defined(DUK_USE_FINALIZER_SUPPORT)
53327 if (heap->finalize_list != NULL) {
53329 }
53330#endif
53331
53332 /*
53333 * Assertions before
53334 */
53335
53336#if defined(DUK_USE_ASSERTIONS)
53337 DUK_ASSERT(heap->ms_prevent_count == 0);
53338 DUK_ASSERT(heap->ms_running == 0);
53341 DUK_ASSERT(heap->ms_recursion_depth == 0);
53342 duk__assert_heaphdr_flags(heap);
53343 duk__assert_validity(heap);
53344#if defined(DUK_USE_REFERENCE_COUNTING)
53345 /* Note: heap->refzero_free_running may be true; a refcount
53346 * finalizer may trigger a mark-and-sweep.
53347 */
53348 duk__assert_valid_refcounts(heap);
53349#endif /* DUK_USE_REFERENCE_COUNTING */
53350#endif /* DUK_USE_ASSERTIONS */
53351
53352 /*
53353 * Begin
53354 */
53355
53356 DUK_ASSERT(heap->ms_prevent_count == 0);
53357 DUK_ASSERT(heap->ms_running == 0);
53358 heap->ms_prevent_count = 1;
53359 heap->ms_running = 1;
53360 entry_creating_error = heap->creating_error;
53361 heap->creating_error = 0;
53362
53363 /*
53364 * Free activation/catcher freelists on every mark-and-sweep for now.
53365 * This is an initial rough draft; ideally we'd keep count of the
53366 * freelist size and free only excess entries.
53367 */
53368
53369 DUK_D(DUK_DPRINT("freeing temporary freelists"));
53371
53372 /*
53373 * Mark roots, hoping that recursion limit is not normally hit.
53374 * If recursion limit is hit, run additional reachability rounds
53375 * starting from "temproots" until marking is complete.
53376 *
53377 * Marking happens in two phases: first we mark actual reachability
53378 * roots (and run "temproots" to complete the process). Then we
53379 * check which objects are unreachable and are finalizable; such
53380 * objects are marked as FINALIZABLE and marked as reachability
53381 * (and "temproots" is run again to complete the process).
53382 *
53383 * The heap finalize_list must also be marked as a reachability root.
53384 * There may be objects on the list from a previous round if the
53385 * previous run had finalizer skip flag.
53386 */
53387
53388#if defined(DUK_USE_ASSERTIONS) && defined(DUK_USE_REFERENCE_COUNTING)
53389 duk__clear_assert_refcounts(heap);
53390#endif
53391#if defined(DUK_USE_LITCACHE_SIZE)
53392 duk__wipe_litcache(heap);
53393#endif
53394 duk__mark_roots_heap(heap); /* Mark main reachability roots. */
53395#if defined(DUK_USE_REFERENCE_COUNTING)
53396 DUK_ASSERT(heap->refzero_list == NULL); /* Always handled to completion inline in DECREF. */
53397#endif
53398 duk__mark_temproots_by_heap_scan(heap); /* Temproots. */
53399
53400#if defined(DUK_USE_FINALIZER_SUPPORT)
53401 duk__mark_finalizable(heap); /* Mark finalizable as reachability roots. */
53402 duk__mark_finalize_list(heap); /* Mark finalizer work list as reachability roots. */
53403#endif
53404 duk__mark_temproots_by_heap_scan(heap); /* Temproots. */
53405
53406 /*
53407 * Sweep garbage and remove marking flags, and move objects with
53408 * finalizers to the finalizer work list.
53409 *
53410 * Objects to be swept need to get their refcounts finalized before
53411 * they are swept. In other words, their target object refcounts
53412 * need to be decreased. This has to be done before freeing any
53413 * objects to avoid decref'ing dangling pointers (which may happen
53414 * even without bugs, e.g. with reference loops)
53415 *
53416 * Because strings don't point to other heap objects, similar
53417 * finalization is not necessary for strings.
53418 */
53419
53420 /* XXX: more emergency behavior, e.g. find smaller hash sizes etc */
53421
53422#if defined(DUK_USE_REFERENCE_COUNTING)
53424#endif
53425 duk__sweep_heap(heap, flags, &count_keep_obj);
53426 duk__sweep_stringtable(heap, &count_keep_str);
53427#if defined(DUK_USE_ASSERTIONS) && defined(DUK_USE_REFERENCE_COUNTING)
53428 duk__check_assert_refcounts(heap);
53429#endif
53430#if defined(DUK_USE_REFERENCE_COUNTING)
53431 DUK_ASSERT(heap->refzero_list == NULL); /* Always handled to completion inline in DECREF. */
53432#endif
53433#if defined(DUK_USE_FINALIZER_SUPPORT)
53435#endif
53436
53437 /*
53438 * Object compaction (emergency only).
53439 *
53440 * Object compaction is a separate step after sweeping, as there is
53441 * more free memory for it to work with. Also, currently compaction
53442 * may insert new objects into the heap allocated list and the string
53443 * table which we don't want to do during a sweep (the reachability
53444 * flags of such objects would be incorrect). The objects inserted
53445 * are currently:
53446 *
53447 * - a temporary duk_hbuffer for a new properties allocation
53448 * - if array part is abandoned, string keys are interned
53449 *
53450 * The object insertions go to the front of the list, so they do not
53451 * cause an infinite loop (they are not compacted).
53452 *
53453 * At present compaction is not allowed when mark-and-sweep runs
53454 * during error handling because it involves a duk_safe_call()
53455 * interfering with error state.
53456 */
53457
53458 if ((flags & DUK_MS_FLAG_EMERGENCY) && !(flags & DUK_MS_FLAG_NO_OBJECT_COMPACTION)) {
53459 if (heap->lj.type != DUK_LJ_TYPE_UNKNOWN) {
53460 DUK_D(DUK_DPRINT("lj.type (%ld) not DUK_LJ_TYPE_UNKNOWN, skip object compaction", (long) heap->lj.type));
53461 } else {
53462 DUK_D(DUK_DPRINT("object compaction"));
53464 }
53465 }
53466
53467 /*
53468 * String table resize check.
53469 *
53470 * This is mainly useful in emergency GC: if the string table load
53471 * factor is really low for some reason, we can shrink the string
53472 * table to a smaller size and free some memory in the process.
53473 * Only execute in emergency GC. String table has internal flags
53474 * to protect against recursive resizing if this mark-and-sweep pass
53475 * was triggered by a string table resize.
53476 */
53477
53478 if (flags & DUK_MS_FLAG_EMERGENCY) {
53479 DUK_D(DUK_DPRINT("stringtable resize check in emergency gc"));
53481 }
53482
53483 /*
53484 * Finish
53485 */
53486
53487 DUK_ASSERT(heap->ms_prevent_count == 1);
53488 DUK_ASSERT(heap->ms_running == 1);
53489 heap->ms_prevent_count = 0;
53490 heap->ms_running = 0;
53491 heap->creating_error = entry_creating_error; /* for nested error handling, see GH-2278 */
53492
53493 /*
53494 * Assertions after
53495 */
53496
53497#if defined(DUK_USE_ASSERTIONS)
53498 DUK_ASSERT(heap->ms_prevent_count == 0);
53500 DUK_ASSERT(heap->ms_recursion_depth == 0);
53501 duk__assert_heaphdr_flags(heap);
53502 duk__assert_validity(heap);
53503#if defined(DUK_USE_REFERENCE_COUNTING)
53504 /* Note: heap->refzero_free_running may be true; a refcount
53505 * finalizer may trigger a mark-and-sweep.
53506 */
53507 duk__assert_valid_refcounts(heap);
53508#endif /* DUK_USE_REFERENCE_COUNTING */
53509#if defined(DUK_USE_LITCACHE_SIZE)
53510 duk__assert_litcache_nulls(heap);
53511#endif /* DUK_USE_LITCACHE_SIZE */
53512#endif /* DUK_USE_ASSERTIONS */
53513
53514 /*
53515 * Reset trigger counter
53516 */
53517
53518#if defined(DUK_USE_VOLUNTARY_GC)
53519 tmp = (count_keep_obj + count_keep_str) / 256;
53521 DUK_D(DUK_DPRINT("garbage collect (mark-and-sweep) finished: %ld objects kept, %ld strings kept, trigger reset to %ld",
53522 (long) count_keep_obj,
53523 (long) count_keep_str,
53524 (long) heap->ms_trigger_counter));
53525#else
53526 DUK_D(DUK_DPRINT("garbage collect (mark-and-sweep) finished: %ld objects kept, %ld strings kept, no voluntary trigger",
53527 (long) count_keep_obj,
53528 (long) count_keep_str));
53529#endif
53530
53531 /*
53532 * Stats dump
53533 */
53534
53535#if defined(DUK_USE_DEBUG)
53536 duk__dump_stats(heap);
53537#endif
53538
53539 /*
53540 * Finalize objects in the finalization work list. Finalized
53541 * objects are queued back to heap_allocated with FINALIZED set.
53542 *
53543 * Since finalizers may cause arbitrary side effects, they are
53544 * prevented e.g. during string table and object property allocation
53545 * resizing using heap->pf_prevent_count. In this case the objects
53546 * remain in the finalization work list after mark-and-sweep exits
53547 * and they may be finalized on the next pass or any DECREF checking
53548 * for finalize_list.
53549 *
53550 * As of Duktape 2.1 finalization happens outside mark-and-sweep
53551 * protection. Mark-and-sweep is allowed while the finalize_list
53552 * is being processed, but no rescue decisions are done while the
53553 * process is on-going. This avoids incorrect rescue decisions
53554 * if an object is considered reachable (and thus rescued) because
53555 * of a reference via finalize_list (which is considered a reachability
53556 * root). When finalize_list is being processed, reachable objects
53557 * with FINALIZED set will just keep their FINALIZED flag for later
53558 * mark-and-sweep processing.
53559 *
53560 * This could also be handled (a bit better) by having a more refined
53561 * notion of reachability for rescue/free decisions.
53562 *
53563 * XXX: avoid finalizer execution when doing emergency GC?
53564 */
53565
53566#if defined(DUK_USE_FINALIZER_SUPPORT)
53567 /* Attempt to process finalize_list, pf_prevent_count check
53568 * is inside the target.
53569 */
53571#endif /* DUK_USE_FINALIZER_SUPPORT */
53573/*
53574 * Memory allocation handling.
53575 */
53576
53577/* #include duk_internal.h -> already included */
53578
53579/*
53580 * Allocate memory with garbage collection.
53581 */
53582
53583/* Slow path: voluntary GC triggered, first alloc attempt failed, or zero size. */
53585 void *res;
53587
53588 DUK_ASSERT(heap != NULL);
53589 DUK_ASSERT(heap->alloc_func != NULL);
53590 DUK_ASSERT_DISABLE(size >= 0);
53591
53592 if (size == 0) {
53593 DUK_D(DUK_DPRINT("zero size alloc in slow path, return NULL"));
53594 return NULL;
53595 }
53596
53597 DUK_D(DUK_DPRINT("first alloc attempt failed or voluntary GC limit reached, attempt to gc and retry"));
53598
53599#if 0
53600 /*
53601 * If GC is already running there is no point in attempting a GC
53602 * because it will be skipped. This could be checked for explicitly,
53603 * but it isn't actually needed: the loop below will eventually
53604 * fail resulting in a NULL.
53605 */
53606
53607 if (heap->ms_prevent_count != 0) {
53608 DUK_D(DUK_DPRINT("duk_heap_mem_alloc() failed, gc in progress (gc skipped), alloc size %ld", (long) size));
53609 return NULL;
53610 }
53611#endif
53612
53613 /*
53614 * Retry with several GC attempts. Initial attempts are made without
53615 * emergency mode; later attempts use emergency mode which minimizes
53616 * memory allocations forcibly.
53617 */
53618
53619 for (i = 0; i < DUK_HEAP_ALLOC_FAIL_MARKANDSWEEP_LIMIT; i++) {
53620 duk_small_uint_t flags;
53621
53622 flags = 0;
53624 flags |= DUK_MS_FLAG_EMERGENCY;
53625 }
53626
53627 duk_heap_mark_and_sweep(heap, flags);
53628
53629 DUK_ASSERT(size > 0);
53630 res = heap->alloc_func(heap->heap_udata, size);
53631 if (res != NULL) {
53632 DUK_D(DUK_DPRINT("duk_heap_mem_alloc() succeeded after gc (pass %ld), alloc size %ld",
53633 (long) (i + 1),
53634 (long) size));
53635 return res;
53636 }
53637 }
53638
53639 DUK_D(DUK_DPRINT("duk_heap_mem_alloc() failed even after gc, alloc size %ld", (long) size));
53640 return NULL;
53641}
53642
53644 void *res;
53645
53646 DUK_ASSERT(heap != NULL);
53647 DUK_ASSERT(heap->alloc_func != NULL);
53648 DUK_ASSERT_DISABLE(size >= 0);
53649
53650#if defined(DUK_USE_VOLUNTARY_GC)
53651 /* Voluntary periodic GC (if enabled). */
53652 if (DUK_UNLIKELY(--(heap)->ms_trigger_counter < 0)) {
53653 goto slowpath;
53654 }
53655#endif
53656
53657#if defined(DUK_USE_GC_TORTURE)
53658 /* Simulate alloc failure on every alloc, except when mark-and-sweep
53659 * is running.
53660 */
53661 if (heap->ms_prevent_count == 0) {
53662 DUK_DDD(DUK_DDDPRINT("gc torture enabled, pretend that first alloc attempt fails"));
53663 res = NULL;
53664 DUK_UNREF(res);
53665 goto slowpath;
53666 }
53667#endif
53668
53669 /* Zero-size allocation should happen very rarely (if at all), so
53670 * don't check zero size on NULL; handle it in the slow path
53671 * instead. This reduces size of inlined code.
53672 */
53673 res = heap->alloc_func(heap->heap_udata, size);
53674 if (DUK_LIKELY(res != NULL)) {
53675 return res;
53677
53678slowpath:
53679
53680 if (size == 0) {
53681 DUK_D(DUK_DPRINT("first alloc attempt returned NULL for zero size alloc, use slow path to deal with it"));
53682 } else {
53683 DUK_D(DUK_DPRINT("first alloc attempt failed, attempt to gc and retry"));
53684 }
53685 return duk__heap_mem_alloc_slowpath(heap, size);
53686}
53687
53689 void *res;
53691 DUK_ASSERT(heap != NULL);
53692 DUK_ASSERT(heap->alloc_func != NULL);
53693 DUK_ASSERT_DISABLE(size >= 0);
53694
53695 res = DUK_ALLOC(heap, size);
53696 if (DUK_LIKELY(res != NULL)) {
53697 duk_memzero(res, size);
53698 }
53699 return res;
53700}
53701
53703 void *res;
53704
53705 DUK_ASSERT(thr != NULL);
53706 DUK_ASSERT(thr->heap != NULL);
53707 DUK_ASSERT(thr->heap->alloc_func != NULL);
53709 res = duk_heap_mem_alloc(thr->heap, size);
53710 if (DUK_LIKELY(res != NULL)) {
53711 return res;
53712 } else if (size == 0) {
53713 DUK_ASSERT(res == NULL);
53714 return res;
53715 }
53717 DUK_WO_NORETURN(return NULL;);
53718}
53719
53721 void *res;
53722
53723 DUK_ASSERT(thr != NULL);
53724 DUK_ASSERT(thr->heap != NULL);
53725 DUK_ASSERT(thr->heap->alloc_func != NULL);
53726
53727 res = duk_heap_mem_alloc(thr->heap, size);
53728 if (DUK_LIKELY(res != NULL)) {
53729 duk_memzero(res, size);
53730 return res;
53731 } else if (size == 0) {
53732 DUK_ASSERT(res == NULL);
53733 return res;
53734 }
53736 DUK_WO_NORETURN(return NULL;);
53737}
53738
53739/*
53740 * Reallocate memory with garbage collection.
53741 */
53742
53743/* Slow path: voluntary GC triggered, first realloc attempt failed, or zero size. */
53745 void *res;
53747
53748 DUK_ASSERT(heap != NULL);
53749 DUK_ASSERT(heap->realloc_func != NULL);
53750 /* ptr may be NULL */
53751 DUK_ASSERT_DISABLE(newsize >= 0);
53752
53753 /* Unlike for malloc(), zero size NULL result check happens at the call site. */
53754
53755 DUK_D(DUK_DPRINT("first realloc attempt failed, attempt to gc and retry"));
53756
53757#if 0
53758 /*
53759 * Avoid a GC if GC is already running. See duk_heap_mem_alloc().
53760 */
53761
53762 if (heap->ms_prevent_count != 0) {
53763 DUK_D(DUK_DPRINT("duk_heap_mem_realloc() failed, gc in progress (gc skipped), alloc size %ld", (long) newsize));
53764 return NULL;
53765 }
53766#endif
53767
53768 /*
53769 * Retry with several GC attempts. Initial attempts are made without
53770 * emergency mode; later attempts use emergency mode which minimizes
53771 * memory allocations forcibly.
53772 */
53773
53774 for (i = 0; i < DUK_HEAP_ALLOC_FAIL_MARKANDSWEEP_LIMIT; i++) {
53775 duk_small_uint_t flags;
53776
53777 flags = 0;
53779 flags |= DUK_MS_FLAG_EMERGENCY;
53780 }
53781
53782 duk_heap_mark_and_sweep(heap, flags);
53783
53784 res = heap->realloc_func(heap->heap_udata, ptr, newsize);
53785 if (res != NULL || newsize == 0) {
53786 DUK_D(DUK_DPRINT("duk_heap_mem_realloc() succeeded after gc (pass %ld), alloc size %ld",
53787 (long) (i + 1),
53788 (long) newsize));
53789 return res;
53790 }
53791 }
53792
53793 DUK_D(DUK_DPRINT("duk_heap_mem_realloc() failed even after gc, alloc size %ld", (long) newsize));
53794 return NULL;
53795}
53796
53798 void *res;
53799
53800 DUK_ASSERT(heap != NULL);
53801 DUK_ASSERT(heap->realloc_func != NULL);
53802 /* ptr may be NULL */
53803 DUK_ASSERT_DISABLE(newsize >= 0);
53804
53805#if defined(DUK_USE_VOLUNTARY_GC)
53806 /* Voluntary periodic GC (if enabled). */
53807 if (DUK_UNLIKELY(--(heap)->ms_trigger_counter < 0)) {
53808 goto gc_retry;
53809 }
53810#endif
53811
53812#if defined(DUK_USE_GC_TORTURE)
53813 /* Simulate alloc failure on every realloc, except when mark-and-sweep
53814 * is running.
53815 */
53816 if (heap->ms_prevent_count == 0) {
53817 DUK_DDD(DUK_DDDPRINT("gc torture enabled, pretend that first realloc attempt fails"));
53818 res = NULL;
53819 DUK_UNREF(res);
53820 goto gc_retry;
53821 }
53822#endif
53823
53824 res = heap->realloc_func(heap->heap_udata, ptr, newsize);
53825 if (DUK_LIKELY(res != NULL) || newsize == 0) {
53826 if (res != NULL && newsize == 0) {
53827 DUK_DD(DUK_DDPRINT("first realloc attempt returned NULL for zero size realloc, accept and return NULL"));
53828 }
53829 return res;
53830 } else {
53831 goto gc_retry;
53832 }
53833 /* Never here. */
53835gc_retry:
53836 return duk__heap_mem_realloc_slowpath(heap, ptr, newsize);
53837}
53838
53839/*
53840 * Reallocate memory with garbage collection, using a callback to provide
53841 * the current allocated pointer. This variant is used when a mark-and-sweep
53842 * (e.g. finalizers) might change the original pointer.
53843 */
53844
53845/* Slow path: voluntary GC triggered, first realloc attempt failed, or zero size. */
53847 duk_mem_getptr cb,
53848 void *ud,
53849 duk_size_t newsize) {
53850 void *res;
53852
53853 DUK_ASSERT(heap != NULL);
53854 DUK_ASSERT(heap->realloc_func != NULL);
53855 DUK_ASSERT_DISABLE(newsize >= 0);
53856
53857 /* Unlike for malloc(), zero size NULL result check happens at the call site. */
53858
53859 DUK_D(DUK_DPRINT("first indirect realloc attempt failed, attempt to gc and retry"));
53860
53861#if 0
53862 /*
53863 * Avoid a GC if GC is already running. See duk_heap_mem_alloc().
53864 */
53865
53866 if (heap->ms_prevent_count != 0) {
53867 DUK_D(DUK_DPRINT("duk_heap_mem_realloc_indirect() failed, gc in progress (gc skipped), alloc size %ld", (long) newsize));
53868 return NULL;
53869 }
53870#endif
53871
53872 /*
53873 * Retry with several GC attempts. Initial attempts are made without
53874 * emergency mode; later attempts use emergency mode which minimizes
53875 * memory allocations forcibly.
53876 */
53877
53878 for (i = 0; i < DUK_HEAP_ALLOC_FAIL_MARKANDSWEEP_LIMIT; i++) {
53879 duk_small_uint_t flags;
53880
53881#if defined(DUK_USE_DEBUG)
53882 void *ptr_pre;
53883 void *ptr_post;
53884#endif
53885
53886#if defined(DUK_USE_DEBUG)
53887 ptr_pre = cb(heap, ud);
53888#endif
53889 flags = 0;
53891 flags |= DUK_MS_FLAG_EMERGENCY;
53892 }
53893
53894 duk_heap_mark_and_sweep(heap, flags);
53895#if defined(DUK_USE_DEBUG)
53896 ptr_post = cb(heap, ud);
53897 if (ptr_pre != ptr_post) {
53898 DUK_DD(DUK_DDPRINT("realloc base pointer changed by mark-and-sweep: %p -> %p",
53899 (void *) ptr_pre,
53900 (void *) ptr_post));
53901 }
53902#endif
53903
53904 /* Note: key issue here is to re-lookup the base pointer on every attempt.
53905 * The pointer being reallocated may change after every mark-and-sweep.
53906 */
53907
53908 res = heap->realloc_func(heap->heap_udata, cb(heap, ud), newsize);
53909 if (res != NULL || newsize == 0) {
53910 DUK_D(DUK_DPRINT("duk_heap_mem_realloc_indirect() succeeded after gc (pass %ld), alloc size %ld",
53911 (long) (i + 1),
53912 (long) newsize));
53913 return res;
53914 }
53915 }
53916
53917 DUK_D(DUK_DPRINT("duk_heap_mem_realloc_indirect() failed even after gc, alloc size %ld", (long) newsize));
53918 return NULL;
53919}
53920
53922 duk_mem_getptr cb,
53923 void *ud,
53924 duk_size_t newsize) {
53925 void *res;
53926
53927 DUK_ASSERT(heap != NULL);
53928 DUK_ASSERT(heap->realloc_func != NULL);
53929 DUK_ASSERT_DISABLE(newsize >= 0);
53930
53931#if defined(DUK_USE_VOLUNTARY_GC)
53932 /* Voluntary periodic GC (if enabled). */
53933 if (DUK_UNLIKELY(--(heap)->ms_trigger_counter < 0)) {
53934 goto gc_retry;
53935 }
53936#endif
53937
53938#if defined(DUK_USE_GC_TORTURE)
53939 /* Simulate alloc failure on every realloc, except when mark-and-sweep
53940 * is running.
53941 */
53942 if (heap->ms_prevent_count == 0) {
53943 DUK_DDD(DUK_DDDPRINT("gc torture enabled, pretend that first indirect realloc attempt fails"));
53944 res = NULL;
53945 DUK_UNREF(res);
53946 goto gc_retry;
53947 }
53948#endif
53949
53950 res = heap->realloc_func(heap->heap_udata, cb(heap, ud), newsize);
53951 if (DUK_LIKELY(res != NULL) || newsize == 0) {
53952 if (res != NULL && newsize == 0) {
53954 "first indirect realloc attempt returned NULL for zero size realloc, accept and return NULL"));
53955 }
53956 return res;
53957 } else {
53958 goto gc_retry;
53959 }
53960 /* Never here. */
53961
53962gc_retry:
53963 return duk__heap_mem_realloc_indirect_slowpath(heap, cb, ud, newsize);
53964}
53965
53966/*
53967 * Free memory
53968 */
53969
53971 DUK_ASSERT(heap != NULL);
53972 DUK_ASSERT(heap->free_func != NULL);
53973 /* ptr may be NULL */
53974
53975 /* Must behave like a no-op with NULL and any pointer returned from
53976 * malloc/realloc with zero size.
53977 */
53978 heap->free_func(heap->heap_udata, ptr);
53980 /* Never perform a GC (even voluntary) in a memory free, otherwise
53981 * all call sites doing frees would need to deal with the side effects.
53982 * No need to update voluntary GC counter either.
53983 */
53984}
53985/*
53986 * Support functions for duk_heap.
53987 */
53988
53989/* #include duk_internal.h -> already included */
53990
53993
53995
53996 root = heap->heap_allocated;
53997#if defined(DUK_USE_DOUBLE_LINKED_HEAP)
53998 if (root != NULL) {
54000 DUK_HEAPHDR_SET_PREV(heap, root, hdr);
54001 }
54002 DUK_HEAPHDR_SET_PREV(heap, hdr, NULL);
54003#endif
54004 DUK_HEAPHDR_SET_NEXT(heap, hdr, root);
54005 DUK_HEAPHDR_ASSERT_LINKS(heap, hdr);
54007 heap->heap_allocated = hdr;
54008}
54009
54010#if defined(DUK_USE_REFERENCE_COUNTING)
54012 duk_heaphdr *prev;
54013 duk_heaphdr *next;
54014
54015 /* Strings are in string table. */
54016 DUK_ASSERT(hdr != NULL);
54018
54019 /* Target 'hdr' must be in heap_allocated (not e.g. finalize_list).
54020 * If not, heap lists will become corrupted so assert early for it.
54021 */
54022#if defined(DUK_USE_ASSERTIONS)
54023 {
54024 duk_heaphdr *tmp;
54025 for (tmp = heap->heap_allocated; tmp != NULL; tmp = DUK_HEAPHDR_GET_NEXT(heap, tmp)) {
54026 if (tmp == hdr) {
54027 break;
54028 }
54029 }
54030 DUK_ASSERT(tmp == hdr);
54031 }
54032#endif
54033
54034 /* Read/write only once to minimize pointer compression calls. */
54035 prev = DUK_HEAPHDR_GET_PREV(heap, hdr);
54036 next = DUK_HEAPHDR_GET_NEXT(heap, hdr);
54037
54038 if (prev != NULL) {
54039 DUK_ASSERT(heap->heap_allocated != hdr);
54040 DUK_HEAPHDR_SET_NEXT(heap, prev, next);
54041 } else {
54043 heap->heap_allocated = next;
54044 }
54045 if (next != NULL) {
54046 DUK_HEAPHDR_SET_PREV(heap, next, prev);
54047 } else {
54048 ;
54049 }
54050}
54051#endif /* DUK_USE_REFERENCE_COUNTING */
54052
54053#if defined(DUK_USE_FINALIZER_SUPPORT)
54056
54057 root = heap->finalize_list;
54058#if defined(DUK_USE_DOUBLE_LINKED_HEAP)
54059 DUK_HEAPHDR_SET_PREV(heap, hdr, NULL);
54060 if (root != NULL) {
54062 DUK_HEAPHDR_SET_PREV(heap, root, hdr);
54063 }
54064#endif
54065 DUK_HEAPHDR_SET_NEXT(heap, hdr, root);
54066 DUK_HEAPHDR_ASSERT_LINKS(heap, hdr);
54068 heap->finalize_list = hdr;
54069}
54070#endif /* DUK_USE_FINALIZER_SUPPORT */
54071
54072#if defined(DUK_USE_FINALIZER_SUPPORT)
54074#if defined(DUK_USE_DOUBLE_LINKED_HEAP)
54075 duk_heaphdr *next;
54076 duk_heaphdr *prev;
54077
54078 next = DUK_HEAPHDR_GET_NEXT(heap, hdr);
54079 prev = DUK_HEAPHDR_GET_PREV(heap, hdr);
54080 if (next != NULL) {
54081 DUK_ASSERT(DUK_HEAPHDR_GET_PREV(heap, next) == hdr);
54082 DUK_HEAPHDR_SET_PREV(heap, next, prev);
54083 }
54084 if (prev == NULL) {
54085 DUK_ASSERT(hdr == heap->finalize_list);
54086 heap->finalize_list = next;
54087 } else {
54088 DUK_ASSERT(hdr != heap->finalize_list);
54089 DUK_HEAPHDR_SET_NEXT(heap, prev, next);
54090 }
54091#else
54092 duk_heaphdr *next;
54093 duk_heaphdr *curr;
54094
54095 /* Random removal is expensive: we need to locate the previous element
54096 * because we don't have a 'prev' pointer.
54097 */
54098 curr = heap->finalize_list;
54099 if (curr == hdr) {
54100 heap->finalize_list = DUK_HEAPHDR_GET_NEXT(heap, curr);
54101 } else {
54102 DUK_ASSERT(hdr != heap->finalize_list);
54103 for (;;) {
54104 DUK_ASSERT(curr != NULL); /* Caller responsibility. */
54105
54106 next = DUK_HEAPHDR_GET_NEXT(heap, curr);
54107 if (next == hdr) {
54108 next = DUK_HEAPHDR_GET_NEXT(heap, hdr);
54109 DUK_HEAPHDR_SET_NEXT(heap, curr, next);
54110 break;
54111 }
54112 }
54113 }
54114#endif
54115}
54116#endif /* DUK_USE_FINALIZER_SUPPORT */
54117
54118#if defined(DUK_USE_ASSERTIONS)
54119DUK_INTERNAL duk_bool_t duk_heap_in_heap_allocated(duk_heap *heap, duk_heaphdr *ptr) {
54120 duk_heaphdr *curr;
54121 DUK_ASSERT(heap != NULL);
54122
54123 for (curr = heap->heap_allocated; curr != NULL; curr = DUK_HEAPHDR_GET_NEXT(heap, curr)) {
54124 if (curr == ptr) {
54125 return 1;
54126 }
54127 }
54128 return 0;
54129}
54130#endif /* DUK_USE_ASSERTIONS */
54131
54132#if defined(DUK_USE_INTERRUPT_COUNTER)
54134 duk_hthread *curr_thr;
54135
54136 DUK_ASSERT(heap != NULL);
54137
54138 if (new_thr != NULL) {
54139 curr_thr = heap->curr_thread;
54140 if (curr_thr == NULL) {
54141 /* For initial entry use default value; zero forces an
54142 * interrupt before executing the first insturction.
54143 */
54144 DUK_DD(DUK_DDPRINT("switch thread, initial entry, init default interrupt counter"));
54145 new_thr->interrupt_counter = 0;
54146 new_thr->interrupt_init = 0;
54147 } else {
54148 /* Copy interrupt counter/init value state to new thread (if any).
54149 * It's OK for new_thr to be the same as curr_thr.
54150 */
54151#if defined(DUK_USE_DEBUG)
54152 if (new_thr != curr_thr) {
54153 DUK_DD(DUK_DDPRINT("switch thread, not initial entry, copy interrupt counter"));
54154 }
54155#endif
54156 new_thr->interrupt_counter = curr_thr->interrupt_counter;
54157 new_thr->interrupt_init = curr_thr->interrupt_init;
54158 }
54159 } else {
54160 DUK_DD(DUK_DDPRINT("switch thread, new thread is NULL, no interrupt counter changes"));
54161 }
54162
54163 heap->curr_thread = new_thr; /* may be NULL */
54164}
54165#endif /* DUK_USE_INTERRUPT_COUNTER */
54166
54167#if defined(DUK_USE_ASSERTIONS)
54168DUK_INTERNAL void duk_heap_assert_valid(duk_heap *heap) {
54169 DUK_ASSERT(heap != NULL);
54170}
54171#endif
54172/*
54173 * Reference counting implementation.
54174 *
54175 * INCREF/DECREF, finalization and freeing of objects whose refcount reaches
54176 * zero (refzero). These operations are very performance sensitive, so
54177 * various small tricks are used in an attempt to maximize speed.
54178 */
54179
54180/* #include duk_internal.h -> already included */
54181
54182#if defined(DUK_USE_REFERENCE_COUNTING)
54183
54184#if !defined(DUK_USE_DOUBLE_LINKED_HEAP)
54185#error internal error, reference counting requires a double linked heap
54186#endif
54187
54188/*
54189 * Heap object refcount finalization.
54190 *
54191 * When an object is about to be freed, all other objects it refers to must
54192 * be decref'd. Refcount finalization does NOT free the object or its inner
54193 * allocations (mark-and-sweep shares these helpers), it just manipulates
54194 * the refcounts.
54195 *
54196 * Note that any of the DECREFs may cause a refcount to drop to zero. If so,
54197 * the object won't be refzero processed inline, but will just be queued to
54198 * refzero_list and processed by an earlier caller working on refzero_list,
54199 * eliminating C recursion from even long refzero cascades. If refzero
54200 * finalization is triggered by mark-and-sweep, refzero conditions are ignored
54201 * (objects are not even queued to refzero_list) because mark-and-sweep deals
54202 * with them; refcounts are still updated so that they remain in sync with
54203 * actual references.
54204 */
54205
54207 DUK_ASSERT(count == 0 || tv != NULL);
54208
54209 while (count-- > 0) {
54210 DUK_TVAL_DECREF_NORZ(thr, tv);
54211 tv++;
54212 }
54213}
54214
54216 duk_hthread *thr;
54219 duk_propvalue *p_val;
54220 duk_tval *p_tv;
54221 duk_hstring **p_key;
54222 duk_uint8_t *p_flag;
54223 duk_hobject *h_proto;
54224
54225 DUK_ASSERT(heap != NULL);
54226 DUK_ASSERT(heap->heap_thread != NULL);
54227 DUK_ASSERT(h);
54229
54230 thr = heap->heap_thread;
54231 DUK_ASSERT(thr != NULL);
54232
54233 p_key = DUK_HOBJECT_E_GET_KEY_BASE(heap, h);
54234 p_val = DUK_HOBJECT_E_GET_VALUE_BASE(heap, h);
54235 p_flag = DUK_HOBJECT_E_GET_FLAGS_BASE(heap, h);
54236 n = DUK_HOBJECT_GET_ENEXT(h);
54237 while (n-- > 0) {
54238 duk_hstring *key;
54239
54240 key = p_key[n];
54241 if (DUK_UNLIKELY(key == NULL)) {
54242 continue;
54243 }
54244 DUK_HSTRING_DECREF_NORZ(thr, key);
54245 if (DUK_UNLIKELY(p_flag[n] & DUK_PROPDESC_FLAG_ACCESSOR)) {
54246 duk_hobject *h_getset;
54247 h_getset = p_val[n].a.get;
54248 DUK_ASSERT(h_getset == NULL || DUK_HEAPHDR_IS_OBJECT((duk_heaphdr *) h_getset));
54249 DUK_HOBJECT_DECREF_NORZ_ALLOWNULL(thr, h_getset);
54250 h_getset = p_val[n].a.set;
54251 DUK_ASSERT(h_getset == NULL || DUK_HEAPHDR_IS_OBJECT((duk_heaphdr *) h_getset));
54252 DUK_HOBJECT_DECREF_NORZ_ALLOWNULL(thr, h_getset);
54253 } else {
54254 duk_tval *tv_val;
54255 tv_val = &p_val[n].v;
54256 DUK_TVAL_DECREF_NORZ(thr, tv_val);
54257 }
54258 }
54259
54260 p_tv = DUK_HOBJECT_A_GET_BASE(heap, h);
54261 n = DUK_HOBJECT_GET_ASIZE(h);
54262 while (n-- > 0) {
54263 duk_tval *tv_val;
54264 tv_val = p_tv + n;
54265 DUK_TVAL_DECREF_NORZ(thr, tv_val);
54266 }
54267
54268 /* Hash part is a 'weak reference' and doesn't contribute to refcounts. */
54269
54270 h_proto = (duk_hobject *) DUK_HOBJECT_GET_PROTOTYPE(heap, h);
54271 DUK_ASSERT(h_proto == NULL || DUK_HEAPHDR_IS_OBJECT((duk_heaphdr *) h_proto));
54273
54274 /* XXX: Object subclass tests are quite awkward at present, ideally
54275 * we should be able to switch-case here with a dense index (subtype
54276 * number or something). For now, fast path plain objects and arrays
54277 * and bit test the rest individually.
54278 */
54279
54280 if (DUK_HOBJECT_HAS_FASTREFS(h)) {
54281 /* Plain object or array, nothing more to do. While a
54282 * duk_harray has additional fields, none of them need
54283 * DECREF updates.
54284 */
54286 return;
54287 }
54289
54290 /* Slow path: special object, start bit checks from most likely. */
54291
54292 /* XXX: reorg, more common first */
54293 if (DUK_HOBJECT_IS_COMPFUNC(h)) {
54294 duk_hcompfunc *f = (duk_hcompfunc *) h;
54295 duk_tval *tv, *tv_end;
54296 duk_hobject **funcs, **funcs_end;
54297
54299
54300 if (DUK_LIKELY(DUK_HCOMPFUNC_GET_DATA(heap, f) != NULL)) {
54301 tv = DUK_HCOMPFUNC_GET_CONSTS_BASE(heap, f);
54302 tv_end = DUK_HCOMPFUNC_GET_CONSTS_END(heap, f);
54303 while (tv < tv_end) {
54304 DUK_TVAL_DECREF_NORZ(thr, tv);
54305 tv++;
54306 }
54307
54308 funcs = DUK_HCOMPFUNC_GET_FUNCS_BASE(heap, f);
54309 funcs_end = DUK_HCOMPFUNC_GET_FUNCS_END(heap, f);
54310 while (funcs < funcs_end) {
54311 duk_hobject *h_func;
54312 h_func = *funcs;
54313 DUK_ASSERT(h_func != NULL);
54316 funcs++;
54317 }
54318 } else {
54319 /* May happen in some out-of-memory corner cases. */
54320 DUK_D(DUK_DPRINT("duk_hcompfunc 'data' is NULL, skipping decref"));
54321 }
54322
54326 } else if (DUK_HOBJECT_IS_DECENV(h)) {
54327 duk_hdecenv *e = (duk_hdecenv *) h;
54331 } else if (DUK_HOBJECT_IS_OBJENV(h)) {
54332 duk_hobjenv *e = (duk_hobjenv *) h;
54334 DUK_ASSERT(e->target != NULL); /* Required for object environments. */
54336#if defined(DUK_USE_BUFFEROBJECT_SUPPORT)
54337 } else if (DUK_HOBJECT_IS_BUFOBJ(h)) {
54338 duk_hbufobj *b = (duk_hbufobj *) h;
54342#endif /* DUK_USE_BUFFEROBJECT_SUPPORT */
54343 } else if (DUK_HOBJECT_IS_BOUNDFUNC(h)) {
54344 duk_hboundfunc *f = (duk_hboundfunc *) (void *) h;
54346 DUK_TVAL_DECREF_NORZ(thr, &f->target);
54348 duk__decref_tvals_norz(thr, f->args, f->nargs);
54349#if defined(DUK_USE_ES6_PROXY)
54350 } else if (DUK_HOBJECT_IS_PROXY(h)) {
54351 duk_hproxy *p = (duk_hproxy *) h;
54355#endif /* DUK_USE_ES6_PROXY */
54356 } else if (DUK_HOBJECT_IS_THREAD(h)) {
54357 duk_hthread *t = (duk_hthread *) h;
54358 duk_activation *act;
54359 duk_tval *tv;
54360
54362
54363 tv = t->valstack;
54364 while (tv < t->valstack_top) {
54365 DUK_TVAL_DECREF_NORZ(thr, tv);
54366 tv++;
54367 }
54368
54369 for (act = t->callstack_curr; act != NULL; act = act->parent) {
54373#if defined(DUK_USE_NONSTD_FUNC_CALLER_PROPERTY)
54374 DUK_HOBJECT_DECREF_NORZ_ALLOWNULL(thr, (duk_hobject *) act->prev_caller);
54375#endif
54376#if 0 /* nothing now */
54377 for (cat = act->cat; cat != NULL; cat = cat->parent) {
54378 }
54379#endif
54380 }
54381
54382 for (i = 0; i < DUK_NUM_BUILTINS; i++) {
54384 }
54387 } else {
54388 /* We may come here if the object should have a FASTREFS flag
54389 * but it's missing for some reason. Assert for never getting
54390 * here; however, other than performance, this is harmless.
54391 */
54392 DUK_D(DUK_DPRINT("missing FASTREFS flag for: %!iO", h));
54393 DUK_ASSERT(0);
54394 }
54395}
54396
54398 DUK_ASSERT(heap != NULL);
54399 DUK_ASSERT(heap->heap_thread != NULL);
54400 DUK_ASSERT(hdr != NULL);
54401
54402 if (DUK_HEAPHDR_IS_OBJECT(hdr)) {
54404 }
54405 /* DUK_HTYPE_BUFFER: nothing to finalize */
54406 /* DUK_HTYPE_STRING: nothing to finalize */
54407}
54408
54409/*
54410 * Refzero processing for duk_hobject: queue a refzero'ed object to either
54411 * finalize_list or refzero_list and process the relevent list(s) if
54412 * necessary.
54413 *
54414 * Refzero_list is single linked, with only 'prev' pointers set and valid.
54415 * All 'next' pointers are intentionally left as garbage. This doesn't
54416 * matter because refzero_list is processed to completion before any other
54417 * code (like mark-and-sweep) might walk the list.
54418 *
54419 * In more detail:
54420 *
54421 * - On first insert refzero_list is NULL and the new object becomes the
54422 * first and only element on the list; duk__refcount_free_pending() is
54423 * called and it starts processing the list from the initial element,
54424 * i.e. the list tail.
54425 *
54426 * - As each object is refcount finalized, new objects may be queued to
54427 * refzero_list head. Their 'next' pointers are left as garbage, but
54428 * 'prev' points are set correctly, with the element at refzero_list
54429 * having a NULL 'prev' pointer. The fact that refzero_list is non-NULL
54430 * is used to reject (1) recursive duk__refcount_free_pending() and
54431 * (2) finalize_list processing calls.
54432 *
54433 * - When we're done with the current object, read its 'prev' pointer and
54434 * free the object. If 'prev' is NULL, we've reached head of list and are
54435 * done: set refzero_list to NULL and process pending finalizers. Otherwise
54436 * continue processing the list.
54437 *
54438 * A refzero cascade is free of side effects because it only involves
54439 * queueing more objects and freeing memory; finalizer execution is blocked
54440 * in the code path queueing objects to finalize_list. As a result the
54441 * initial refzero call (which triggers duk__refcount_free_pending()) must
54442 * check finalize_list so that finalizers are executed snappily.
54443 *
54444 * If finalize_list processing starts first, refzero may occur while we're
54445 * processing finalizers. That's fine: that particular refzero cascade is
54446 * handled to completion without side effects. Once the cascade is complete,
54447 * we'll run pending finalizers but notice that we're already doing that and
54448 * return.
54449 *
54450 * This could be expanded to allow incremental freeing: just bail out
54451 * early and resume at a future alloc/decref/refzero. However, if that
54452 * were done, the list structure would need to be kept consistent at all
54453 * times, mark-and-sweep would need to handle refzero_list, etc.
54454 */
54455
54457 duk_heaphdr *curr;
54458#if defined(DUK_USE_DEBUG)
54459 duk_int_t count = 0;
54460#endif
54461
54462 DUK_ASSERT(heap != NULL);
54463
54464 curr = heap->refzero_list;
54465 DUK_ASSERT(curr != NULL);
54466 DUK_ASSERT(DUK_HEAPHDR_GET_PREV(heap, curr) == NULL); /* We're called on initial insert only. */
54467 /* curr->next is GARBAGE. */
54468
54469 do {
54470 duk_heaphdr *prev;
54471
54472 DUK_DDD(DUK_DDDPRINT("refzero processing %p: %!O", (void *) curr, (duk_heaphdr *) curr));
54473
54474#if defined(DUK_USE_DEBUG)
54475 count++;
54476#endif
54477
54478 DUK_ASSERT(curr != NULL);
54479 DUK_ASSERT(DUK_HEAPHDR_GET_TYPE(curr) == DUK_HTYPE_OBJECT); /* currently, always the case */
54480 /* FINALIZED may be set; don't care about flags here. */
54481
54482 /* Refcount finalize 'curr'. Refzero_list must be non-NULL
54483 * here to prevent recursive entry to duk__refcount_free_pending().
54484 */
54485 DUK_ASSERT(heap->refzero_list != NULL);
54487
54488 prev = DUK_HEAPHDR_GET_PREV(heap, curr);
54489 DUK_ASSERT((prev == NULL && heap->refzero_list == curr) || (prev != NULL && heap->refzero_list != curr));
54490 /* prev->next is intentionally not updated and is garbage. */
54491
54492 duk_free_hobject(heap, (duk_hobject *) curr); /* Invalidates 'curr'. */
54493
54494 curr = prev;
54495 } while (curr != NULL);
54496
54497 heap->refzero_list = NULL;
54498
54499 DUK_DD(DUK_DDPRINT("refzero processed %ld objects", (long) count));
54500}
54501
54503 duk_heaphdr *hdr;
54505
54506 DUK_ASSERT(heap != NULL);
54507 DUK_ASSERT(heap->heap_thread != NULL);
54508 DUK_ASSERT(obj != NULL);
54510
54511 hdr = (duk_heaphdr *) obj;
54512
54513 /* Refzero'd objects must be in heap_allocated. They can't be in
54514 * finalize_list because all objects on finalize_list have an
54515 * artificial +1 refcount bump.
54516 */
54517#if defined(DUK_USE_ASSERTIONS)
54518 DUK_ASSERT(duk_heap_in_heap_allocated(heap, (duk_heaphdr *) obj));
54519#endif
54520
54522
54523#if defined(DUK_USE_FINALIZER_SUPPORT)
54524 /* This finalizer check MUST BE side effect free. It should also be
54525 * as fast as possible because it's applied to every object freed.
54526 */
54527 if (DUK_UNLIKELY(DUK_HOBJECT_HAS_FINALIZER_FAST(heap, (duk_hobject *) hdr) != 0U)) {
54528 /* Special case: FINALIZED may be set if mark-and-sweep queued
54529 * object for finalization, the finalizer was executed (and
54530 * FINALIZED set), mark-and-sweep hasn't yet processed the
54531 * object again, but its refcount drops to zero. Free without
54532 * running the finalizer again.
54533 */
54534 if (DUK_HEAPHDR_HAS_FINALIZED(hdr)) {
54535 DUK_D(DUK_DPRINT("refzero'd object has finalizer and FINALIZED is set -> free"));
54536 } else {
54537 /* Set FINALIZABLE flag so that all objects on finalize_list
54538 * will have it set and are thus detectable based on the
54539 * flag alone.
54540 */
54543
54544#if defined(DUK_USE_REFERENCE_COUNTING)
54545 /* Bump refcount on finalize_list insert so that a
54546 * refzero can never occur when an object is waiting
54547 * for its finalizer call. Refzero might otherwise
54548 * now happen because we allow duk_push_heapptr() for
54549 * objects pending finalization.
54550 */
54552#endif
54554
54555 /* Process finalizers unless skipping is explicitly
54556 * requested (NORZ) or refzero_list is being processed
54557 * (avoids side effects during a refzero cascade).
54558 * If refzero_list is processed, the initial refzero
54559 * call will run pending finalizers when refzero_list
54560 * is done.
54561 */
54562 if (!skip_free_pending && heap->refzero_list == NULL) {
54564 }
54565 return;
54566 }
54567 }
54568#endif /* DUK_USE_FINALIZER_SUPPORT */
54569
54570 /* No need to finalize, free object via refzero_list. */
54571
54572 root = heap->refzero_list;
54573
54574 DUK_HEAPHDR_SET_PREV(heap, hdr, NULL);
54575 /* 'next' is left as GARBAGE. */
54576 heap->refzero_list = hdr;
54577
54578 if (root == NULL) {
54579 /* Object is now queued. Refzero_list was NULL so
54580 * no-one is currently processing it; do it here.
54581 * With refzero processing just doing a cascade of
54582 * free calls, we can process it directly even when
54583 * NORZ macros are used: there are no side effects.
54584 */
54586 DUK_ASSERT(heap->refzero_list == NULL);
54587
54588 /* Process finalizers only after the entire cascade
54589 * is finished. In most cases there's nothing to
54590 * finalize, so fast path check to avoid a call.
54591 */
54592#if defined(DUK_USE_FINALIZER_SUPPORT)
54593 if (!skip_free_pending && DUK_UNLIKELY(heap->finalize_list != NULL)) {
54595 }
54596#endif
54597 } else {
54598 DUK_ASSERT(DUK_HEAPHDR_GET_PREV(heap, root) == NULL);
54599 DUK_HEAPHDR_SET_PREV(heap, root, hdr);
54600
54601 /* Object is now queued. Because refzero_list was
54602 * non-NULL, it's already being processed by someone
54603 * in the C call stack, so we're done.
54604 */
54605 }
54606}
54608#if defined(DUK_USE_FINALIZER_SUPPORT)
54610 DUK_ASSERT(thr != NULL);
54611 DUK_ASSERT(thr->heap != NULL);
54612 DUK_ASSERT(thr->heap->refzero_list == NULL); /* Processed to completion inline. */
54613
54614 if (DUK_UNLIKELY(thr->heap->finalize_list != NULL)) {
54616 }
54617}
54618
54620 DUK_ASSERT(thr != NULL);
54621 DUK_ASSERT(thr->heap != NULL);
54622 DUK_ASSERT(thr->heap->refzero_list == NULL); /* Processed to completion inline. */
54623
54624 if (DUK_UNLIKELY(thr->heap->finalize_list != NULL)) {
54626 }
54627}
54628#endif /* DUK_USE_FINALIZER_SUPPORT */
54629
54630/*
54631 * Refzero processing for duk_hstring.
54632 */
54633
54635 DUK_ASSERT(heap != NULL);
54636 DUK_ASSERT(heap->heap_thread != NULL);
54637 DUK_ASSERT(str != NULL);
54639
54641 duk_heap_strtable_unlink(heap, str);
54642 duk_free_hstring(heap, str);
54643}
54644
54645/*
54646 * Refzero processing for duk_hbuffer.
54647 */
54648
54650 DUK_ASSERT(heap != NULL);
54651 DUK_ASSERT(heap->heap_thread != NULL);
54652 DUK_ASSERT(buf != NULL);
54654
54656 duk_free_hbuffer(heap, buf);
54657}
54658
54659/*
54660 * Incref and decref functions.
54661 *
54662 * Decref may trigger immediate refzero handling, which may free and finalize
54663 * an arbitrary number of objects (a "DECREF cascade").
54664 *
54665 * Refzero handling is skipped entirely if (1) mark-and-sweep is running or
54666 * (2) execution is paused in the debugger. The objects are left in the heap,
54667 * and will be freed by mark-and-sweep or eventual heap destruction.
54668 *
54669 * This is necessary during mark-and-sweep because refcounts are also updated
54670 * during the sweep phase (otherwise objects referenced by a swept object
54671 * would have incorrect refcounts) which then calls here. This could be
54672 * avoided by using separate decref macros in mark-and-sweep; however,
54673 * mark-and-sweep also calls finalizers which would use the ordinary decref
54674 * macros anyway.
54675 *
54676 * We can't process refzeros (= free objects) when the debugger is running
54677 * as the debugger might make an object unreachable but still continue
54678 * inspecting it (or even cause it to be pushed back). So we must rely on
54679 * mark-and-sweep to collect them.
54680 *
54681 * The DUK__RZ_SUPPRESS_CHECK() condition is also used in heap destruction
54682 * when running finalizers for remaining objects: the flag prevents objects
54683 * from being moved around in heap linked lists while that's being done.
54684 *
54685 * The suppress condition is important to performance.
54686 */
54687
54688#define DUK__RZ_SUPPRESS_ASSERT1() \
54689 do { \
54690 DUK_ASSERT(thr != NULL); \
54691 DUK_ASSERT(thr->heap != NULL); \
54692 /* When mark-and-sweep runs, heap_thread must exist. */ \
54693 DUK_ASSERT(thr->heap->ms_running == 0 || thr->heap->heap_thread != NULL); \
54694 /* In normal operation finalizers are executed with ms_running == 0 \
54695 * so we should never see ms_running == 1 and thr != heap_thread. \
54696 * In heap destruction finalizers are executed with ms_running != 0 \
54697 * to e.g. prevent refzero; a special value ms_running == 2 is used \
54698 * in that case so it can be distinguished from the normal runtime \
54699 * case, and allows a stronger assertion here (GH-2030). \
54700 */ \
54701 DUK_ASSERT(!(thr->heap->ms_running == 1 && thr != thr->heap->heap_thread)); \
54702 /* We may be called when the heap is initializing and we process \
54703 * refzeros normally, but mark-and-sweep and finalizers are prevented \
54704 * if that's the case. \
54705 */ \
54706 DUK_ASSERT(thr->heap->heap_initializing == 0 || thr->heap->ms_prevent_count > 0); \
54707 DUK_ASSERT(thr->heap->heap_initializing == 0 || thr->heap->pf_prevent_count > 0); \
54708 } while (0)
54709
54710#if defined(DUK_USE_DEBUGGER_SUPPORT)
54711#define DUK__RZ_SUPPRESS_ASSERT2() \
54712 do { \
54713 /* When debugger is paused, ms_running is set. */ \
54714 DUK_ASSERT(!DUK_HEAP_HAS_DEBUGGER_PAUSED(thr->heap) || thr->heap->ms_running != 0); \
54715 } while (0)
54716#define DUK__RZ_SUPPRESS_COND() (heap->ms_running != 0)
54717#else
54718#define DUK__RZ_SUPPRESS_ASSERT2() \
54719 do { \
54720 } while (0)
54721#define DUK__RZ_SUPPRESS_COND() (heap->ms_running != 0)
54722#endif /* DUK_USE_DEBUGGER_SUPPORT */
54724#define DUK__RZ_SUPPRESS_CHECK() \
54725 do { \
54726 DUK__RZ_SUPPRESS_ASSERT1(); \
54727 DUK__RZ_SUPPRESS_ASSERT2(); \
54728 if (DUK_UNLIKELY(DUK__RZ_SUPPRESS_COND())) { \
54729 DUK_DDD( \
54730 DUK_DDDPRINT("refzero handling suppressed (not even queued) when mark-and-sweep running, object: %p", \
54731 (void *) h)); \
54732 return; \
54733 } \
54734 } while (0)
54736#define DUK__RZ_STRING() \
54737 do { \
54738 duk__refcount_refzero_hstring(heap, (duk_hstring *) h); \
54739 } while (0)
54740#define DUK__RZ_BUFFER() \
54741 do { \
54742 duk__refcount_refzero_hbuffer(heap, (duk_hbuffer *) h); \
54743 } while (0)
54744#define DUK__RZ_OBJECT() \
54745 do { \
54746 duk__refcount_refzero_hobject(heap, (duk_hobject *) h, skip_free_pending); \
54747 } while (0)
54748
54749/* XXX: test the effect of inlining here vs. NOINLINE in refzero helpers */
54750#if defined(DUK_USE_FAST_REFCOUNT_DEFAULT)
54751#define DUK__RZ_INLINE DUK_ALWAYS_INLINE
54752#else
54753#define DUK__RZ_INLINE /*nop*/
54754#endif
54755
54758
54759 DUK_ASSERT(thr != NULL);
54760 DUK_ASSERT(h != NULL);
54761 heap = thr->heap;
54762
54765}
54766
54769
54770 DUK_ASSERT(thr != NULL);
54771 DUK_ASSERT(h != NULL);
54772 heap = thr->heap;
54773
54776}
54777
54779 duk_heap *heap;
54780
54781 DUK_ASSERT(thr != NULL);
54782 DUK_ASSERT(h != NULL);
54783 heap = thr->heap;
54784
54787}
54788
54790 duk_heap *heap;
54791 duk_small_uint_t htype;
54792
54793 DUK_ASSERT(thr != NULL);
54794 DUK_ASSERT(h != NULL);
54795 heap = thr->heap;
54796
54798 DUK_DDD(DUK_DDDPRINT("ms_running=%ld, heap_thread=%p", (long) thr->heap->ms_running, thr->heap->heap_thread));
54800
54801 switch (htype) {
54802 case DUK_HTYPE_STRING:
54803 /* Strings have no internal references but do have "weak"
54804 * references in the string cache. Also note that strings
54805 * are not on the heap_allocated list like other heap
54806 * elements.
54807 */
54808
54810 break;
54812 case DUK_HTYPE_OBJECT:
54813 /* Objects have internal references. Must finalize through
54814 * the "refzero" work list.
54816
54818 break;
54820 default:
54821 /* Buffers have no internal references. However, a dynamic
54822 * buffer has a separate allocation for the buffer. This is
54823 * freed by duk_heap_free_heaphdr_raw().
54824 */
54825
54828 break;
54829 }
54830}
54833 duk__heaphdr_refzero_helper(thr, h, 0 /*skip_free_pending*/);
54834}
54835
54837 duk__heaphdr_refzero_helper(thr, h, 1 /*skip_free_pending*/);
54838}
54839
54842}
54843
54846}
54847
54849 duk__hobject_refzero_helper(thr, h, 0 /*skip_free_pending*/);
54850}
54851
54853 duk__hobject_refzero_helper(thr, h, 1 /*skip_free_pending*/);
54854}
54855
54856#if !defined(DUK_USE_FAST_REFCOUNT_DEFAULT)
54857DUK_INTERNAL void duk_tval_incref(duk_tval *tv) {
54858 DUK_ASSERT(tv != NULL);
54859
54862 DUK_ASSERT(h != NULL);
54866 DUK_ASSERT(DUK_HEAPHDR_GET_REFCOUNT(h) != 0); /* No wrapping. */
54867 }
54868}
54869
54870DUK_INTERNAL void duk_tval_decref(duk_hthread *thr, duk_tval *tv) {
54871 DUK_ASSERT(thr != NULL);
54872 DUK_ASSERT(tv != NULL);
54873
54876 DUK_ASSERT(h != NULL);
54879#if 0
54880 if (DUK_HEAPHDR_PREDEC_REFCOUNT(h) != 0) {
54881 return;
54882 }
54883 duk_heaphdr_refzero(thr, h);
54884#else
54885 duk_heaphdr_decref(thr, h);
54886#endif
54887 }
54888}
54889
54890DUK_INTERNAL void duk_tval_decref_norz(duk_hthread *thr, duk_tval *tv) {
54891 DUK_ASSERT(thr != NULL);
54892 DUK_ASSERT(tv != NULL);
54893
54896 DUK_ASSERT(h != NULL);
54899#if 0
54900 if (DUK_HEAPHDR_PREDEC_REFCOUNT(h) != 0) {
54901 return;
54902 }
54904#else
54905 duk_heaphdr_decref_norz(thr, h);
54906#endif
54907 }
54908}
54909#endif /* !DUK_USE_FAST_REFCOUNT_DEFAULT */
54910
54911#define DUK__DECREF_ASSERTS() \
54912 do { \
54913 DUK_ASSERT(thr != NULL); \
54914 DUK_ASSERT(thr->heap != NULL); \
54915 DUK_ASSERT(h != NULL); \
54916 DUK_ASSERT(DUK_HEAPHDR_HTYPE_VALID((duk_heaphdr *) h)); \
54917 DUK_ASSERT(DUK_HEAPHDR_GET_REFCOUNT((duk_heaphdr *) h) >= 1); \
54918 } while (0)
54919#if defined(DUK_USE_ROM_OBJECTS)
54920#define DUK__INCREF_SHARED() \
54921 do { \
54922 if (DUK_HEAPHDR_HAS_READONLY((duk_heaphdr *) h)) { \
54923 return; \
54924 } \
54925 DUK_HEAPHDR_PREINC_REFCOUNT((duk_heaphdr *) h); \
54926 DUK_ASSERT(DUK_HEAPHDR_GET_REFCOUNT((duk_heaphdr *) h) != 0); /* No wrapping. */ \
54927 } while (0)
54928#define DUK__DECREF_SHARED() \
54929 do { \
54930 if (DUK_HEAPHDR_HAS_READONLY((duk_heaphdr *) h)) { \
54931 return; \
54932 } \
54933 if (DUK_HEAPHDR_PREDEC_REFCOUNT((duk_heaphdr *) h) != 0) { \
54934 return; \
54935 } \
54936 } while (0)
54937#else
54938#define DUK__INCREF_SHARED() \
54939 do { \
54940 DUK_HEAPHDR_PREINC_REFCOUNT((duk_heaphdr *) h); \
54941 DUK_ASSERT(DUK_HEAPHDR_GET_REFCOUNT((duk_heaphdr *) h) != 0); /* No wrapping. */ \
54942 } while (0)
54943#define DUK__DECREF_SHARED() \
54944 do { \
54945 if (DUK_HEAPHDR_PREDEC_REFCOUNT((duk_heaphdr *) h) != 0) { \
54946 return; \
54947 } \
54948 } while (0)
54949#endif
54950
54951#if !defined(DUK_USE_FAST_REFCOUNT_DEFAULT)
54952/* This will in practice be inlined because it's just an INC instructions
54953 * and a bit test + INC when ROM objects are enabled.
54954 */
54955DUK_INTERNAL void duk_heaphdr_incref(duk_heaphdr *h) {
54956 DUK_ASSERT(h != NULL);
54959
54961}
54962
54963DUK_INTERNAL void duk_heaphdr_decref(duk_hthread *thr, duk_heaphdr *h) {
54966 duk_heaphdr_refzero(thr, h);
54967
54968 /* Forced mark-and-sweep when GC torture enabled; this could happen
54969 * on any DECREF (but not DECREF_NORZ).
54970 */
54971 DUK_GC_TORTURE(thr->heap);
54972}
54973DUK_INTERNAL void duk_heaphdr_decref_norz(duk_hthread *thr, duk_heaphdr *h) {
54977}
54978#endif /* !DUK_USE_FAST_REFCOUNT_DEFAULT */
54979
54980#if 0 /* Not needed. */
54981DUK_INTERNAL void duk_hstring_decref(duk_hthread *thr, duk_hstring *h) {
54984 duk_hstring_refzero(thr, h);
54985}
54986DUK_INTERNAL void duk_hstring_decref_norz(duk_hthread *thr, duk_hstring *h) {
54989 duk_hstring_refzero_norz(thr, h);
54990}
54991DUK_INTERNAL void duk_hbuffer_decref(duk_hthread *thr, duk_hbuffer *h) {
54994 duk_hbuffer_refzero(thr, h);
54995}
54996DUK_INTERNAL void duk_hbuffer_decref_norz(duk_hthread *thr, duk_hbuffer *h) {
54999 duk_hbuffer_refzero_norz(thr, h);
55000}
55001DUK_INTERNAL void duk_hobject_decref(duk_hthread *thr, duk_hobject *h) {
55004 duk_hobject_refzero(thr, h);
55005}
55006DUK_INTERNAL void duk_hobject_decref_norz(duk_hthread *thr, duk_hobject *h) {
55010}
55011#endif
55012
55013#else /* DUK_USE_REFERENCE_COUNTING */
55014
55015/* no refcounting */
55016
55017#endif /* DUK_USE_REFERENCE_COUNTING */
55018
55019/* automatic undefs */
55020#undef DUK__DECREF_ASSERTS
55021#undef DUK__DECREF_SHARED
55022#undef DUK__INCREF_SHARED
55023#undef DUK__RZ_BUFFER
55024#undef DUK__RZ_INLINE
55025#undef DUK__RZ_OBJECT
55026#undef DUK__RZ_STRING
55027#undef DUK__RZ_SUPPRESS_ASSERT1
55028#undef DUK__RZ_SUPPRESS_ASSERT2
55029#undef DUK__RZ_SUPPRESS_CHECK
55030#undef DUK__RZ_SUPPRESS_COND
55031/*
55032 * String cache.
55033 *
55034 * Provides a cache to optimize indexed string lookups. The cache keeps
55035 * track of (byte offset, char offset) states for a fixed number of strings.
55036 * Otherwise we'd need to scan from either end of the string, as we store
55037 * strings in (extended) UTF-8.
55038 */
55039
55040/* #include duk_internal.h -> already included */
55041
55042/*
55043 * Delete references to given hstring from the heap string cache.
55044 *
55045 * String cache references are 'weak': they are not counted towards
55046 * reference counts, nor serve as roots for mark-and-sweep. When an
55047 * object is about to be freed, such references need to be removed.
55048 */
55049
55051 duk_uint_t i;
55052 for (i = 0; i < DUK_HEAP_STRCACHE_SIZE; i++) {
55053 duk_strcache_entry *c = heap->strcache + i;
55054 if (c->h == h) {
55055 DUK_DD(
55056 DUK_DDPRINT("deleting weak strcache reference to hstring %p from heap %p", (void *) h, (void *) heap));
55057 c->h = NULL;
55058
55059 /* XXX: the string shouldn't appear twice, but we now loop to the
55060 * end anyway; if fixed, add a looping assertion to ensure there
55061 * is no duplicate.
55062 */
55063 }
55064 }
55065}
55066
55067/*
55068 * String scanning helpers
55069 *
55070 * All bytes other than UTF-8 continuation bytes ([0x80,0xbf]) are
55071 * considered to contribute a character. This must match how string
55072 * character length is computed.
55073 */
55074
55075DUK_LOCAL const duk_uint8_t *duk__scan_forwards(const duk_uint8_t *p, const duk_uint8_t *q, duk_uint_fast32_t n) {
55076 while (n > 0) {
55077 for (;;) {
55078 p++;
55079 if (p >= q) {
55080 return NULL;
55081 }
55082 if ((*p & 0xc0) != 0x80) {
55083 break;
55084 }
55085 }
55086 n--;
55087 }
55088 return p;
55089}
55090
55091DUK_LOCAL const duk_uint8_t *duk__scan_backwards(const duk_uint8_t *p, const duk_uint8_t *q, duk_uint_fast32_t n) {
55092 while (n > 0) {
55093 for (;;) {
55094 p--;
55095 if (p < q) {
55096 return NULL;
55097 }
55098 if ((*p & 0xc0) != 0x80) {
55099 break;
55100 }
55101 }
55102 n--;
55103 }
55104 return p;
55105}
55106
55107/*
55108 * Convert char offset to byte offset
55109 *
55110 * Avoid using the string cache if possible: for ASCII strings byte and
55111 * char offsets are equal and for short strings direct scanning may be
55112 * better than using the string cache (which may evict a more important
55113 * entry).
55114 *
55115 * Typing now assumes 32-bit string byte/char offsets (duk_uint_fast32_t).
55116 * Better typing might be to use duk_size_t.
55117 *
55118 * Caller should ensure 'char_offset' is within the string bounds [0,charlen]
55119 * (endpoint is inclusive). If this is not the case, no memory unsafe
55120 * behavior will happen but an error will be thrown.
55121 */
55122
55124 duk_heap *heap;
55125 duk_strcache_entry *sce;
55126 duk_uint_fast32_t byte_offset;
55127 duk_uint_t i;
55128 duk_bool_t use_cache;
55129 duk_uint_fast32_t dist_start, dist_end, dist_sce;
55130 duk_uint_fast32_t char_length;
55131 const duk_uint8_t *p_start;
55132 const duk_uint8_t *p_end;
55133 const duk_uint8_t *p_found;
55134
55135 /*
55136 * For ASCII strings, the answer is simple.
55137 */
55138
55140 return char_offset;
55141 }
55142
55143 char_length = (duk_uint_fast32_t) DUK_HSTRING_GET_CHARLEN(h);
55144 DUK_ASSERT(char_offset <= char_length);
55145
55147 /* Must recheck because the 'is ascii' flag may be set
55148 * lazily. Alternatively, we could just compare charlen
55149 * to bytelen.
55150 */
55151 return char_offset;
55152 }
55153
55154 /*
55155 * For non-ASCII strings, we need to scan forwards or backwards
55156 * from some starting point. The starting point may be the start
55157 * or end of the string, or some cached midpoint in the string
55158 * cache.
55159 *
55160 * For "short" strings we simply scan without checking or updating
55161 * the cache. For longer strings we check and update the cache as
55162 * necessary, inserting a new cache entry if none exists.
55163 */
55164
55165 DUK_DDD(DUK_DDDPRINT("non-ascii string %p, char_offset=%ld, clen=%ld, blen=%ld",
55166 (void *) h,
55167 (long) char_offset,
55168 (long) DUK_HSTRING_GET_CHARLEN(h),
55169 (long) DUK_HSTRING_GET_BYTELEN(h)));
55170
55171 heap = thr->heap;
55172 sce = NULL;
55173 use_cache = (char_length > DUK_HEAP_STRINGCACHE_NOCACHE_LIMIT);
55174
55175 if (use_cache) {
55176#if defined(DUK_USE_DEBUG_LEVEL) && (DUK_USE_DEBUG_LEVEL >= 2)
55177 DUK_DDD(DUK_DDDPRINT("stringcache before char2byte (using cache):"));
55178 for (i = 0; i < DUK_HEAP_STRCACHE_SIZE; i++) {
55179 duk_strcache_entry *c = heap->strcache + i;
55180 DUK_DDD(DUK_DDDPRINT(" [%ld] -> h=%p, cidx=%ld, bidx=%ld",
55181 (long) i,
55182 (void *) c->h,
55183 (long) c->cidx,
55184 (long) c->bidx));
55185 }
55186#endif
55187
55188 for (i = 0; i < DUK_HEAP_STRCACHE_SIZE; i++) {
55189 duk_strcache_entry *c = heap->strcache + i;
55190
55191 if (c->h == h) {
55192 sce = c;
55193 break;
55194 }
55195 }
55196 }
55197
55198 /*
55199 * Scan from shortest distance:
55200 * - start of string
55201 * - end of string
55202 * - cache entry (if exists)
55203 */
55204
55205 DUK_ASSERT(DUK_HSTRING_GET_CHARLEN(h) >= char_offset);
55206 dist_start = char_offset;
55207 dist_end = char_length - char_offset;
55208 dist_sce = 0;
55209 DUK_UNREF(dist_sce); /* initialize for debug prints, needed if sce==NULL */
55210
55211 p_start = (const duk_uint8_t *) DUK_HSTRING_GET_DATA(h);
55212 p_end = (const duk_uint8_t *) (p_start + DUK_HSTRING_GET_BYTELEN(h));
55213 p_found = NULL;
55214
55215 if (sce) {
55216 if (char_offset >= sce->cidx) {
55217 dist_sce = char_offset - sce->cidx;
55218 if ((dist_sce <= dist_start) && (dist_sce <= dist_end)) {
55219 DUK_DDD(DUK_DDDPRINT("non-ascii string, use_cache=%ld, sce=%p:%ld:%ld, "
55220 "dist_start=%ld, dist_end=%ld, dist_sce=%ld => "
55221 "scan forwards from sce",
55222 (long) use_cache,
55223 (void *) (sce ? sce->h : NULL),
55224 (sce ? (long) sce->cidx : (long) -1),
55225 (sce ? (long) sce->bidx : (long) -1),
55226 (long) dist_start,
55227 (long) dist_end,
55228 (long) dist_sce));
55229
55230 p_found = duk__scan_forwards(p_start + sce->bidx, p_end, dist_sce);
55231 goto scan_done;
55232 }
55233 } else {
55234 dist_sce = sce->cidx - char_offset;
55235 if ((dist_sce <= dist_start) && (dist_sce <= dist_end)) {
55236 DUK_DDD(DUK_DDDPRINT("non-ascii string, use_cache=%ld, sce=%p:%ld:%ld, "
55237 "dist_start=%ld, dist_end=%ld, dist_sce=%ld => "
55238 "scan backwards from sce",
55239 (long) use_cache,
55240 (void *) (sce ? sce->h : NULL),
55241 (sce ? (long) sce->cidx : (long) -1),
55242 (sce ? (long) sce->bidx : (long) -1),
55243 (long) dist_start,
55244 (long) dist_end,
55245 (long) dist_sce));
55246
55247 p_found = duk__scan_backwards(p_start + sce->bidx, p_start, dist_sce);
55248 goto scan_done;
55249 }
55250 }
55251 }
55252
55253 /* no sce, or sce scan not best */
55254
55255 if (dist_start <= dist_end) {
55256 DUK_DDD(DUK_DDDPRINT("non-ascii string, use_cache=%ld, sce=%p:%ld:%ld, "
55257 "dist_start=%ld, dist_end=%ld, dist_sce=%ld => "
55258 "scan forwards from string start",
55259 (long) use_cache,
55260 (void *) (sce ? sce->h : NULL),
55261 (sce ? (long) sce->cidx : (long) -1),
55262 (sce ? (long) sce->bidx : (long) -1),
55263 (long) dist_start,
55264 (long) dist_end,
55265 (long) dist_sce));
55266
55267 p_found = duk__scan_forwards(p_start, p_end, dist_start);
55268 } else {
55269 DUK_DDD(DUK_DDDPRINT("non-ascii string, use_cache=%ld, sce=%p:%ld:%ld, "
55270 "dist_start=%ld, dist_end=%ld, dist_sce=%ld => "
55271 "scan backwards from string end",
55272 (long) use_cache,
55273 (void *) (sce ? sce->h : NULL),
55274 (sce ? (long) sce->cidx : (long) -1),
55275 (sce ? (long) sce->bidx : (long) -1),
55276 (long) dist_start,
55277 (long) dist_end,
55278 (long) dist_sce));
55279
55280 p_found = duk__scan_backwards(p_end, p_start, dist_end);
55281 }
55282
55283scan_done:
55284
55285 if (DUK_UNLIKELY(p_found == NULL)) {
55286 /* Scan error: this shouldn't normally happen; it could happen if
55287 * string is not valid UTF-8 data, and clen/blen are not consistent
55288 * with the scanning algorithm.
55289 */
55290 goto scan_error;
55291 }
55292
55293 DUK_ASSERT(p_found >= p_start);
55294 DUK_ASSERT(p_found <= p_end); /* may be equal */
55295 byte_offset = (duk_uint32_t) (p_found - p_start);
55296
55297 DUK_DDD(DUK_DDDPRINT("-> string %p, cidx %ld -> bidx %ld", (void *) h, (long) char_offset, (long) byte_offset));
55298
55299 /*
55300 * Update cache entry (allocating if necessary), and move the
55301 * cache entry to the first place (in an "LRU" policy).
55302 */
55303
55304 if (use_cache) {
55305 /* update entry, allocating if necessary */
55306 if (!sce) {
55307 sce = heap->strcache + DUK_HEAP_STRCACHE_SIZE - 1; /* take last entry */
55308 sce->h = h;
55309 }
55310 DUK_ASSERT(sce != NULL);
55311 sce->bidx = (duk_uint32_t) (p_found - p_start);
55312 sce->cidx = (duk_uint32_t) char_offset;
55313
55314 /* LRU: move our entry to first */
55315 if (sce > &heap->strcache[0]) {
55316 /*
55317 * A C
55318 * B A
55319 * C <- sce ==> B
55320 * D D
55321 */
55323
55324 tmp = *sce;
55325 duk_memmove((void *) (&heap->strcache[1]),
55326 (const void *) (&heap->strcache[0]),
55327 (size_t) (((char *) sce) - ((char *) &heap->strcache[0])));
55328 heap->strcache[0] = tmp;
55329
55330 /* 'sce' points to the wrong entry here, but is no longer used */
55331 }
55332#if defined(DUK_USE_DEBUG_LEVEL) && (DUK_USE_DEBUG_LEVEL >= 2)
55333 DUK_DDD(DUK_DDDPRINT("stringcache after char2byte (using cache):"));
55334 for (i = 0; i < DUK_HEAP_STRCACHE_SIZE; i++) {
55335 duk_strcache_entry *c = heap->strcache + i;
55336 DUK_DDD(DUK_DDDPRINT(" [%ld] -> h=%p, cidx=%ld, bidx=%ld",
55337 (long) i,
55338 (void *) c->h,
55339 (long) c->cidx,
55340 (long) c->bidx));
55341 }
55342#endif
55343 }
55344
55345 return byte_offset;
55346
55347scan_error:
55348 DUK_ERROR_INTERNAL(thr);
55352 * Heap string table handling, string interning.
55353 */
55355/* #include duk_internal.h -> already included */
55356
55357/* Resize checks not needed if minsize == maxsize, typical for low memory
55358 * targets.
55359 */
55360#define DUK__STRTAB_RESIZE_CHECK
55361#if (DUK_USE_STRTAB_MINSIZE == DUK_USE_STRTAB_MAXSIZE)
55362#undef DUK__STRTAB_RESIZE_CHECK
55363#endif
55364
55365#if defined(DUK_USE_STRTAB_PTRCOMP)
55366#define DUK__HEAPPTR_ENC16(heap, ptr) DUK_USE_HEAPPTR_ENC16((heap)->heap_udata, (ptr))
55367#define DUK__HEAPPTR_DEC16(heap, val) DUK_USE_HEAPPTR_DEC16((heap)->heap_udata, (val))
55368#define DUK__GET_STRTABLE(heap) ((heap)->strtable16)
55369#else
55370#define DUK__HEAPPTR_ENC16(heap, ptr) (ptr)
55371#define DUK__HEAPPTR_DEC16(heap, val) (val)
55372#define DUK__GET_STRTABLE(heap) ((heap)->strtable)
55373#endif
55374
55375#define DUK__STRTAB_U32_MAX_STRLEN 10 /* 4'294'967'295 */
55376
55377/*
55378 * Debug dump stringtable.
55379 */
55380
55381#if defined(DUK_USE_DEBUG)
55382DUK_INTERNAL void duk_heap_strtable_dump(duk_heap *heap) {
55383#if defined(DUK_USE_STRTAB_PTRCOMP)
55384 duk_uint16_t *strtable;
55385#else
55386 duk_hstring **strtable;
55387#endif
55388 duk_uint32_t i;
55389 duk_hstring *h;
55390 duk_size_t count_total = 0;
55391 duk_size_t count_chain;
55392 duk_size_t count_chain_min = DUK_SIZE_MAX;
55393 duk_size_t count_chain_max = 0;
55394 duk_size_t count_len[8]; /* chain lengths from 0 to 7 */
55395
55396 if (heap == NULL) {
55397 DUK_D(DUK_DPRINT("string table, heap=NULL"));
55398 return;
55399 }
55400
55401 strtable = DUK__GET_STRTABLE(heap);
55402 if (strtable == NULL) {
55403 DUK_D(DUK_DPRINT("string table, strtab=NULL"));
55404 return;
55405 }
55406
55407 duk_memzero((void *) count_len, sizeof(count_len));
55408 for (i = 0; i < heap->st_size; i++) {
55409 h = DUK__HEAPPTR_DEC16(heap, strtable[i]);
55410 count_chain = 0;
55411 while (h != NULL) {
55412 count_chain++;
55413 h = h->hdr.h_next;
55414 }
55415 if (count_chain < sizeof(count_len) / sizeof(duk_size_t)) {
55416 count_len[count_chain]++;
55417 }
55418 count_chain_max = (count_chain > count_chain_max ? count_chain : count_chain_max);
55419 count_chain_min = (count_chain < count_chain_min ? count_chain : count_chain_min);
55420 count_total += count_chain;
55421 }
55422
55423 DUK_D(DUK_DPRINT("string table, strtab=%p, count=%lu, chain min=%lu max=%lu avg=%lf: "
55424 "counts: %lu %lu %lu %lu %lu %lu %lu %lu ...",
55425 (void *) heap->strtable,
55426 (unsigned long) count_total,
55427 (unsigned long) count_chain_min,
55428 (unsigned long) count_chain_max,
55429 (double) count_total / (double) heap->st_size,
55430 (unsigned long) count_len[0],
55431 (unsigned long) count_len[1],
55432 (unsigned long) count_len[2],
55433 (unsigned long) count_len[3],
55434 (unsigned long) count_len[4],
55435 (unsigned long) count_len[5],
55436 (unsigned long) count_len[6],
55437 (unsigned long) count_len[7]));
55438}
55439#endif /* DUK_USE_DEBUG */
55440
55441/*
55442 * Assertion helper to ensure strtable is populated correctly.
55443 */
55444
55445#if defined(DUK_USE_ASSERTIONS)
55446DUK_LOCAL void duk__strtable_assert_checks(duk_heap *heap) {
55447#if defined(DUK_USE_STRTAB_PTRCOMP)
55448 duk_uint16_t *strtable;
55449#else
55450 duk_hstring **strtable;
55451#endif
55452 duk_uint32_t i;
55453 duk_hstring *h;
55454 duk_size_t count = 0;
55455
55456 DUK_ASSERT(heap != NULL);
55457
55458 strtable = DUK__GET_STRTABLE(heap);
55459 if (strtable != NULL) {
55460 DUK_ASSERT(heap->st_size != 0);
55461 DUK_ASSERT(heap->st_mask == heap->st_size - 1);
55462
55463 for (i = 0; i < heap->st_size; i++) {
55464 h = DUK__HEAPPTR_DEC16(heap, strtable[i]);
55465 while (h != NULL) {
55466 DUK_ASSERT((DUK_HSTRING_GET_HASH(h) & heap->st_mask) == i);
55467 count++;
55468 h = h->hdr.h_next;
55469 }
55470 }
55471 } else {
55472 DUK_ASSERT(heap->st_size == 0);
55473 DUK_ASSERT(heap->st_mask == 0);
55474 }
55475
55476#if defined(DUK__STRTAB_RESIZE_CHECK)
55477 DUK_ASSERT(count == (duk_size_t) heap->st_count);
55478#endif
55479}
55480#endif /* DUK_USE_ASSERTIONS */
55481
55482/*
55483 * Allocate and initialize a duk_hstring.
55484 *
55485 * Returns a NULL if allocation or initialization fails for some reason.
55486 *
55487 * The string won't be inserted into the string table and isn't tracked in
55488 * any way (link pointers will be NULL). The caller must place the string
55489 * into the string table without any risk of a longjmp, otherwise the string
55490 * is leaked.
55491 */
55492
55494 const duk_uint8_t *str,
55495 duk_uint32_t blen,
55496 duk_uint32_t strhash,
55497 const duk_uint8_t *extdata) {
55498 duk_hstring *res;
55499 const duk_uint8_t *data;
55500#if !defined(DUK_USE_HSTRING_ARRIDX)
55501 duk_uarridx_t dummy;
55502#endif
55503
55504 DUK_ASSERT(heap != NULL);
55505 DUK_UNREF(extdata);
55506
55507#if defined(DUK_USE_STRLEN16)
55508 /* If blen <= 0xffffUL, clen is also guaranteed to be <= 0xffffUL. */
55509 if (blen > 0xffffUL) {
55510 DUK_D(DUK_DPRINT("16-bit string blen/clen active and blen over 16 bits, reject intern"));
55511 goto alloc_error;
55512 }
55513#endif
55514
55515 /* XXX: Memzeroing the allocated structure is not really necessary
55516 * because we could just initialize all fields explicitly (almost
55517 * all fields are initialized explicitly anyway).
55518 */
55519#if defined(DUK_USE_HSTRING_EXTDATA) && defined(DUK_USE_EXTSTR_INTERN_CHECK)
55520 if (extdata) {
55521 res = (duk_hstring *) DUK_ALLOC(heap, sizeof(duk_hstring_external));
55522 if (DUK_UNLIKELY(res == NULL)) {
55523 goto alloc_error;
55524 }
55525 duk_memzero(res, sizeof(duk_hstring_external));
55526#if defined(DUK_USE_EXPLICIT_NULL_INIT)
55528#endif
55530
55531 DUK_ASSERT(extdata[blen] == 0); /* Application responsibility. */
55532 data = extdata;
55533 ((duk_hstring_external *) res)->extdata = extdata;
55534 } else
55535#endif /* DUK_USE_HSTRING_EXTDATA && DUK_USE_EXTSTR_INTERN_CHECK */
55536 {
55537 duk_uint8_t *data_tmp;
55538
55539 /* NUL terminate for convenient C access */
55540 DUK_ASSERT(sizeof(duk_hstring) + blen + 1 > blen); /* No wrap, limits ensure. */
55541 res = (duk_hstring *) DUK_ALLOC(heap, sizeof(duk_hstring) + blen + 1);
55542 if (DUK_UNLIKELY(res == NULL)) {
55543 goto alloc_error;
55544 }
55545 duk_memzero(res, sizeof(duk_hstring));
55546#if defined(DUK_USE_EXPLICIT_NULL_INIT)
55548#endif
55550
55551 data_tmp = (duk_uint8_t *) (res + 1);
55552 duk_memcpy(data_tmp, str, blen);
55553 data_tmp[blen] = (duk_uint8_t) 0;
55554 data = (const duk_uint8_t *) data_tmp;
55555 }
55556
55557 DUK_HSTRING_SET_BYTELEN(res, blen);
55558 DUK_HSTRING_SET_HASH(res, strhash);
55559
55561#if defined(DUK_USE_HSTRING_ARRIDX)
55562 res->arridx = duk_js_to_arrayindex_string(data, blen);
55563 if (res->arridx != DUK_HSTRING_NO_ARRAY_INDEX) {
55564#else
55565 dummy = duk_js_to_arrayindex_string(data, blen);
55566 if (dummy != DUK_HSTRING_NO_ARRAY_INDEX) {
55567#endif
55568 /* Array index strings cannot be symbol strings,
55569 * and they're always pure ASCII so blen == clen.
55570 */
55574 } else {
55575 /* Because 'data' is NUL-terminated, we don't need a
55576 * blen > 0 check here. For NUL (0x00) the symbol
55577 * checks will be false.
55578 */
55579 if (DUK_UNLIKELY(data[0] >= 0x80U)) {
55580 if (data[0] <= 0x81) {
55582 } else if (data[0] == 0x82U || data[0] == 0xffU) {
55585 }
55586 }
55587
55588 /* Using an explicit 'ASCII' flag has larger footprint (one call site
55589 * only) but is quite useful for the case when there's no explicit
55590 * 'clen' in duk_hstring.
55591 *
55592 * The flag is set lazily for RAM strings.
55593 */
55595
55596#if defined(DUK_USE_HSTRING_LAZY_CLEN)
55597 /* Charlen initialized to 0, updated on-the-fly. */
55598#else
55599 duk_hstring_init_charlen(res); /* Also sets ASCII flag. */
55600#endif
55601 }
55602
55603 DUK_DDD(DUK_DDDPRINT("interned string, hash=0x%08lx, blen=%ld, has_arridx=%ld, has_extdata=%ld",
55604 (unsigned long) DUK_HSTRING_GET_HASH(res),
55605 (long) DUK_HSTRING_GET_BYTELEN(res),
55606 (long) (DUK_HSTRING_HAS_ARRIDX(res) ? 1 : 0),
55607 (long) (DUK_HSTRING_HAS_EXTDATA(res) ? 1 : 0)));
55608
55609 DUK_ASSERT(res != NULL);
55610 return res;
55611
55612alloc_error:
55613 return NULL;
55614}
55615
55616/*
55617 * Grow strtable allocation in-place.
55618 */
55619
55620#if defined(DUK__STRTAB_RESIZE_CHECK)
55622 duk_uint32_t new_st_size;
55623 duk_uint32_t old_st_size;
55624 duk_uint32_t i;
55625 duk_hstring *h;
55626 duk_hstring *next;
55627 duk_hstring *prev;
55628#if defined(DUK_USE_STRTAB_PTRCOMP)
55629 duk_uint16_t *new_ptr;
55630 duk_uint16_t *new_ptr_high;
55631#else
55632 duk_hstring **new_ptr;
55633 duk_hstring **new_ptr_high;
55634#endif
55635
55636 DUK_DD(DUK_DDPRINT("grow in-place: %lu -> %lu", (unsigned long) heap->st_size, (unsigned long) heap->st_size * 2));
55637
55638 DUK_ASSERT(heap != NULL);
55639 DUK_ASSERT(heap->st_resizing == 1);
55640 DUK_ASSERT(heap->st_size >= 2);
55641 DUK_ASSERT((heap->st_size & (heap->st_size - 1)) == 0); /* 2^N */
55642 DUK_ASSERT(DUK__GET_STRTABLE(heap) != NULL);
55643
55644 DUK_STATS_INC(heap, stats_strtab_resize_grow);
55645
55646 new_st_size = heap->st_size << 1U;
55647 DUK_ASSERT(new_st_size > heap->st_size); /* No overflow. */
55648
55649 /* Reallocate the strtable first and then work in-place to rehash
55650 * strings. We don't need an indirect allocation here: even if GC
55651 * is triggered to satisfy the allocation, recursive strtable resize
55652 * is prevented by flags. This is also why we don't need to use
55653 * DUK_REALLOC_INDIRECT().
55654 */
55655
55656#if defined(DUK_USE_STRTAB_PTRCOMP)
55657 new_ptr = (duk_uint16_t *) DUK_REALLOC(heap, heap->strtable16, sizeof(duk_uint16_t) * new_st_size);
55658#else
55659 new_ptr = (duk_hstring **) DUK_REALLOC(heap, heap->strtable, sizeof(duk_hstring *) * new_st_size);
55660#endif
55661 if (DUK_UNLIKELY(new_ptr == NULL)) {
55662 /* If realloc fails we can continue normally: the string table
55663 * won't "fill up" although chains will gradually get longer.
55664 * When string insertions continue, we'll quite soon try again
55665 * with no special handling.
55666 */
55667 DUK_D(DUK_DPRINT("string table grow failed, ignoring"));
55668 return;
55669 }
55670#if defined(DUK_USE_STRTAB_PTRCOMP)
55671 heap->strtable16 = new_ptr;
55672#else
55673 heap->strtable = new_ptr;
55674#endif
55675
55676 /* Rehash a single bucket into two separate ones. When we grow
55677 * by x2 the highest 'new' bit determines whether a string remains
55678 * in its old position (bit is 0) or goes to a new one (bit is 1).
55679 */
55680
55681 old_st_size = heap->st_size;
55682 new_ptr_high = new_ptr + old_st_size;
55683 for (i = 0; i < old_st_size; i++) {
55684 duk_hstring *new_root;
55685 duk_hstring *new_root_high;
55686
55687 h = DUK__HEAPPTR_DEC16(heap, new_ptr[i]);
55688 new_root = h;
55689 new_root_high = NULL;
55690
55691 prev = NULL;
55692 while (h != NULL) {
55693 duk_uint32_t mask;
55694
55695 DUK_ASSERT((DUK_HSTRING_GET_HASH(h) & heap->st_mask) == i);
55696 next = h->hdr.h_next;
55697
55698 /* Example: if previous size was 256, previous mask is 0xFF
55699 * and size is 0x100 which corresponds to the new bit that
55700 * comes into play.
55701 */
55702 DUK_ASSERT(heap->st_mask == old_st_size - 1);
55703 mask = old_st_size;
55704 if (DUK_HSTRING_GET_HASH(h) & mask) {
55705 if (prev != NULL) {
55706 prev->hdr.h_next = h->hdr.h_next;
55707 } else {
55708 DUK_ASSERT(h == new_root);
55709 new_root = h->hdr.h_next;
55710 }
55711
55712 h->hdr.h_next = new_root_high;
55713 new_root_high = h;
55714 } else {
55715 prev = h;
55716 }
55717 h = next;
55718 }
55719
55720 new_ptr[i] = DUK__HEAPPTR_ENC16(heap, new_root);
55721 new_ptr_high[i] = DUK__HEAPPTR_ENC16(heap, new_root_high);
55722 }
55723
55724 heap->st_size = new_st_size;
55725 heap->st_mask = new_st_size - 1;
55726
55727#if defined(DUK_USE_ASSERTIONS)
55728 duk__strtable_assert_checks(heap);
55729#endif
55730}
55731#endif /* DUK__STRTAB_RESIZE_CHECK */
55732
55733/*
55734 * Shrink strtable allocation in-place.
55735 */
55736
55737#if defined(DUK__STRTAB_RESIZE_CHECK)
55739 duk_uint32_t new_st_size;
55740 duk_uint32_t i;
55741 duk_hstring *h;
55742 duk_hstring *other;
55744#if defined(DUK_USE_STRTAB_PTRCOMP)
55745 duk_uint16_t *old_ptr;
55746 duk_uint16_t *old_ptr_high;
55747 duk_uint16_t *new_ptr;
55748#else
55749 duk_hstring **old_ptr;
55750 duk_hstring **old_ptr_high;
55751 duk_hstring **new_ptr;
55752#endif
55753
55754 DUK_DD(DUK_DDPRINT("shrink in-place: %lu -> %lu", (unsigned long) heap->st_size, (unsigned long) heap->st_size / 2));
55755
55756 DUK_ASSERT(heap != NULL);
55757 DUK_ASSERT(heap->st_resizing == 1);
55758 DUK_ASSERT(heap->st_size >= 2);
55759 DUK_ASSERT((heap->st_size & (heap->st_size - 1)) == 0); /* 2^N */
55760 DUK_ASSERT(DUK__GET_STRTABLE(heap) != NULL);
55761
55762 DUK_STATS_INC(heap, stats_strtab_resize_shrink);
55763
55764 new_st_size = heap->st_size >> 1U;
55765
55766 /* Combine two buckets into a single one. When we shrink, one hash
55767 * bit (highest) disappears.
55768 */
55769 old_ptr = DUK__GET_STRTABLE(heap);
55770 old_ptr_high = old_ptr + new_st_size;
55771 for (i = 0; i < new_st_size; i++) {
55772 h = DUK__HEAPPTR_DEC16(heap, old_ptr[i]);
55773 other = DUK__HEAPPTR_DEC16(heap, old_ptr_high[i]);
55774
55775 if (h == NULL) {
55776 /* First chain is empty, so use second one as is. */
55777 root = other;
55778 } else {
55779 /* Find end of first chain, and link in the second. */
55780 root = h;
55781 while (h->hdr.h_next != NULL) {
55782 h = h->hdr.h_next;
55783 }
55784 h->hdr.h_next = other;
55785 }
55786
55787 old_ptr[i] = DUK__HEAPPTR_ENC16(heap, root);
55788 }
55789
55790 heap->st_size = new_st_size;
55791 heap->st_mask = new_st_size - 1;
55792
55793 /* The strtable is now consistent and we can realloc safely. Even
55794 * if side effects cause string interning or removal the strtable
55795 * updates are safe. Recursive resize has been prevented by caller.
55796 * This is also why we don't need to use DUK_REALLOC_INDIRECT().
55797 *
55798 * We assume a realloc() to a smaller size is guaranteed to succeed.
55799 * It would be relatively straightforward to handle the error by
55800 * essentially performing a "grow" step to recover.
55801 */
55802
55803#if defined(DUK_USE_STRTAB_PTRCOMP)
55804 new_ptr = (duk_uint16_t *) DUK_REALLOC(heap, heap->strtable16, sizeof(duk_uint16_t) * new_st_size);
55805 DUK_ASSERT(new_ptr != NULL);
55806 heap->strtable16 = new_ptr;
55807#else
55808 new_ptr = (duk_hstring **) DUK_REALLOC(heap, heap->strtable, sizeof(duk_hstring *) * new_st_size);
55809 DUK_ASSERT(new_ptr != NULL);
55810 heap->strtable = new_ptr;
55811#endif
55812
55813#if defined(DUK_USE_ASSERTIONS)
55814 duk__strtable_assert_checks(heap);
55815#endif
55816}
55817#endif /* DUK__STRTAB_RESIZE_CHECK */
55818
55819/*
55820 * Grow/shrink check.
55821 */
55822
55823#if defined(DUK__STRTAB_RESIZE_CHECK)
55825 duk_uint32_t load_factor; /* fixed point */
55826
55827 DUK_ASSERT(heap != NULL);
55828#if defined(DUK_USE_STRTAB_PTRCOMP)
55829 DUK_ASSERT(heap->strtable16 != NULL);
55830#else
55831 DUK_ASSERT(heap->strtable != NULL);
55832#endif
55833
55834 DUK_STATS_INC(heap, stats_strtab_resize_check);
55835
55836 /* Prevent recursive resizing. */
55837 if (DUK_UNLIKELY(heap->st_resizing != 0U)) {
55838 DUK_D(DUK_DPRINT("prevent recursive strtable resize"));
55839 return;
55840 }
55841
55842 heap->st_resizing = 1;
55843
55844 DUK_ASSERT(heap->st_size >= 16U);
55845 DUK_ASSERT((heap->st_size >> 4U) >= 1);
55846 load_factor = heap->st_count / (heap->st_size >> 4U);
55847
55848 DUK_DD(DUK_DDPRINT("resize check string table: size=%lu, count=%lu, load_factor=%lu (fixed point .4; float %lf)",
55849 (unsigned long) heap->st_size,
55850 (unsigned long) heap->st_count,
55851 (unsigned long) load_factor,
55852 (double) heap->st_count / (double) heap->st_size));
55853
55854 if (load_factor >= DUK_USE_STRTAB_GROW_LIMIT) {
55855 if (heap->st_size >= DUK_USE_STRTAB_MAXSIZE) {
55856 DUK_DD(DUK_DDPRINT("want to grow strtable (based on load factor) but already maximum size"));
55857 } else {
55858 DUK_D(DUK_DPRINT("grow string table: %lu -> %lu",
55859 (unsigned long) heap->st_size,
55860 (unsigned long) heap->st_size * 2));
55861#if defined(DUK_USE_DEBUG)
55862 duk_heap_strtable_dump(heap);
55863#endif
55865 }
55866 } else if (load_factor <= DUK_USE_STRTAB_SHRINK_LIMIT) {
55867 if (heap->st_size <= DUK_USE_STRTAB_MINSIZE) {
55868 DUK_DD(DUK_DDPRINT("want to shrink strtable (based on load factor) but already minimum size"));
55869 } else {
55870 DUK_D(DUK_DPRINT("shrink string table: %lu -> %lu",
55871 (unsigned long) heap->st_size,
55872 (unsigned long) heap->st_size / 2));
55873#if defined(DUK_USE_DEBUG)
55874 duk_heap_strtable_dump(heap);
55875#endif
55877 }
55878 } else {
55879 DUK_DD(DUK_DDPRINT("no need for strtable resize"));
55880 }
55881
55882 heap->st_resizing = 0;
55883}
55884#endif /* DUK__STRTAB_RESIZE_CHECK */
55885
55886/*
55887 * Torture grow/shrink: unconditionally grow and shrink back.
55888 */
55889
55890#if defined(DUK_USE_STRTAB_TORTURE) && defined(DUK__STRTAB_RESIZE_CHECK)
55891DUK_LOCAL void duk__strtable_resize_torture(duk_heap *heap) {
55892 duk_uint32_t old_st_size;
55894 DUK_ASSERT(heap != NULL);
55895
55896 old_st_size = heap->st_size;
55897 if (old_st_size >= DUK_USE_STRTAB_MAXSIZE) {
55898 return;
55899 }
55900
55901 heap->st_resizing = 1;
55903 if (heap->st_size > old_st_size) {
55905 }
55906 heap->st_resizing = 0;
55907}
55908#endif /* DUK_USE_STRTAB_TORTURE && DUK__STRTAB_RESIZE_CHECK */
55909
55910/*
55911 * Raw intern; string already checked not to be present.
55912 */
55913
55914DUK_LOCAL duk_hstring *duk__strtable_do_intern(duk_heap *heap, const duk_uint8_t *str, duk_uint32_t blen, duk_uint32_t strhash) {
55915 duk_hstring *res;
55916 const duk_uint8_t *extdata;
55917#if defined(DUK_USE_STRTAB_PTRCOMP)
55918 duk_uint16_t *slot;
55919#else
55920 duk_hstring **slot;
55921#endif
55922
55923 DUK_DDD(DUK_DDDPRINT("do_intern: heap=%p, str=%p, blen=%lu, strhash=%lx, st_size=%lu, st_count=%lu, load=%lf",
55924 (void *) heap,
55925 (const void *) str,
55926 (unsigned long) blen,
55927 (unsigned long) strhash,
55928 (unsigned long) heap->st_size,
55929 (unsigned long) heap->st_count,
55930 (double) heap->st_count / (double) heap->st_size));
55931
55932 DUK_ASSERT(heap != NULL);
55933
55934 /* Prevent any side effects on the string table and the caller provided
55935 * str/blen arguments while interning is in progress. For example, if
55936 * the caller provided str/blen from a dynamic buffer, a finalizer
55937 * might resize or modify that dynamic buffer, invalidating the call
55938 * arguments.
55939 *
55940 * While finalizers must be prevented, mark-and-sweep itself is fine.
55941 * Recursive string table resize is prevented explicitly here.
55942 */
55943
55944 heap->pf_prevent_count++;
55945 DUK_ASSERT(heap->pf_prevent_count != 0); /* Wrap. */
55946
55947#if defined(DUK_USE_STRTAB_TORTURE) && defined(DUK__STRTAB_RESIZE_CHECK)
55948 duk__strtable_resize_torture(heap);
55949#endif
55950
55951 /* String table grow/shrink check. Because of chaining (and no
55952 * accumulation issues as with hash probe chains and DELETED
55953 * markers) there's never a mandatory need to resize right now.
55954 * Check for the resize only periodically, based on st_count
55955 * bit pattern. Because string table removal doesn't do a shrink
55956 * check, we do that also here.
55957 *
55958 * Do the resize and possible grow/shrink before the new duk_hstring
55959 * has been allocated. Otherwise we may trigger a GC when the result
55960 * duk_hstring is not yet strongly referenced.
55961 */
55962
55963#if defined(DUK__STRTAB_RESIZE_CHECK)
55964 if (DUK_UNLIKELY((heap->st_count & DUK_USE_STRTAB_RESIZE_CHECK_MASK) == 0)) {
55966 }
55967#endif
55968
55969 /* External string check (low memory optimization). */
55970
55971#if defined(DUK_USE_HSTRING_EXTDATA) && defined(DUK_USE_EXTSTR_INTERN_CHECK)
55972 extdata =
55973 (const duk_uint8_t *) DUK_USE_EXTSTR_INTERN_CHECK(heap->heap_udata, (void *) DUK_LOSE_CONST(str), (duk_size_t) blen);
55974#else
55975 extdata = (const duk_uint8_t *) NULL;
55976#endif
55977
55978 /* Allocate and initialize string, not yet linked. This may cause a
55979 * GC which may cause other strings to be interned and inserted into
55980 * the string table before we insert our string. Finalizer execution
55981 * is disabled intentionally to avoid a finalizer from e.g. resizing
55982 * a buffer used as a data area for 'str'.
55983 */
55984
55985 res = duk__strtable_alloc_hstring(heap, str, blen, strhash, extdata);
55986
55987 /* Allow side effects again: GC must be avoided until duk_hstring
55988 * result (if successful) has been INCREF'd.
55989 */
55990 DUK_ASSERT(heap->pf_prevent_count > 0);
55991 heap->pf_prevent_count--;
55992
55993 /* Alloc error handling. */
55994
55995 if (DUK_UNLIKELY(res == NULL)) {
55996#if defined(DUK_USE_HSTRING_EXTDATA) && defined(DUK_USE_EXTSTR_INTERN_CHECK)
55997 if (extdata != NULL) {
55998 DUK_USE_EXTSTR_FREE(heap->heap_udata, (const void *) extdata);
55999 }
56000#endif
56001 return NULL;
56002 }
56003
56004 /* Insert into string table. */
56005
56006#if defined(DUK_USE_STRTAB_PTRCOMP)
56007 slot = heap->strtable16 + (strhash & heap->st_mask);
56008#else
56009 slot = heap->strtable + (strhash & heap->st_mask);
56010#endif
56011 DUK_ASSERT(res->hdr.h_next == NULL); /* This is the case now, but unnecessary zeroing/NULLing. */
56012 res->hdr.h_next = DUK__HEAPPTR_DEC16(heap, *slot);
56013 *slot = DUK__HEAPPTR_ENC16(heap, res);
56014
56015 /* Update string count only for successful inserts. */
56016
56017#if defined(DUK__STRTAB_RESIZE_CHECK)
56018 heap->st_count++;
56019#endif
56020
56021 /* The duk_hstring is in the string table but is not yet strongly
56022 * reachable. Calling code MUST NOT make any allocations or other
56023 * side effects before the duk_hstring has been INCREF'd and made
56024 * reachable.
56025 */
56026
56027 return res;
56028}
56029
56030/*
56031 * Intern a string from str/blen, returning either an existing duk_hstring
56032 * or adding a new one into the string table. The input string does -not-
56033 * need to be NUL terminated.
56034 *
56035 * The input 'str' argument may point to a Duktape managed data area such as
56036 * the data area of a dynamic buffer. It's crucial to avoid any side effects
56037 * that might affect the data area (e.g. resize the dynamic buffer, or write
56038 * to the buffer) before the string is fully interned.
56039 */
56040
56041#if defined(DUK_USE_ROM_STRINGS)
56042DUK_LOCAL duk_hstring *duk__strtab_romstring_lookup(duk_heap *heap, const duk_uint8_t *str, duk_size_t blen, duk_uint32_t strhash) {
56043 duk_size_t lookup_hash;
56044 duk_hstring *curr;
56045
56046 DUK_ASSERT(heap != NULL);
56047 DUK_UNREF(heap);
56048
56049 lookup_hash = (blen << 4);
56050 if (blen > 0) {
56051 lookup_hash += str[0];
56053 lookup_hash &= 0xff;
56054
56055 curr = (duk_hstring *) DUK_LOSE_CONST(duk_rom_strings_lookup[lookup_hash]);
56056 while (curr != NULL) {
56057 /* Unsafe memcmp() because for zero blen, str may be NULL. */
56058 if (strhash == DUK_HSTRING_GET_HASH(curr) && blen == DUK_HSTRING_GET_BYTELEN(curr) &&
56059 duk_memcmp_unsafe((const void *) str, (const void *) DUK_HSTRING_GET_DATA(curr), blen) == 0) {
56060 DUK_DDD(DUK_DDDPRINT("intern check: rom string: %!O, computed hash 0x%08lx, rom hash 0x%08lx",
56061 curr,
56062 (unsigned long) strhash,
56063 (unsigned long) DUK_HSTRING_GET_HASH(curr)));
56064 return curr;
56065 }
56066 curr = curr->hdr.h_next;
56067 }
56068
56069 return NULL;
56070}
56071#endif /* DUK_USE_ROM_STRINGS */
56072
56073DUK_INTERNAL duk_hstring *duk_heap_strtable_intern(duk_heap *heap, const duk_uint8_t *str, duk_uint32_t blen) {
56074 duk_uint32_t strhash;
56075 duk_hstring *h;
56076
56077 DUK_DDD(DUK_DDDPRINT("intern check: heap=%p, str=%p, blen=%lu", (void *) heap, (const void *) str, (unsigned long) blen));
56078
56079 /* Preliminaries. */
56080
56081 /* XXX: maybe just require 'str != NULL' even for zero size? */
56082 DUK_ASSERT(heap != NULL);
56083 DUK_ASSERT(blen == 0 || str != NULL);
56084 DUK_ASSERT(blen <= DUK_HSTRING_MAX_BYTELEN); /* Caller is responsible for ensuring this. */
56085 strhash = duk_heap_hashstring(heap, str, (duk_size_t) blen);
56086
56087 /* String table lookup. */
56088
56089 DUK_ASSERT(DUK__GET_STRTABLE(heap) != NULL);
56090 DUK_ASSERT(heap->st_size > 0);
56091 DUK_ASSERT(heap->st_size == heap->st_mask + 1);
56092#if defined(DUK_USE_STRTAB_PTRCOMP)
56093 h = DUK__HEAPPTR_DEC16(heap, heap->strtable16[strhash & heap->st_mask]);
56094#else
56095 h = heap->strtable[strhash & heap->st_mask];
56096#endif
56097 while (h != NULL) {
56098 if (DUK_HSTRING_GET_HASH(h) == strhash && DUK_HSTRING_GET_BYTELEN(h) == blen &&
56099 duk_memcmp_unsafe((const void *) str, (const void *) DUK_HSTRING_GET_DATA(h), (size_t) blen) == 0) {
56100 /* Found existing entry. */
56101 DUK_STATS_INC(heap, stats_strtab_intern_hit);
56102 return h;
56103 }
56104 h = h->hdr.h_next;
56105 }
56106
56107 /* ROM table lookup. Because this lookup is slower, do it only after
56108 * RAM lookup. This works because no ROM string is ever interned into
56109 * the RAM string table.
56110 */
56111
56112#if defined(DUK_USE_ROM_STRINGS)
56113 h = duk__strtab_romstring_lookup(heap, str, blen, strhash);
56114 if (h != NULL) {
56115 DUK_STATS_INC(heap, stats_strtab_intern_hit);
56116 return h;
56117 }
56118#endif
56119
56120 /* Not found in string table; insert. */
56121
56122 DUK_STATS_INC(heap, stats_strtab_intern_miss);
56123 h = duk__strtable_do_intern(heap, str, blen, strhash);
56124 return h; /* may be NULL */
56125}
56126
56127/*
56128 * Intern a string from u32.
56129 */
56130
56131/* XXX: Could arrange some special handling because we know that the result
56132 * will have an arridx flag and an ASCII flag, won't need a clen check, etc.
56133 */
56134
56136 duk_uint8_t buf[DUK__STRTAB_U32_MAX_STRLEN];
56137 duk_uint8_t *p;
56138
56139 DUK_ASSERT(heap != NULL);
56140
56141 /* This is smaller and faster than a %lu sprintf. */
56142 p = buf + sizeof(buf);
56143 do {
56144 p--;
56145 *p = duk_lc_digits[val % 10];
56146 val = val / 10;
56147 } while (val != 0); /* For val == 0, emit exactly one '0'. */
56148 DUK_ASSERT(p >= buf);
56149
56150 return duk_heap_strtable_intern(heap, (const duk_uint8_t *) p, (duk_uint32_t) ((buf + sizeof(buf)) - p));
56151}
56152
56153/*
56154 * Checked convenience variants.
56155 *
56156 * XXX: Because the main use case is for the checked variants, make them the
56157 * main functionality and provide a safe variant separately (it is only needed
56158 * during heap init). The problem with that is that longjmp state and error
56159 * creation must already be possible to throw.
56160 */
56161
56162DUK_INTERNAL duk_hstring *duk_heap_strtable_intern_checked(duk_hthread *thr, const duk_uint8_t *str, duk_uint32_t blen) {
56163 duk_hstring *res;
56164
56165 DUK_ASSERT(thr != NULL);
56166 DUK_ASSERT(thr->heap != NULL);
56167 DUK_ASSERT(blen == 0 || str != NULL);
56168
56169 res = duk_heap_strtable_intern(thr->heap, str, blen);
56170 if (DUK_UNLIKELY(res == NULL)) {
56172 DUK_WO_NORETURN(return NULL;);
56173 }
56174 return res;
56175}
56176
56177#if defined(DUK_USE_LITCACHE_SIZE)
56178DUK_LOCAL duk_uint_t duk__strtable_litcache_key(const duk_uint8_t *str, duk_uint32_t blen) {
56179 duk_uintptr_t key;
56180
56183
56184 key = (duk_uintptr_t) blen ^ (duk_uintptr_t) str;
56185 key &= (duk_uintptr_t) (DUK_USE_LITCACHE_SIZE - 1); /* Assumes size is power of 2. */
56186 /* Due to masking, cast is in 32-bit range. */
56187 DUK_ASSERT(key <= DUK_UINT_MAX);
56188 return (duk_uint_t) key;
56189}
56190
56191DUK_INTERNAL duk_hstring *duk_heap_strtable_intern_literal_checked(duk_hthread *thr, const duk_uint8_t *str, duk_uint32_t blen) {
56192 duk_uint_t key;
56193 duk_litcache_entry *ent;
56194 duk_hstring *h;
56195
56196 /* Fast path check: literal exists in literal cache. */
56197 key = duk__strtable_litcache_key(str, blen);
56198 ent = thr->heap->litcache + key;
56199 if (ent->addr == str) {
56200 DUK_DD(DUK_DDPRINT("intern check for cached, pinned literal: str=%p, blen=%ld -> duk_hstring %!O",
56201 (const void *) str,
56202 (long) blen,
56203 (duk_heaphdr *) ent->h));
56204 DUK_ASSERT(ent->h != NULL);
56206 DUK_STATS_INC(thr->heap, stats_strtab_litcache_hit);
56207 return ent->h;
56208 }
56209
56210 /* Intern and update (overwrite) cache entry. */
56211 h = duk_heap_strtable_intern_checked(thr, str, blen);
56212 ent->addr = str;
56213 ent->h = h;
56214 DUK_STATS_INC(thr->heap, stats_strtab_litcache_miss);
56215
56216 /* Pin the duk_hstring until the next mark-and-sweep. This means
56217 * litcache entries don't need to be invalidated until the next
56218 * mark-and-sweep as their target duk_hstring is not freed before
56219 * the mark-and-sweep happens. The pin remains even if the literal
56220 * cache entry is overwritten, and is still useful to avoid string
56221 * table traffic.
56222 */
56224 DUK_DD(DUK_DDPRINT("pin duk_hstring because it is a literal: %!O", (duk_heaphdr *) h));
56226 DUK_HSTRING_INCREF(thr, h);
56228 DUK_STATS_INC(thr->heap, stats_strtab_litcache_pin);
56229 }
56230
56231 return h;
56232}
56233#endif /* DUK_USE_LITCACHE_SIZE */
56234
56236 duk_hstring *res;
56238 DUK_ASSERT(thr != NULL);
56239 DUK_ASSERT(thr->heap != NULL);
56240
56241 res = duk_heap_strtable_intern_u32(thr->heap, val);
56242 if (DUK_UNLIKELY(res == NULL)) {
56244 DUK_WO_NORETURN(return NULL;);
56245 }
56246 return res;
56247}
56248
56249/*
56250 * Remove (unlink) a string from the string table.
56251 *
56252 * Just unlinks the duk_hstring, leaving link pointers as garbage.
56253 * Caller must free the string itself.
56254 */
56255
56256#if defined(DUK_USE_REFERENCE_COUNTING)
56257/* Unlink without a 'prev' pointer. */
56259#if defined(DUK_USE_STRTAB_PTRCOMP)
56260 duk_uint16_t *slot;
56261#else
56262 duk_hstring **slot;
56263#endif
56264 duk_hstring *other;
56265 duk_hstring *prev;
56266
56267 DUK_DDD(DUK_DDDPRINT("remove: heap=%p, h=%p, blen=%lu, strhash=%lx",
56268 (void *) heap,
56269 (void *) h,
56270 (unsigned long) (h != NULL ? DUK_HSTRING_GET_BYTELEN(h) : 0),
56271 (unsigned long) (h != NULL ? DUK_HSTRING_GET_HASH(h) : 0)));
56272
56273 DUK_ASSERT(heap != NULL);
56274 DUK_ASSERT(h != NULL);
56275
56276#if defined(DUK__STRTAB_RESIZE_CHECK)
56277 DUK_ASSERT(heap->st_count > 0);
56278 heap->st_count--;
56279#endif
56280
56281#if defined(DUK_USE_STRTAB_PTRCOMP)
56282 slot = heap->strtable16 + (DUK_HSTRING_GET_HASH(h) & heap->st_mask);
56283#else
56284 slot = heap->strtable + (DUK_HSTRING_GET_HASH(h) & heap->st_mask);
56285#endif
56286 other = DUK__HEAPPTR_DEC16(heap, *slot);
56287 DUK_ASSERT(other != NULL); /* At least argument string is in the chain. */
56288
56289 prev = NULL;
56290 while (other != h) {
56291 prev = other;
56292 other = other->hdr.h_next;
56293 DUK_ASSERT(other != NULL); /* We'll eventually find 'h'. */
56294 }
56295 if (prev != NULL) {
56296 /* Middle of list. */
56297 prev->hdr.h_next = h->hdr.h_next;
56298 } else {
56299 /* Head of list. */
56300 *slot = DUK__HEAPPTR_ENC16(heap, h->hdr.h_next);
56301 }
56302
56303 /* There's no resize check on a string free. The next string
56304 * intern will do one.
56305 */
56306}
56307#endif /* DUK_USE_REFERENCE_COUNTING */
56308
56309/* Unlink with a 'prev' pointer. */
56311#if defined(DUK_USE_STRTAB_PTRCOMP)
56312 duk_uint16_t *slot;
56313#else
56314 duk_hstring **slot;
56315#endif
56316
56317 DUK_DDD(DUK_DDDPRINT("remove: heap=%p, prev=%p, h=%p, blen=%lu, strhash=%lx",
56318 (void *) heap,
56319 (void *) prev,
56320 (void *) h,
56321 (unsigned long) (h != NULL ? DUK_HSTRING_GET_BYTELEN(h) : 0),
56322 (unsigned long) (h != NULL ? DUK_HSTRING_GET_HASH(h) : 0)));
56323
56324 DUK_ASSERT(heap != NULL);
56325 DUK_ASSERT(h != NULL);
56326 DUK_ASSERT(prev == NULL || prev->hdr.h_next == h);
56327
56328#if defined(DUK__STRTAB_RESIZE_CHECK)
56329 DUK_ASSERT(heap->st_count > 0);
56330 heap->st_count--;
56331#endif
56332
56333 if (prev != NULL) {
56334 /* Middle of list. */
56335 prev->hdr.h_next = h->hdr.h_next;
56336 } else {
56337 /* Head of list. */
56338#if defined(DUK_USE_STRTAB_PTRCOMP)
56339 slot = heap->strtable16 + (DUK_HSTRING_GET_HASH(h) & heap->st_mask);
56340#else
56341 slot = heap->strtable + (DUK_HSTRING_GET_HASH(h) & heap->st_mask);
56342#endif
56343 DUK_ASSERT(DUK__HEAPPTR_DEC16(heap, *slot) == h);
56344 *slot = DUK__HEAPPTR_ENC16(heap, h->hdr.h_next);
56345 }
56346}
56347
56348/*
56349 * Force string table resize check in mark-and-sweep.
56350 */
56351
56353 /* Does only one grow/shrink step if needed. The heap->st_resizing
56354 * flag protects against recursive resizing.
56355 */
56356
56357 DUK_ASSERT(heap != NULL);
56358 DUK_UNREF(heap);
56359
56360#if defined(DUK__STRTAB_RESIZE_CHECK)
56361#if defined(DUK_USE_STRTAB_PTRCOMP)
56362 if (heap->strtable16 != NULL) {
56363#else
56364 if (heap->strtable != NULL) {
56365#endif
56367 }
56368#endif
56369}
56370
56371/*
56372 * Free strings in the string table and the string table itself.
56373 */
56374
56376#if defined(DUK_USE_STRTAB_PTRCOMP)
56377 duk_uint16_t *strtable;
56378 duk_uint16_t *st;
56379#else
56380 duk_hstring **strtable;
56381 duk_hstring **st;
56382#endif
56383 duk_hstring *h;
56384
56385 DUK_ASSERT(heap != NULL);
56386
56387#if defined(DUK_USE_ASSERTIONS)
56388 duk__strtable_assert_checks(heap);
56389#endif
56390
56391 /* Strtable can be NULL if heap init fails. However, in that case
56392 * heap->st_size is 0, so strtable == strtable_end and we skip the
56393 * loop without a special check.
56394 */
56395 strtable = DUK__GET_STRTABLE(heap);
56396 st = strtable + heap->st_size;
56397 DUK_ASSERT(strtable != NULL || heap->st_size == 0);
56398
56399 while (strtable != st) {
56400 --st;
56401 h = DUK__HEAPPTR_DEC16(heap, *st);
56402 while (h) {
56403 duk_hstring *h_next;
56404 h_next = h->hdr.h_next;
56405
56406 /* Strings may have inner refs (extdata) in some cases. */
56407 duk_free_hstring(heap, h);
56408
56409 h = h_next;
56410 }
56411 }
56412
56413 DUK_FREE(heap, strtable);
56414}
56415
56416/* automatic undefs */
56417#undef DUK__GET_STRTABLE
56418#undef DUK__HEAPPTR_DEC16
56419#undef DUK__HEAPPTR_ENC16
56420#undef DUK__STRTAB_U32_MAX_STRLEN
56421/*
56422 * duk_heaphdr assertion helpers
56423 */
56424
56425/* #include duk_internal.h -> already included */
56426
56427#if defined(DUK_USE_ASSERTIONS)
56428
56429#if defined(DUK_USE_DOUBLE_LINKED_HEAP)
56430DUK_INTERNAL void duk_heaphdr_assert_links(duk_heap *heap, duk_heaphdr *h) {
56431 DUK_UNREF(heap);
56432 if (h != NULL) {
56433 duk_heaphdr *h_prev, *h_next;
56434 h_prev = DUK_HEAPHDR_GET_PREV(heap, h);
56435 h_next = DUK_HEAPHDR_GET_NEXT(heap, h);
56436 DUK_ASSERT(h_prev == NULL || (DUK_HEAPHDR_GET_NEXT(heap, h_prev) == h));
56437 DUK_ASSERT(h_next == NULL || (DUK_HEAPHDR_GET_PREV(heap, h_next) == h));
56438 }
56439}
56440#else
56441DUK_INTERNAL void duk_heaphdr_assert_links(duk_heap *heap, duk_heaphdr *h) {
56442 DUK_UNREF(heap);
56443 DUK_UNREF(h);
56444}
56445#endif
56446
56447DUK_INTERNAL void duk_heaphdr_assert_valid(duk_heaphdr *h) {
56448 DUK_ASSERT(h != NULL);
56450}
56451
56452/* Assert validity of a heaphdr, including all subclasses. */
56453DUK_INTERNAL void duk_heaphdr_assert_valid_subclassed(duk_heaphdr *h) {
56454 switch (DUK_HEAPHDR_GET_TYPE(h)) {
56455 case DUK_HTYPE_OBJECT: {
56456 duk_hobject *h_obj = (duk_hobject *) h;
56458 if (DUK_HOBJECT_IS_COMPFUNC(h_obj)) {
56460 } else if (DUK_HOBJECT_IS_NATFUNC(h_obj)) {
56462 } else if (DUK_HOBJECT_IS_DECENV(h_obj)) {
56464 } else if (DUK_HOBJECT_IS_OBJENV(h_obj)) {
56466 } else if (DUK_HOBJECT_IS_BUFOBJ(h_obj)) {
56467#if defined(DUK_USE_BUFFEROBJECT_SUPPORT)
56469#endif
56470 } else if (DUK_HOBJECT_IS_BOUNDFUNC(h_obj)) {
56472 } else if (DUK_HOBJECT_IS_PROXY(h_obj)) {
56474 } else if (DUK_HOBJECT_IS_THREAD(h_obj)) {
56476 } else {
56477 /* Just a plain object. */
56478 ;
56479 }
56480 break;
56481 }
56482 case DUK_HTYPE_STRING: {
56483 duk_hstring *h_str = (duk_hstring *) h;
56485 break;
56486 }
56487 case DUK_HTYPE_BUFFER: {
56488 duk_hbuffer *h_buf = (duk_hbuffer *) h;
56490 break;
56491 }
56492 default: {
56493 DUK_ASSERT(0);
56494 }
56495 }
56497
56498#endif /* DUK_USE_ASSERTIONS */
56499/*
56500 * Hobject allocation.
56501 *
56502 * Provides primitive allocation functions for all object types (plain object,
56503 * compiled function, native function, thread). The object return is not yet
56504 * in "heap allocated" list and has a refcount of zero, so caller must careful.
56505 */
56506
56507/* XXX: In most cases there's no need for plain allocation without pushing
56508 * to the value stack. Maybe rework contract?
56509 */
56510
56511/* #include duk_internal.h -> already included */
56512
56513/*
56514 * Helpers.
56515 */
56516
56517DUK_LOCAL void duk__init_object_parts(duk_heap *heap, duk_uint_t hobject_flags, duk_hobject *obj) {
56518 DUK_ASSERT(obj != NULL);
56519 /* Zeroed by caller. */
56520
56521 obj->hdr.h_flags = hobject_flags | DUK_HTYPE_OBJECT;
56522 DUK_ASSERT(DUK_HEAPHDR_GET_TYPE(&obj->hdr) == DUK_HTYPE_OBJECT); /* Assume zero shift. */
56523
56524#if defined(DUK_USE_EXPLICIT_NULL_INIT)
56525 DUK_HOBJECT_SET_PROTOTYPE(heap, obj, NULL);
56526 DUK_HOBJECT_SET_PROPS(heap, obj, NULL);
56527#endif
56528#if defined(DUK_USE_HEAPPTR16)
56529 /* Zero encoded pointer is required to match NULL. */
56530 DUK_HEAPHDR_SET_NEXT(heap, &obj->hdr, NULL);
56531#if defined(DUK_USE_DOUBLE_LINKED_HEAP)
56532 DUK_HEAPHDR_SET_PREV(heap, &obj->hdr, NULL);
56533#endif
56534#endif
56535 DUK_HEAPHDR_ASSERT_LINKS(heap, &obj->hdr);
56537
56538 /* obj->props is intentionally left as NULL, and duk_hobject_props.c must deal
56539 * with this properly. This is intentional: empty objects consume a minimum
56540 * amount of memory. Further, an initial allocation might fail and cause
56541 * 'obj' to "leak" (require a mark-and-sweep) since it is not reachable yet.
56542 */
56543}
56545DUK_LOCAL void *duk__hobject_alloc_init(duk_hthread *thr, duk_uint_t hobject_flags, duk_size_t size) {
56546 void *res;
56547
56548 res = (void *) DUK_ALLOC_CHECKED_ZEROED(thr, size);
56549 DUK_ASSERT(res != NULL);
56550 duk__init_object_parts(thr->heap, hobject_flags, (duk_hobject *) res);
56551 return res;
56552}
56553
56554/*
56555 * Allocate an duk_hobject.
56556 *
56557 * The allocated object has no allocation for properties; the caller may
56558 * want to force a resize if a desired size is known.
56559 *
56560 * The allocated object has zero reference count and is not reachable.
56561 * The caller MUST make the object reachable and increase its reference
56562 * count before invoking any operation that might require memory allocation.
56563 */
56564
56567
56568 DUK_ASSERT(heap != NULL);
56569
56570 /* different memory layout, alloc size, and init */
56571 DUK_ASSERT((hobject_flags & DUK_HOBJECT_FLAG_COMPFUNC) == 0);
56572 DUK_ASSERT((hobject_flags & DUK_HOBJECT_FLAG_NATFUNC) == 0);
56574
56575 res = (duk_hobject *) DUK_ALLOC_ZEROED(heap, sizeof(duk_hobject));
56576 if (DUK_UNLIKELY(res == NULL)) {
56577 return NULL;
56578 }
56580
56581 duk__init_object_parts(heap, hobject_flags, res);
56582
56584 return res;
56585}
56586
56588 duk_hobject *res;
56589
56590 res = (duk_hobject *) duk__hobject_alloc_init(thr, hobject_flags, sizeof(duk_hobject));
56591 return res;
56593
56595 duk_hcompfunc *res;
56596
56597 res = (duk_hcompfunc *) duk__hobject_alloc_init(thr, hobject_flags, sizeof(duk_hcompfunc));
56598#if defined(DUK_USE_EXPLICIT_NULL_INIT)
56599#if defined(DUK_USE_HEAPPTR16)
56600 /* NULL pointer is required to encode to zero, so memset is enough. */
56601#else
56602 res->data = NULL;
56603 res->funcs = NULL;
56604 res->bytecode = NULL;
56605#endif
56606 res->lex_env = NULL;
56607 res->var_env = NULL;
56608#endif
56609
56610 return res;
56611}
56612
56614 duk_hnatfunc *res;
56615
56616 res = (duk_hnatfunc *) duk__hobject_alloc_init(thr, hobject_flags, sizeof(duk_hnatfunc));
56617#if defined(DUK_USE_EXPLICIT_NULL_INIT)
56618 res->func = NULL;
56619#endif
56620
56621 return res;
56622}
56623
56626
56627 res = (duk_hboundfunc *) DUK_ALLOC(heap, sizeof(duk_hboundfunc));
56628 if (!res) {
56629 return NULL;
56630 }
56631 duk_memzero(res, sizeof(duk_hboundfunc));
56632
56633 duk__init_object_parts(heap, hobject_flags, &res->obj);
56634
56637
56638#if defined(DUK_USE_EXPLICIT_NULL_INIT)
56639 res->args = NULL;
56640#endif
56641
56642 return res;
56643}
56644
56645#if defined(DUK_USE_BUFFEROBJECT_SUPPORT)
56647 duk_hbufobj *res;
56648
56649 res = (duk_hbufobj *) duk__hobject_alloc_init(thr, hobject_flags, sizeof(duk_hbufobj));
56650#if defined(DUK_USE_EXPLICIT_NULL_INIT)
56651 res->buf = NULL;
56652 res->buf_prop = NULL;
56653#endif
56654
56656 return res;
56657}
56658#endif /* DUK_USE_BUFFEROBJECT_SUPPORT */
56659
56660/* Allocate a new thread.
56661 *
56662 * Leaves the built-ins array uninitialized. The caller must either
56663 * initialize a new global context or share existing built-ins from
56664 * another thread.
56665 */
56667 duk_hthread *res;
56668
56669 res = (duk_hthread *) DUK_ALLOC(heap, sizeof(duk_hthread));
56670 if (DUK_UNLIKELY(res == NULL)) {
56671 return NULL;
56672 }
56673 duk_memzero(res, sizeof(duk_hthread));
56674
56675 duk__init_object_parts(heap, hobject_flags, &res->obj);
56676
56677#if defined(DUK_USE_EXPLICIT_NULL_INIT)
56678 res->ptr_curr_pc = NULL;
56679 res->heap = NULL;
56680 res->valstack = NULL;
56681 res->valstack_end = NULL;
56682 res->valstack_alloc_end = NULL;
56683 res->valstack_bottom = NULL;
56684 res->valstack_top = NULL;
56685 res->callstack_curr = NULL;
56686 res->resumer = NULL;
56687 res->compile_ctx = NULL,
56688#if defined(DUK_USE_HEAPPTR16)
56689 res->strs16 = NULL;
56690#else
56691 res->strs = NULL;
56692#endif
56693 {
56695 for (i = 0; i < DUK_NUM_BUILTINS; i++) {
56696 res->builtins[i] = NULL;
56697 }
56698 }
56699#endif
56700 /* When nothing is running, API calls are in non-strict mode. */
56701 DUK_ASSERT(res->strict == 0);
56702
56703 res->heap = heap;
56704
56705 /* XXX: Any reason not to merge duk_hthread_alloc.c here? */
56706 return res;
56707}
56708
56710 duk_hthread *res;
56711
56712 res = duk_hthread_alloc_unchecked(thr->heap, hobject_flags);
56713 if (res == NULL) {
56715 DUK_WO_NORETURN(return NULL;);
56716 }
56717 return res;
56718}
56719
56721 duk_harray *res;
56722
56723 res = (duk_harray *) duk__hobject_alloc_init(thr, hobject_flags, sizeof(duk_harray));
56724
56725 DUK_ASSERT(res->length == 0);
56726
56727 return res;
56728}
56729
56731 duk_hdecenv *res;
56732
56733 res = (duk_hdecenv *) duk__hobject_alloc_init(thr, hobject_flags, sizeof(duk_hdecenv));
56734#if defined(DUK_USE_EXPLICIT_NULL_INIT)
56735 res->thread = NULL;
56736 res->varmap = NULL;
56737#endif
56739 DUK_ASSERT(res->thread == NULL);
56740 DUK_ASSERT(res->varmap == NULL);
56741 DUK_ASSERT(res->regbase_byteoff == 0);
56742
56743 return res;
56744}
56745
56747 duk_hobjenv *res;
56748
56749 res = (duk_hobjenv *) duk__hobject_alloc_init(thr, hobject_flags, sizeof(duk_hobjenv));
56750#if defined(DUK_USE_EXPLICIT_NULL_INIT)
56751 res->target = NULL;
56752#endif
56753
56754 DUK_ASSERT(res->target == NULL);
56755
56756 return res;
56757}
56758
56760 duk_hproxy *res;
56761
56762 res = (duk_hproxy *) duk__hobject_alloc_init(thr, hobject_flags, sizeof(duk_hproxy));
56763
56764 /* Leave ->target and ->handler uninitialized, as caller will always
56765 * explicitly initialize them before any side effects are possible.
56766 */
56767
56768 return res;
56769}
56770/*
56771 * duk_hobject and subclass assertion helpers
56772 */
56773
56774/* #include duk_internal.h -> already included */
56775
56776#if defined(DUK_USE_ASSERTIONS)
56777
56778DUK_INTERNAL void duk_hobject_assert_valid(duk_hobject *h) {
56779 DUK_ASSERT(h != NULL);
56792 /* Object is an Array <=> object has exotic array behavior */
56795}
56796
56797DUK_INTERNAL void duk_harray_assert_valid(duk_harray *h) {
56798 DUK_ASSERT(h != NULL);
56801}
56802
56803DUK_INTERNAL void duk_hboundfunc_assert_valid(duk_hboundfunc *h) {
56804 DUK_ASSERT(h != NULL);
56809 DUK_ASSERT(h->nargs == 0 || h->args != NULL);
56810}
56811
56812#if defined(DUK_USE_BUFFEROBJECT_SUPPORT)
56813DUK_INTERNAL void duk_hbufobj_assert_valid(duk_hbufobj *h) {
56814 DUK_ASSERT(h != NULL);
56815 DUK_ASSERT(h->shift <= 3);
56817 DUK_ASSERT((h->shift == 0 && h->elem_type == DUK_HBUFOBJ_ELEM_UINT8) ||
56818 (h->shift == 0 && h->elem_type == DUK_HBUFOBJ_ELEM_UINT8CLAMPED) ||
56819 (h->shift == 0 && h->elem_type == DUK_HBUFOBJ_ELEM_INT8) ||
56820 (h->shift == 1 && h->elem_type == DUK_HBUFOBJ_ELEM_UINT16) ||
56821 (h->shift == 1 && h->elem_type == DUK_HBUFOBJ_ELEM_INT16) ||
56822 (h->shift == 2 && h->elem_type == DUK_HBUFOBJ_ELEM_UINT32) ||
56823 (h->shift == 2 && h->elem_type == DUK_HBUFOBJ_ELEM_INT32) ||
56824 (h->shift == 2 && h->elem_type == DUK_HBUFOBJ_ELEM_FLOAT32) ||
56825 (h->shift == 3 && h->elem_type == DUK_HBUFOBJ_ELEM_FLOAT64));
56826 DUK_ASSERT(h->is_typedarray == 0 || h->is_typedarray == 1);
56828 if (h->buf == NULL) {
56829 DUK_ASSERT(h->offset == 0);
56830 DUK_ASSERT(h->length == 0);
56831 } else {
56832 /* No assertions for offset or length; in particular,
56833 * it's OK for length to be longer than underlying
56834 * buffer. Just ensure they don't wrap when added.
56835 */
56836 DUK_ASSERT(h->offset + h->length >= h->offset);
56837 }
56838}
56839#endif /* DUK_USE_BUFFEROBJECT_SUPPORT */
56840
56841DUK_INTERNAL void duk_hcompfunc_assert_valid(duk_hcompfunc *h) {
56842 DUK_ASSERT(h != NULL);
56843}
56844
56845DUK_INTERNAL void duk_hnatfunc_assert_valid(duk_hnatfunc *h) {
56846 DUK_ASSERT(h != NULL);
56847}
56848
56849DUK_INTERNAL void duk_hdecenv_assert_valid(duk_hdecenv *h) {
56850 DUK_ASSERT(h != NULL);
56852 DUK_ASSERT(h->thread == NULL || h->varmap != NULL);
56853}
56854
56855DUK_INTERNAL void duk_hobjenv_assert_valid(duk_hobjenv *h) {
56856 DUK_ASSERT(h != NULL);
56858 DUK_ASSERT(h->target != NULL);
56859 DUK_ASSERT(h->has_this == 0 || h->has_this == 1);
56860}
56861
56862DUK_INTERNAL void duk_hproxy_assert_valid(duk_hproxy *h) {
56863 DUK_ASSERT(h != NULL);
56864 DUK_ASSERT(h->target != NULL);
56865 DUK_ASSERT(h->handler != NULL);
56867}
56868
56869DUK_INTERNAL void duk_hthread_assert_valid(duk_hthread *thr) {
56870 DUK_ASSERT(thr != NULL);
56873 DUK_ASSERT(thr->unused1 == 0);
56874 DUK_ASSERT(thr->unused2 == 0);
56875}
56876
56877DUK_INTERNAL void duk_ctx_assert_valid(duk_hthread *thr) {
56878 DUK_ASSERT(thr != NULL);
56880 DUK_ASSERT(thr->valstack != NULL);
56881 DUK_ASSERT(thr->valstack_bottom != NULL);
56882 DUK_ASSERT(thr->valstack_top != NULL);
56883 DUK_ASSERT(thr->valstack_end != NULL);
56884 DUK_ASSERT(thr->valstack_alloc_end != NULL);
56886 DUK_ASSERT(thr->valstack_end >= thr->valstack);
56887 DUK_ASSERT(thr->valstack_top >= thr->valstack);
56889 DUK_ASSERT(thr->valstack_end >= thr->valstack_top);
56891}
56892
56893#endif /* DUK_USE_ASSERTIONS */
56894/*
56895 * Object enumeration support.
56896 *
56897 * Creates an internal enumeration state object to be used e.g. with for-in
56898 * enumeration. The state object contains a snapshot of target object keys
56899 * and internal control state for enumeration. Enumerator flags allow caller
56900 * to e.g. request internal/non-enumerable properties, and to enumerate only
56901 * "own" properties.
56902 *
56903 * Also creates the result value for e.g. Object.keys() based on the same
56904 * internal structure.
56905 *
56906 * This snapshot-based enumeration approach is used to simplify enumeration:
56907 * non-snapshot-based approaches are difficult to reconcile with mutating
56908 * the enumeration target, running multiple long-lived enumerators at the
56909 * same time, garbage collection details, etc. The downside is that the
56910 * enumerator object is memory inefficient especially for iterating arrays.
56911 */
56912
56913/* #include duk_internal.h -> already included */
56914
56915/* XXX: identify enumeration target with an object index (not top of stack) */
56916
56917/* First enumerated key index in enumerator object, must match exactly the
56918 * number of control properties inserted to the enumerator.
56919 */
56920#define DUK__ENUM_START_INDEX 2
56921
56922/* Current implementation suffices for ES2015 for now because there's no symbol
56923 * sorting, so commented out for now.
56924 */
56925
56926/*
56927 * Helper to sort enumeration keys using a callback for pairwise duk_hstring
56928 * comparisons. The keys are in the enumeration object entry part, starting
56929 * from DUK__ENUM_START_INDEX, and the entry part is dense. Entry part values
56930 * are all "true", e.g. "1" -> true, "3" -> true, "foo" -> true, "2" -> true,
56931 * so it suffices to just switch keys without switching values.
56932 *
56933 * ES2015 [[OwnPropertyKeys]] enumeration order for ordinary objects:
56934 * (1) array indices in ascending order,
56935 * (2) non-array-index keys in insertion order, and
56936 * (3) symbols in insertion order.
56937 * http://www.ecma-international.org/ecma-262/6.0/#sec-ordinary-object-internal-methods-and-internal-slots-ownpropertykeys.
56938 *
56939 * This rule is applied to "own properties" at each inheritance level;
56940 * non-duplicate parent keys always follow child keys. For example,
56941 * an inherited array index will enumerate -after- a symbol in the
56942 * child.
56943 *
56944 * Insertion sort is used because (1) it's simple and compact, (2) works
56945 * in-place, (3) minimizes operations if data is already nearly sorted,
56946 * (4) doesn't reorder elements considered equal.
56947 * http://en.wikipedia.org/wiki/Insertion_sort
56948 */
56949
56950/* Sort key, must hold array indices, "not array index" marker, and one more
56951 * higher value for symbols.
56952 */
56953#if !defined(DUK_USE_SYMBOL_BUILTIN)
56954typedef duk_uint32_t duk__sort_key_t;
56955#elif defined(DUK_USE_64BIT_OPS)
56956typedef duk_uint64_t duk__sort_key_t;
56957#else
56959#endif
56960
56961/* Get sort key for a duk_hstring. */
56964
56965 /* For array indices [0,0xfffffffe] use the array index as is.
56966 * For strings, use 0xffffffff, the marker 'arridx' already in
56967 * duk_hstring. For symbols, any value above 0xffffffff works,
56968 * as long as it is the same for all symbols; currently just add
56969 * the masked flag field into the arridx temporary.
56970 */
56971 DUK_ASSERT(x != NULL);
56973
56975
56976#if defined(DUK_USE_SYMBOL_BUILTIN)
56978#endif
56980 return (duk__sort_key_t) val;
56981}
56982
56983/* Insert element 'b' after element 'a'? */
56985 duk__sort_key_t val_a;
56986
56987 DUK_ASSERT(a != NULL);
56988 DUK_ASSERT(b != NULL);
56989 DUK_UNREF(b); /* Not actually needed now, val_b suffices. */
56990
56991 val_a = duk__hstring_sort_key(a);
56992
56993 if (val_a > val_b) {
56994 return 0;
56995 } else {
56996 return 1;
56997 }
56998}
56999
57001 duk_hstring **keys;
57002 duk_int_fast32_t idx;
57003
57004 DUK_ASSERT(h_obj != NULL);
57005 DUK_ASSERT(idx_start >= DUK__ENUM_START_INDEX);
57006 DUK_ASSERT(idx_end >= idx_start);
57007 DUK_UNREF(thr);
57008
57009 if (idx_end <= idx_start + 1) {
57010 return; /* Zero or one element(s). */
57011 }
57012
57013 keys = DUK_HOBJECT_E_GET_KEY_BASE(thr->heap, h_obj);
57014
57015 for (idx = idx_start + 1; idx < idx_end; idx++) {
57016 duk_hstring *h_curr;
57017 duk_int_fast32_t idx_insert;
57018 duk__sort_key_t val_curr;
57019
57020 h_curr = keys[idx];
57021 DUK_ASSERT(h_curr != NULL);
57022
57023 /* Scan backwards for insertion place. This works very well
57024 * when the elements are nearly in order which is the common
57025 * (and optimized for) case.
57026 */
57027
57028 val_curr = duk__hstring_sort_key(h_curr); /* Remains same during scanning. */
57029 for (idx_insert = idx - 1; idx_insert >= idx_start; idx_insert--) {
57030 duk_hstring *h_insert;
57031 h_insert = keys[idx_insert];
57032 DUK_ASSERT(h_insert != NULL);
57033
57034 if (duk__sort_compare_es6(h_insert, h_curr, val_curr)) {
57035 break;
57036 }
57037 }
57038 /* If we're out of indices, idx_insert == idx_start - 1 and idx_insert++
57039 * brings us back to idx_start.
57040 */
57041 idx_insert++;
57042 DUK_ASSERT(idx_insert >= 0 && idx_insert <= idx);
57043
57044 /* .-- p_insert .-- p_curr
57045 * v v
57046 * | ... | insert | ... | curr
57047 */
57048
57049 /* This could also done when the keys are in order, i.e.
57050 * idx_insert == idx. The result would be an unnecessary
57051 * memmove() but we use an explicit check because the keys
57052 * are very often in order already.
57053 */
57054 if (idx != idx_insert) {
57055 duk_memmove((void *) (keys + idx_insert + 1),
57056 (const void *) (keys + idx_insert),
57057 ((size_t) (idx - idx_insert) * sizeof(duk_hstring *)));
57058 keys[idx_insert] = h_curr;
57059 }
57060 }
57061
57062 /* Entry part has been reordered now with no side effects.
57063 * If the object has a hash part, it will now be incorrect
57064 * and we need to rehash. Do that by forcing a resize to
57065 * the current size.
57066 */
57068}
57069
57070/*
57071 * Create an internal enumerator object E, which has its keys ordered
57072 * to match desired enumeration ordering. Also initialize internal control
57073 * properties for enumeration.
57074 *
57075 * Note: if an array was used to hold enumeration keys instead, an array
57076 * scan would be needed to eliminate duplicates found in the prototype chain.
57077 */
57078
57080 /* 'k' may be unreachable on entry so must push without any
57081 * potential for GC.
57082 */
57083 duk_push_hstring(thr, k);
57084 duk_push_true(thr);
57085 duk_put_prop(thr, -3);
57086}
57087
57089 duk__add_enum_key(thr, DUK_HTHREAD_GET_STRING(thr, stridx));
57090}
57091
57093 duk_hobject *enum_target;
57094 duk_hobject *curr;
57095 duk_hobject *res;
57096#if defined(DUK_USE_ES6_PROXY)
57097 duk_hobject *h_proxy_target;
57098 duk_hobject *h_proxy_handler;
57099 duk_hobject *h_trap_result;
57100#endif
57101 duk_uint_fast32_t i, len; /* used for array, stack, and entry indices */
57102 duk_uint_fast32_t sort_start_index;
57103
57104 DUK_ASSERT(thr != NULL);
57105
57106 enum_target = duk_require_hobject(thr, -1);
57107 DUK_ASSERT(enum_target != NULL);
57108
57110 res = duk_known_hobject(thr, -1);
57111
57112 /* [enum_target res] */
57113
57114 /* Target must be stored so that we can recheck whether or not
57115 * keys still exist when we enumerate. This is not done if the
57116 * enumeration result comes from a proxy trap as there is no
57117 * real object to check against.
57118 */
57119 duk_push_hobject(thr, enum_target);
57120 duk_put_prop_stridx_short(thr, -2, DUK_STRIDX_INT_TARGET); /* Target is bare, plain put OK. */
57121
57122 /* Initialize index so that we skip internal control keys. */
57124 duk_put_prop_stridx_short(thr, -2, DUK_STRIDX_INT_NEXT); /* Target is bare, plain put OK. */
57125
57126 /*
57127 * Proxy object handling
57128 */
57129
57130#if defined(DUK_USE_ES6_PROXY)
57131 if (DUK_LIKELY((enum_flags & DUK_ENUM_NO_PROXY_BEHAVIOR) != 0)) {
57132 goto skip_proxy;
57133 }
57134 if (DUK_LIKELY(!duk_hobject_proxy_check(enum_target, &h_proxy_target, &h_proxy_handler))) {
57135 goto skip_proxy;
57136 }
57137
57138 /* XXX: share code with Object.keys() Proxy handling */
57139
57140 /* In ES2015 for-in invoked the "enumerate" trap; in ES2016 "enumerate"
57141 * has been obsoleted and "ownKeys" is used instead.
57142 */
57143 DUK_DDD(DUK_DDDPRINT("proxy enumeration"));
57144 duk_push_hobject(thr, h_proxy_handler);
57146 /* No need to replace the 'enum_target' value in stack, only the
57147 * enum_target reference. This also ensures that the original
57148 * enum target is reachable, which keeps the proxy and the proxy
57149 * target reachable. We do need to replace the internal _Target.
57150 */
57151 DUK_DDD(DUK_DDDPRINT("no ownKeys trap, enumerate proxy target instead"));
57152 DUK_DDD(DUK_DDDPRINT("h_proxy_target=%!O", (duk_heaphdr *) h_proxy_target));
57153 enum_target = h_proxy_target;
57154
57155 duk_push_hobject(thr, enum_target); /* -> [ ... enum_target res handler undefined target ] */
57156 duk_put_prop_stridx_short(thr, -4, DUK_STRIDX_INT_TARGET); /* Target is bare, plain put OK. */
57157
57158 duk_pop_2(thr); /* -> [ ... enum_target res ] */
57159 goto skip_proxy;
57160 }
57161
57162 /* [ ... enum_target res handler trap ] */
57163 duk_insert(thr, -2);
57164 duk_push_hobject(thr, h_proxy_target); /* -> [ ... enum_target res trap handler target ] */
57165 duk_call_method(thr, 1 /*nargs*/); /* -> [ ... enum_target res trap_result ] */
57166 h_trap_result = duk_require_hobject(thr, -1);
57167 DUK_UNREF(h_trap_result);
57168
57169 duk_proxy_ownkeys_postprocess(thr, h_proxy_target, enum_flags);
57170 /* -> [ ... enum_target res trap_result keys_array ] */
57171
57172 /* Copy cleaned up trap result keys into the enumerator object. */
57173 /* XXX: result is a dense array; could make use of that. */
57174 DUK_ASSERT(duk_is_array(thr, -1));
57175 len = (duk_uint_fast32_t) duk_get_length(thr, -1);
57176 for (i = 0; i < len; i++) {
57177 (void) duk_get_prop_index(thr, -1, (duk_uarridx_t) i);
57178 DUK_ASSERT(duk_is_string(thr, -1)); /* postprocess cleaned up */
57179 /* [ ... enum_target res trap_result keys_array val ] */
57180 duk_push_true(thr);
57181 /* [ ... enum_target res trap_result keys_array val true ] */
57182 duk_put_prop(thr, -5);
57183 }
57184 /* [ ... enum_target res trap_result keys_array ] */
57185 duk_pop_2(thr);
57186 duk_remove_m2(thr);
57187
57188 /* [ ... res ] */
57189
57190 /* The internal _Target property is kept pointing to the original
57191 * enumeration target (the proxy object), so that the enumerator
57192 * 'next' operation can read property values if so requested. The
57193 * fact that the _Target is a proxy disables key existence check
57194 * during enumeration.
57195 */
57196 DUK_DDD(DUK_DDDPRINT("proxy enumeration, final res: %!O", (duk_heaphdr *) res));
57197 goto compact_and_return;
57198
57199skip_proxy:
57200#endif /* DUK_USE_ES6_PROXY */
57201
57202 curr = enum_target;
57203 sort_start_index = DUK__ENUM_START_INDEX;
57205 while (curr) {
57206 duk_uint_fast32_t sort_end_index;
57207#if !defined(DUK_USE_PREFER_SIZE)
57208 duk_bool_t need_sort = 0;
57209#endif
57210 duk_bool_t cond;
57211
57212 /* Enumeration proceeds by inheritance level. Virtual
57213 * properties need to be handled specially, followed by
57214 * array part, and finally entry part.
57215 *
57216 * If there are array index keys in the entry part or any
57217 * other risk of the ES2015 [[OwnPropertyKeys]] order being
57218 * violated, need_sort is set and an explicit ES2015 sort is
57219 * done for the inheritance level.
57220 */
57221
57222 /* XXX: inheriting from proxy */
57223
57224 /*
57225 * Virtual properties.
57226 *
57227 * String and buffer indices are virtual and always enumerable,
57228 * 'length' is virtual and non-enumerable. Array and arguments
57229 * object props have special behavior but are concrete.
57230 *
57231 * String and buffer objects don't have an array part so as long
57232 * as virtual array index keys are enumerated first, we don't
57233 * need to set need_sort.
57234 */
57235
57236#if defined(DUK_USE_BUFFEROBJECT_SUPPORT)
57238#else
57240#endif
57241 cond = cond && !(enum_flags & DUK_ENUM_EXCLUDE_STRINGS);
57242 if (cond) {
57243 duk_bool_t have_length = 1;
57244
57245 /* String and buffer enumeration behavior is identical now,
57246 * so use shared handler.
57247 */
57249 duk_hstring *h_val;
57250 h_val = duk_hobject_get_internal_value_string(thr->heap, curr);
57251 DUK_ASSERT(h_val != NULL); /* string objects must not created without internal value */
57253 }
57254#if defined(DUK_USE_BUFFEROBJECT_SUPPORT)
57255 else {
57256 duk_hbufobj *h_bufobj;
57258 h_bufobj = (duk_hbufobj *) curr;
57259
57260 if (h_bufobj == NULL || !h_bufobj->is_typedarray) {
57261 /* Zero length seems like a good behavior for neutered buffers.
57262 * ArrayBuffer (non-view) and DataView don't have index properties
57263 * or .length property.
57264 */
57265 len = 0;
57266 have_length = 0;
57267 } else {
57268 /* There's intentionally no check for
57269 * current underlying buffer length.
57270 */
57271 len = (duk_uint_fast32_t) (h_bufobj->length >> h_bufobj->shift);
57272 }
57273 }
57274#endif /* DUK_USE_BUFFEROBJECT_SUPPORT */
57275
57276 for (i = 0; i < len; i++) {
57277 duk_hstring *k;
57278
57279 /* This is a bit fragile: the string is not
57280 * reachable until it is pushed by the helper.
57281 */
57282 k = duk_heap_strtable_intern_u32_checked(thr, (duk_uint32_t) i);
57283 DUK_ASSERT(k);
57284
57285 duk__add_enum_key(thr, k);
57286
57287 /* [enum_target res] */
57288 }
57289
57290 /* 'length' and other virtual properties are not
57291 * enumerable, but are included if non-enumerable
57292 * properties are requested.
57293 */
57294
57295 if (have_length && (enum_flags & DUK_ENUM_INCLUDE_NONENUMERABLE)) {
57297 }
57298 }
57299
57300 /*
57301 * Array part
57302 */
57303
57304 cond = !(enum_flags & DUK_ENUM_EXCLUDE_STRINGS);
57305 if (cond) {
57306 for (i = 0; i < (duk_uint_fast32_t) DUK_HOBJECT_GET_ASIZE(curr); i++) {
57307 duk_hstring *k;
57308 duk_tval *tv;
57309
57310 tv = DUK_HOBJECT_A_GET_VALUE_PTR(thr->heap, curr, i);
57311 if (DUK_TVAL_IS_UNUSED(tv)) {
57312 continue;
57313 }
57314 k = duk_heap_strtable_intern_u32_checked(thr, (duk_uint32_t) i); /* Fragile reachability. */
57315 DUK_ASSERT(k);
57316
57317 duk__add_enum_key(thr, k);
57318
57319 /* [enum_target res] */
57320 }
57321
57322 if (DUK_HOBJECT_HAS_EXOTIC_ARRAY(curr)) {
57323 /* Array .length comes after numeric indices. */
57324 if (enum_flags & DUK_ENUM_INCLUDE_NONENUMERABLE) {
57326 }
57327 }
57328 }
57329
57330 /*
57331 * Entries part
57332 */
57333
57334 for (i = 0; i < (duk_uint_fast32_t) DUK_HOBJECT_GET_ENEXT(curr); i++) {
57335 duk_hstring *k;
57336
57337 k = DUK_HOBJECT_E_GET_KEY(thr->heap, curr, i);
57338 if (!k) {
57339 continue;
57340 }
57341 if (!(enum_flags & DUK_ENUM_INCLUDE_NONENUMERABLE) &&
57342 !DUK_HOBJECT_E_SLOT_IS_ENUMERABLE(thr->heap, curr, i)) {
57343 continue;
57344 }
57346 if (!(enum_flags & DUK_ENUM_INCLUDE_HIDDEN) && DUK_HSTRING_HAS_HIDDEN(k)) {
57347 continue;
57348 }
57349 if (!(enum_flags & DUK_ENUM_INCLUDE_SYMBOLS)) {
57350 continue;
57351 }
57352#if !defined(DUK_USE_PREFER_SIZE)
57353 need_sort = 1;
57354#endif
57355 } else {
57356 DUK_ASSERT(!DUK_HSTRING_HAS_HIDDEN(k)); /* would also have symbol flag */
57357 if (enum_flags & DUK_ENUM_EXCLUDE_STRINGS) {
57358 continue;
57359 }
57360 }
57361 if (DUK_HSTRING_HAS_ARRIDX(k)) {
57362 /* This in currently only possible if the
57363 * object has no array part: the array part
57364 * is exhaustive when it is present.
57365 */
57366#if !defined(DUK_USE_PREFER_SIZE)
57367 need_sort = 1;
57368#endif
57369 } else {
57370 if (enum_flags & DUK_ENUM_ARRAY_INDICES_ONLY) {
57371 continue;
57372 }
57373 }
57374
57377
57378 duk__add_enum_key(thr, k);
57379
57380 /* [enum_target res] */
57381 }
57382
57383 /* Sort enumerated keys according to ES2015 requirements for
57384 * the "inheritance level" just processed. This is far from
57385 * optimal, ES2015 semantics could be achieved more efficiently
57386 * by handling array index string keys (and symbol keys)
57387 * specially above in effect doing the sort inline.
57388 *
57389 * Skip the sort if array index sorting is requested because
57390 * we must consider all keys, also inherited, so an explicit
57391 * sort is done for the whole result after we're done with the
57392 * prototype chain.
57393 *
57394 * Also skip the sort if need_sort == 0, i.e. we know for
57395 * certain that the enumerated order is already correct.
57396 */
57397 sort_end_index = DUK_HOBJECT_GET_ENEXT(res);
57398
57399 if (!(enum_flags & DUK_ENUM_SORT_ARRAY_INDICES)) {
57400#if defined(DUK_USE_PREFER_SIZE)
57401 duk__sort_enum_keys_es6(thr, res, (duk_int_fast32_t) sort_start_index, (duk_int_fast32_t) sort_end_index);
57402#else
57403 if (need_sort) {
57404 DUK_DDD(DUK_DDDPRINT("need to sort"));
57406 res,
57407 (duk_int_fast32_t) sort_start_index,
57408 (duk_int_fast32_t) sort_end_index);
57409 } else {
57410 DUK_DDD(DUK_DDDPRINT("no need to sort"));
57411 }
57412#endif
57413 }
57414
57415 sort_start_index = sort_end_index;
57416
57417 if (enum_flags & DUK_ENUM_OWN_PROPERTIES_ONLY) {
57418 break;
57419 }
57420
57421 curr = DUK_HOBJECT_GET_PROTOTYPE(thr->heap, curr);
57422 }
57423
57424 /* [enum_target res] */
57425
57426 duk_remove_m2(thr);
57427
57428 /* [res] */
57429
57430 if (enum_flags & DUK_ENUM_SORT_ARRAY_INDICES) {
57431 /* Some E5/E5.1 algorithms require that array indices are iterated
57432 * in a strictly ascending order. This is the case for e.g.
57433 * Array.prototype.forEach() and JSON.stringify() PropertyList
57434 * handling. The caller can request an explicit sort in these
57435 * cases.
57436 */
57437
57438 /* Sort to ES2015 order which works for pure array incides but
57439 * also for mixed keys.
57440 */
57442 res,
57445 }
57446
57447#if defined(DUK_USE_ES6_PROXY)
57448compact_and_return:
57449#endif
57450 /* compact; no need to seal because object is internal */
57451 duk_hobject_compact_props(thr, res);
57452
57453 DUK_DDD(DUK_DDDPRINT("created enumerator object: %!iT", (duk_tval *) duk_get_tval(thr, -1)));
57454}
57455
57456/*
57457 * Returns non-zero if a key and/or value was enumerated, and:
57458 *
57459 * [enum] -> [key] (get_value == 0)
57460 * [enum] -> [key value] (get_value == 1)
57461 *
57462 * Returns zero without pushing anything on the stack otherwise.
57463 */
57465 duk_hobject *e;
57466 duk_hobject *enum_target;
57467 duk_hstring *res = NULL;
57469 duk_bool_t check_existence;
57470
57471 DUK_ASSERT(thr != NULL);
57472
57473 /* [... enum] */
57474
57475 e = duk_require_hobject(thr, -1);
57476
57477 /* XXX use get tval ptr, more efficient */
57479 idx = (duk_uint_fast32_t) duk_require_uint(thr, -1);
57480 duk_pop(thr);
57481 DUK_DDD(DUK_DDDPRINT("enumeration: index is: %ld", (long) idx));
57482
57483 /* Enumeration keys are checked against the enumeration target (to see
57484 * that they still exist). In the proxy enumeration case _Target will
57485 * be the proxy, and checking key existence against the proxy is not
57486 * required (or sensible, as the keys may be fully virtual).
57487 */
57489 enum_target = duk_require_hobject(thr, -1);
57490 DUK_ASSERT(enum_target != NULL);
57491#if defined(DUK_USE_ES6_PROXY)
57492 check_existence = (!DUK_HOBJECT_IS_PROXY(enum_target));
57493#else
57494 check_existence = 1;
57495#endif
57496 duk_pop(thr); /* still reachable */
57497
57498 DUK_DDD(DUK_DDDPRINT("getting next enum value, enum_target=%!iO, enumerator=%!iT",
57499 (duk_heaphdr *) enum_target,
57500 (duk_tval *) duk_get_tval(thr, -1)));
57501
57502 /* no array part */
57503 for (;;) {
57504 duk_hstring *k;
57505
57506 if (idx >= DUK_HOBJECT_GET_ENEXT(e)) {
57507 DUK_DDD(DUK_DDDPRINT("enumeration: ran out of elements"));
57508 break;
57509 }
57510
57511 /* we know these because enum objects are internally created */
57512 k = DUK_HOBJECT_E_GET_KEY(thr->heap, e, idx);
57513 DUK_ASSERT(k != NULL);
57516
57517 idx++;
57518
57519 /* recheck that the property still exists */
57520 if (check_existence && !duk_hobject_hasprop_raw(thr, enum_target, k)) {
57521 DUK_DDD(DUK_DDDPRINT("property deleted during enumeration, skip"));
57522 continue;
57523 }
57524
57525 DUK_DDD(DUK_DDDPRINT("enumeration: found element, key: %!O", (duk_heaphdr *) k));
57526 res = k;
57527 break;
57528 }
57529
57530 DUK_DDD(DUK_DDDPRINT("enumeration: updating next index to %ld", (long) idx));
57531
57532 duk_push_u32(thr, (duk_uint32_t) idx);
57534
57535 /* [... enum] */
57536
57537 if (res) {
57538 duk_push_hstring(thr, res);
57539 if (get_value) {
57540 duk_push_hobject(thr, enum_target);
57541 duk_dup_m2(thr); /* -> [... enum key enum_target key] */
57542 duk_get_prop(thr, -2); /* -> [... enum key enum_target val] */
57543 duk_remove_m2(thr); /* -> [... enum key val] */
57544 duk_remove(thr, -3); /* -> [... key val] */
57545 } else {
57546 duk_remove_m2(thr); /* -> [... key] */
57547 }
57548 return 1;
57549 } else {
57550 duk_pop(thr); /* -> [...] */
57551 return 0;
57552 }
57553}
57554
57555/*
57556 * Get enumerated keys in an ECMAScript array. Matches Object.keys() behavior
57557 * described in E5 Section 15.2.3.14.
57558 */
57559
57561 duk_hobject *e;
57562 duk_hstring **keys;
57563 duk_tval *tv;
57565
57566 DUK_ASSERT(thr != NULL);
57567 DUK_ASSERT(duk_get_hobject(thr, -1) != NULL);
57568
57569 /* Create a temporary enumerator to get the (non-duplicated) key list;
57570 * the enumerator state is initialized without being needed, but that
57571 * has little impact.
57572 */
57573
57574 duk_hobject_enumerator_create(thr, enum_flags);
57575 e = duk_known_hobject(thr, -1);
57576
57577 /* [enum_target enum res] */
57578
57579 /* Create dense result array to exact size. */
57581 count = (duk_uint32_t) (DUK_HOBJECT_GET_ENEXT(e) - DUK__ENUM_START_INDEX);
57582
57583 /* XXX: uninit would be OK */
57584 tv = duk_push_harray_with_size_outptr(thr, (duk_uint32_t) count);
57585 DUK_ASSERT(count == 0 || tv != NULL);
57586 DUK_ASSERT(!duk_is_bare_object(thr, -1));
57587
57588 /* Fill result array, no side effects. */
57589
57590 keys = DUK_HOBJECT_E_GET_KEY_BASE(thr->heap, e);
57591 keys += DUK__ENUM_START_INDEX;
57592
57593 while (count-- > 0) {
57594 duk_hstring *k;
57595
57596 k = *keys++;
57597 DUK_ASSERT(k != NULL); /* enumerator must have no keys deleted */
57598
57600 tv++;
57601 DUK_HSTRING_INCREF(thr, k);
57602 }
57603
57604 /* [enum_target enum res] */
57605 duk_remove_m2(thr);
57606
57607 /* [enum_target res] */
57608
57609 return 1; /* return 1 to allow callers to tail call */
57610}
57611
57612/* automatic undefs */
57613#undef DUK__ENUM_START_INDEX
57614/*
57615 * Misc support functions
57616 */
57617
57618/* #include duk_internal.h -> already included */
57619
57621 duk_hobject *h,
57622 duk_hobject *p,
57623 duk_bool_t ignore_loop) {
57624 duk_uint_t sanity;
57625
57626 DUK_ASSERT(thr != NULL);
57627
57628 /* False if the object is NULL or the prototype 'p' is NULL.
57629 * In particular, false if both are NULL (don't compare equal).
57630 */
57631 if (h == NULL || p == NULL) {
57632 return 0;
57633 }
57636 do {
57637 if (h == p) {
57638 return 1;
57639 }
57640
57641 if (sanity-- == 0) {
57642 if (ignore_loop) {
57643 break;
57644 } else {
57646 DUK_WO_NORETURN(return 0;);
57647 }
57648 }
57649 h = DUK_HOBJECT_GET_PROTOTYPE(thr->heap, h);
57650 } while (h);
57651
57652 return 0;
57653}
57654
57656#if defined(DUK_USE_REFERENCE_COUNTING)
57657 duk_hobject *tmp;
57658
57659 DUK_ASSERT(h);
57660 tmp = DUK_HOBJECT_GET_PROTOTYPE(thr->heap, h);
57661 DUK_HOBJECT_SET_PROTOTYPE(thr->heap, h, p);
57662 DUK_HOBJECT_INCREF_ALLOWNULL(thr, p); /* avoid problems if p == h->prototype */
57664#else
57665 DUK_ASSERT(h);
57666 DUK_UNREF(thr);
57667 DUK_HOBJECT_SET_PROTOTYPE(thr->heap, h, p);
57668#endif
57669}
57670/*
57671 * Helpers for creating and querying pc2line debug data, which
57672 * converts a bytecode program counter to a source line number.
57673 *
57674 * The run-time pc2line data is bit-packed, and documented in:
57675 *
57676 * doc/function-objects.rst
57677 */
57678
57679/* #include duk_internal.h -> already included */
57680
57681#if defined(DUK_USE_PC2LINE)
57682
57683/* Generate pc2line data for an instruction sequence, leaving a buffer on stack top. */
57685 duk_hbuffer_dynamic *h_buf;
57686 duk_bitencoder_ctx be_ctx_alloc;
57687 duk_bitencoder_ctx *be_ctx = &be_ctx_alloc;
57688 duk_uint32_t *hdr;
57689 duk_size_t new_size;
57690 duk_uint_fast32_t num_header_entries;
57691 duk_uint_fast32_t curr_offset;
57692 duk_int_fast32_t curr_line, next_line, diff_line;
57693 duk_uint_fast32_t curr_pc;
57694 duk_uint_fast32_t hdr_index;
57695
57697
57698 num_header_entries = (length + DUK_PC2LINE_SKIP - 1) / DUK_PC2LINE_SKIP;
57699 curr_offset = (duk_uint_fast32_t) (sizeof(duk_uint32_t) + num_header_entries * sizeof(duk_uint32_t) * 2);
57700
57701 duk_push_dynamic_buffer(thr, (duk_size_t) curr_offset);
57702 h_buf = (duk_hbuffer_dynamic *) duk_known_hbuffer(thr, -1);
57704
57705 hdr = (duk_uint32_t *) DUK_HBUFFER_DYNAMIC_GET_DATA_PTR(thr->heap, h_buf);
57706 DUK_ASSERT(hdr != NULL);
57707 hdr[0] = (duk_uint32_t) length; /* valid pc range is [0, length[ */
57708
57709 curr_pc = 0U;
57710 while (curr_pc < length) {
57711 new_size = (duk_size_t) (curr_offset + DUK_PC2LINE_MAX_DIFF_LENGTH);
57712 duk_hbuffer_resize(thr, h_buf, new_size);
57713
57714 hdr = (duk_uint32_t *) DUK_HBUFFER_DYNAMIC_GET_DATA_PTR(thr->heap, h_buf);
57715 DUK_ASSERT(hdr != NULL);
57716 DUK_ASSERT(curr_pc < length);
57717 hdr_index = 1 + (curr_pc / DUK_PC2LINE_SKIP) * 2;
57718 curr_line = (duk_int_fast32_t) instrs[curr_pc].line;
57719 hdr[hdr_index + 0] = (duk_uint32_t) curr_line;
57720 hdr[hdr_index + 1] = (duk_uint32_t) curr_offset;
57721
57722#if 0
57723 DUK_DDD(DUK_DDDPRINT("hdr[%ld]: pc=%ld line=%ld offset=%ld",
57724 (long) (curr_pc / DUK_PC2LINE_SKIP),
57725 (long) curr_pc,
57726 (long) hdr[hdr_index + 0],
57727 (long) hdr[hdr_index + 1]));
57728#endif
57729
57730 duk_memzero(be_ctx, sizeof(*be_ctx));
57731 be_ctx->data = ((duk_uint8_t *) hdr) + curr_offset;
57733
57734 for (;;) {
57735 curr_pc++;
57736 if (((curr_pc % DUK_PC2LINE_SKIP) == 0) || /* end of diff run */
57737 (curr_pc >= length)) { /* end of bytecode */
57738 break;
57739 }
57740 DUK_ASSERT(curr_pc < length);
57741 next_line = (duk_int32_t) instrs[curr_pc].line;
57742 diff_line = next_line - curr_line;
57743
57744#if 0
57745 DUK_DDD(DUK_DDDPRINT("curr_line=%ld, next_line=%ld -> diff_line=%ld",
57746 (long) curr_line, (long) next_line, (long) diff_line));
57747#endif
57748
57749 if (diff_line == 0) {
57750 /* 0 */
57751 duk_be_encode(be_ctx, 0, 1);
57752 } else if (diff_line >= 1 && diff_line <= 4) {
57753 /* 1 0 <2 bits> */
57754 duk_be_encode(be_ctx, (duk_uint32_t) ((0x02 << 2) + (diff_line - 1)), 4);
57755 } else if (diff_line >= -0x80 && diff_line <= 0x7f) {
57756 /* 1 1 0 <8 bits> */
57757 DUK_ASSERT(diff_line + 0x80 >= 0 && diff_line + 0x80 <= 0xff);
57758 duk_be_encode(be_ctx, (duk_uint32_t) ((0x06 << 8) + (diff_line + 0x80)), 11);
57759 } else {
57760 /* 1 1 1 <32 bits>
57761 * Encode in two parts to avoid bitencode 24-bit limitation
57762 */
57763 duk_be_encode(be_ctx, (duk_uint32_t) ((0x07 << 16) + ((next_line >> 16) & 0xffff)), 19);
57764 duk_be_encode(be_ctx, (duk_uint32_t) (next_line & 0xffff), 16);
57765 }
57766
57767 curr_line = next_line;
57768 }
57769
57770 duk_be_finish(be_ctx);
57771 DUK_ASSERT(!be_ctx->truncated);
57772
57773 /* be_ctx->offset == length of encoded bitstream */
57774 curr_offset += (duk_uint_fast32_t) be_ctx->offset;
57775 }
57776
57777 /* compact */
57778 new_size = (duk_size_t) curr_offset;
57779 duk_hbuffer_resize(thr, h_buf, new_size);
57780
57781 (void) duk_to_fixed_buffer(thr, -1, NULL);
57782
57783 DUK_DDD(DUK_DDDPRINT("final pc2line data: pc_limit=%ld, length=%ld, %lf bits/opcode --> %!ixT",
57784 (long) length,
57785 (long) new_size,
57786 (double) new_size * 8.0 / (double) length,
57787 (duk_tval *) duk_get_tval(thr, -1)));
57788}
57789
57790/* PC is unsigned. If caller does PC arithmetic and gets a negative result,
57791 * it will map to a large PC which is out of bounds and causes a zero to be
57792 * returned.
57793 */
57795 duk_bitdecoder_ctx bd_ctx_alloc;
57796 duk_bitdecoder_ctx *bd_ctx = &bd_ctx_alloc;
57797 duk_uint32_t *hdr;
57798 duk_uint_fast32_t start_offset;
57799 duk_uint_fast32_t pc_limit;
57800 duk_uint_fast32_t hdr_index;
57801 duk_uint_fast32_t pc_base;
57803 duk_uint_fast32_t curr_line;
57804
57805 DUK_ASSERT(buf != NULL);
57807 DUK_UNREF(thr);
57808
57809 /*
57810 * Use the index in the header to find the right starting point
57811 */
57812
57813 hdr_index = pc / DUK_PC2LINE_SKIP;
57814 pc_base = hdr_index * DUK_PC2LINE_SKIP;
57815 n = pc - pc_base;
57816
57817 if (DUK_HBUFFER_FIXED_GET_SIZE(buf) <= sizeof(duk_uint32_t)) {
57818 DUK_DD(DUK_DDPRINT("pc2line lookup failed: buffer is smaller than minimal header"));
57819 goto pc2line_error;
57820 }
57821
57822 hdr = (duk_uint32_t *) (void *) DUK_HBUFFER_FIXED_GET_DATA_PTR(thr->heap, buf);
57823 pc_limit = hdr[0];
57824 if (pc >= pc_limit) {
57825 /* Note: pc is unsigned and cannot be negative */
57826 DUK_DD(DUK_DDPRINT("pc2line lookup failed: pc out of bounds (pc=%ld, limit=%ld)", (long) pc, (long) pc_limit));
57827 goto pc2line_error;
57828 }
57829
57830 curr_line = hdr[1 + hdr_index * 2];
57831 start_offset = hdr[1 + hdr_index * 2 + 1];
57832 if ((duk_size_t) start_offset > DUK_HBUFFER_FIXED_GET_SIZE(buf)) {
57833 DUK_DD(DUK_DDPRINT("pc2line lookup failed: start_offset out of bounds (start_offset=%ld, buffer_size=%ld)",
57834 (long) start_offset,
57835 (long) DUK_HBUFFER_GET_SIZE((duk_hbuffer *) buf)));
57836 goto pc2line_error;
57837 }
57838
57839 /*
57840 * Iterate the bitstream (line diffs) until PC is reached
57841 */
57842
57843 duk_memzero(bd_ctx, sizeof(*bd_ctx));
57844 bd_ctx->data = ((duk_uint8_t *) hdr) + start_offset;
57845 bd_ctx->length = (duk_size_t) (DUK_HBUFFER_FIXED_GET_SIZE(buf) - start_offset);
57846
57847#if 0
57848 DUK_DDD(DUK_DDDPRINT("pc2line lookup: pc=%ld -> hdr_index=%ld, pc_base=%ld, n=%ld, start_offset=%ld",
57849 (long) pc, (long) hdr_index, (long) pc_base, (long) n, (long) start_offset));
57850#endif
57851
57852 while (n > 0) {
57853#if 0
57854 DUK_DDD(DUK_DDDPRINT("lookup: n=%ld, curr_line=%ld", (long) n, (long) curr_line));
57855#endif
57856
57857 if (duk_bd_decode_flag(bd_ctx)) {
57858 if (duk_bd_decode_flag(bd_ctx)) {
57859 if (duk_bd_decode_flag(bd_ctx)) {
57860 /* 1 1 1 <32 bits> */
57862 t = duk_bd_decode(bd_ctx, 16); /* workaround: max nbits = 24 now */
57863 t = (t << 16) + duk_bd_decode(bd_ctx, 16);
57864 curr_line = t;
57865 } else {
57866 /* 1 1 0 <8 bits> */
57868 t = duk_bd_decode(bd_ctx, 8);
57869 curr_line = curr_line + t - 0x80;
57870 }
57871 } else {
57872 /* 1 0 <2 bits> */
57874 t = duk_bd_decode(bd_ctx, 2);
57875 curr_line = curr_line + t + 1;
57876 }
57877 } else {
57878 /* 0: no change */
57879 }
57880
57881 n--;
57882 }
57883
57884 DUK_DDD(DUK_DDDPRINT("pc2line lookup result: pc %ld -> line %ld", (long) pc, (long) curr_line));
57885 return curr_line;
57886
57887pc2line_error:
57888 DUK_D(DUK_DPRINT("pc2line conversion failed for pc=%ld", (long) pc));
57889 return 0;
57890}
57891
57893 duk_hbuffer_fixed *pc2line;
57895
57896 /* XXX: now that pc2line is used by the debugger quite heavily in
57897 * checked execution, this should be optimized to avoid value stack
57898 * and perhaps also implement some form of pc2line caching (see
57899 * future work in debugger.rst).
57900 */
57901
57903 pc2line = (duk_hbuffer_fixed *) (void *) duk_get_hbuffer(thr, -1);
57904 if (pc2line != NULL) {
57907 } else {
57908 line = 0;
57909 }
57910 duk_pop(thr);
57911
57912 return line;
57913}
57914
57915#endif /* DUK_USE_PC2LINE */
57916/*
57917 * duk_hobject property access functionality.
57918 *
57919 * This is very central functionality for size, performance, and compliance.
57920 * It is also rather intricate; see hobject-algorithms.rst for discussion on
57921 * the algorithms and memory-management.rst for discussion on refcounts and
57922 * side effect issues.
57923 *
57924 * Notes:
57925 *
57926 * - It might be tempting to assert "refcount nonzero" for objects
57927 * being operated on, but that's not always correct: objects with
57928 * a zero refcount may be operated on by the refcount implementation
57929 * (finalization) for instance. Hence, no refcount assertions are made.
57930 *
57931 * - Many operations (memory allocation, identifier operations, etc)
57932 * may cause arbitrary side effects (e.g. through GC and finalization).
57933 * These side effects may invalidate duk_tval pointers which point to
57934 * areas subject to reallocation (like value stack). Heap objects
57935 * themselves have stable pointers. Holding heap object pointers or
57936 * duk_tval copies is not problematic with respect to side effects;
57937 * care must be taken when holding and using argument duk_tval pointers.
57938 *
57939 * - If a finalizer is executed, it may operate on the the same object
57940 * we're currently dealing with. For instance, the finalizer might
57941 * delete a certain property which has already been looked up and
57942 * confirmed to exist. Ideally finalizers would be disabled if GC
57943 * happens during property access. At the moment property table realloc
57944 * disables finalizers, and all DECREFs may cause arbitrary changes so
57945 * handle DECREF carefully.
57947 * - The order of operations for a DECREF matters. When DECREF is executed,
57948 * the entire object graph must be consistent; note that a refzero may
57949 * lead to a mark-and-sweep through a refcount finalizer. Use NORZ macros
57950 * and an explicit DUK_REFZERO_CHECK_xxx() if achieving correct order is hard.
57951 */
57953/*
57954 * XXX: array indices are mostly typed as duk_uint32_t here; duk_uarridx_t
57955 * might be more appropriate.
57956 */
57958/* #include duk_internal.h -> already included */
57959
57960/*
57961 * Local defines
57962 */
57963
57964#define DUK__NO_ARRAY_INDEX DUK_HSTRING_NO_ARRAY_INDEX
57965
57966/* Marker values for hash part. */
57967#define DUK__HASH_UNUSED DUK_HOBJECT_HASHIDX_UNUSED
57968#define DUK__HASH_DELETED DUK_HOBJECT_HASHIDX_DELETED
57969
57970/* Valstack space that suffices for all local calls, excluding any recursion
57971 * into ECMAScript or Duktape/C calls (Proxy, getters, etc).
57972 */
57973#define DUK__VALSTACK_SPACE 10
57974
57975/* Valstack space allocated especially for proxy lookup which does a
57976 * recursive property lookup.
57977 */
57978#define DUK__VALSTACK_PROXY_LOOKUP 20
57979
57980/*
57981 * Local prototypes
57982 */
57983
57985 duk_hobject *obj,
57986 duk_hstring *key,
57987 duk_propdesc *temp_desc);
57989 duk_hobject *obj,
57990 duk_hstring *key,
57991 duk_propdesc *temp_desc,
57992 duk_bool_t throw_flag);
57994 duk_hobject *obj,
57995 duk_hstring *key,
57996 duk_propdesc *temp_desc);
57997
57999 duk_hobject *obj,
58000 duk_uint32_t old_len,
58001 duk_uint32_t new_len,
58002 duk_bool_t force_flag,
58003 duk_uint32_t *out_result_len);
58005
58009 duk_hobject *obj,
58010 duk_hstring *key,
58011 duk_uint32_t arr_idx,
58012 duk_propdesc *out_desc,
58013 duk_small_uint_t flags);
58014
58016DUK_LOCAL_DECL void duk__grow_props_for_array_item(duk_hthread *thr, duk_hobject *obj, duk_uint32_t highest_arr_idx);
58017
58018/*
58019 * Misc helpers
58020 */
58021
58022/* Convert a duk_tval number (caller checks) to a 32-bit index. Returns
58023 * DUK__NO_ARRAY_INDEX if the number is not whole or not a valid array
58024 * index.
58025 */
58026/* XXX: for fastints, could use a variant which assumes a double duk_tval
58027 * (and doesn't need to check for fastint again).
58028 */
58030 duk_double_t dbl;
58031 duk_uint32_t idx;
58032
58033 DUK_ASSERT(tv != NULL);
58035
58036 /* -0 is accepted here as index 0 because ToString(-0) == "0" which is
58037 * in canonical form and thus an array index.
58038 */
58039 dbl = DUK_TVAL_GET_NUMBER(tv);
58040 idx = (duk_uint32_t) dbl;
58041 if (duk_double_equals((duk_double_t) idx, dbl)) {
58042 /* Is whole and within 32 bit range. If the value happens to be 0xFFFFFFFF,
58043 * it's not a valid array index but will then match DUK__NO_ARRAY_INDEX.
58044 */
58045 return idx;
58046 }
58047 return DUK__NO_ARRAY_INDEX;
58048}
58049
58050#if defined(DUK_USE_FASTINT)
58051/* Convert a duk_tval fastint (caller checks) to a 32-bit index. */
58053 duk_int64_t t;
58054
58055 DUK_ASSERT(tv != NULL);
58058 t = DUK_TVAL_GET_FASTINT(tv);
58059 if (((duk_uint64_t) t & ~DUK_U64_CONSTANT(0xffffffff)) != 0) {
58060 /* Catches >0x100000000 and negative values. */
58061 return DUK__NO_ARRAY_INDEX;
58062 }
58063
58064 /* If the value happens to be 0xFFFFFFFF, it's not a valid array index
58065 * but will then match DUK__NO_ARRAY_INDEX.
58066 */
58067 return (duk_uint32_t) t;
58068}
58069#endif /* DUK_USE_FASTINT */
58070
58071/* Convert a duk_tval on the value stack (in a trusted index we don't validate)
58072 * to a string or symbol using ES2015 ToPropertyKey():
58073 * http://www.ecma-international.org/ecma-262/6.0/#sec-topropertykey.
58074 *
58075 * Also check if it's a valid array index and return that (or DUK__NO_ARRAY_INDEX
58076 * if not).
58077 */
58078DUK_LOCAL duk_uint32_t duk__to_property_key(duk_hthread *thr, duk_idx_t idx, duk_hstring **out_h) {
58079 duk_uint32_t arr_idx;
58080 duk_hstring *h;
58081 duk_tval *tv_dst;
58082
58083 DUK_ASSERT(thr != NULL);
58084 DUK_ASSERT(out_h != NULL);
58085 DUK_ASSERT(duk_is_valid_index(thr, idx));
58086 DUK_ASSERT(idx < 0);
58087
58088 /* XXX: The revised ES2015 ToPropertyKey() handling (ES5.1 was just
58089 * ToString()) involves a ToPrimitive(), a symbol check, and finally
58090 * a ToString(). Figure out the best way to have a good fast path
58091 * but still be compliant and share code.
58093
58094 tv_dst = DUK_GET_TVAL_NEGIDX(thr, idx); /* intentionally unvalidated */
58095 if (DUK_TVAL_IS_STRING(tv_dst)) {
58096 /* Most important path: strings and plain symbols are used as
58097 * is. For symbols the array index check below is unnecessary
58098 * (they're never valid array indices) but checking that the
58099 * string is a symbol would make the plain string path slower
58100 * unnecessarily.
58101 */
58102 h = DUK_TVAL_GET_STRING(tv_dst);
58103 } else {
58104 h = duk_to_property_key_hstring(thr, idx);
58105 }
58106 DUK_ASSERT(h != NULL);
58107 *out_h = h;
58108
58109 arr_idx = DUK_HSTRING_GET_ARRIDX_FAST(h);
58110 return arr_idx;
58111}
58112
58113DUK_LOCAL duk_uint32_t duk__push_tval_to_property_key(duk_hthread *thr, duk_tval *tv_key, duk_hstring **out_h) {
58114 duk_push_tval(thr, tv_key); /* XXX: could use an unsafe push here */
58115 return duk__to_property_key(thr, -1, out_h);
58116}
58117
58118/* String is an own (virtual) property of a plain buffer. */
58120 DUK_UNREF(thr);
58122 /* Virtual index properties. Checking explicitly for
58123 * 'arr_idx != DUK__NO_ARRAY_INDEX' is not necessary
58124 * because DUK__NO_ARRAY_INDEXi is always larger than
58125 * maximum allowed buffer size.
58126 */
58128 if (arr_idx < DUK_HBUFFER_GET_SIZE(buf)) {
58129 return 1;
58130 }
58131
58132 /* Other virtual properties. */
58133 return (key == DUK_HTHREAD_STRING_LENGTH(thr));
58134}
58135
58136/*
58137 * Helpers for managing property storage size
58138 */
58139
58140/* Get default hash part size for a certain entry part size. */
58141#if defined(DUK_USE_HOBJECT_HASH_PART)
58142DUK_LOCAL duk_uint32_t duk__get_default_h_size(duk_uint32_t e_size) {
58144
58145 if (e_size >= DUK_USE_HOBJECT_HASH_PROP_LIMIT) {
58146 duk_uint32_t res;
58147 duk_uint32_t tmp;
58148
58149 /* Hash size should be 2^N where N is chosen so that 2^N is
58150 * larger than e_size. Extra shifting is used to ensure hash
58151 * is relatively sparse.
58153 tmp = e_size;
58154 res = 2; /* Result will be 2 ** (N + 1). */
58155 while (tmp >= 0x40) {
58156 tmp >>= 6;
58157 res <<= 6;
58158 }
58159 while (tmp != 0) {
58160 tmp >>= 1;
58161 res <<= 1;
58162 }
58163 DUK_ASSERT((DUK_HOBJECT_MAX_PROPERTIES << 2U) > DUK_HOBJECT_MAX_PROPERTIES); /* Won't wrap, even shifted by 2. */
58164 DUK_ASSERT(res > e_size);
58165 return res;
58166 } else {
58167 return 0;
58168 }
58169}
58170#endif /* USE_PROP_HASH_PART */
58171
58172/* Get minimum entry part growth for a certain size. */
58173DUK_LOCAL duk_uint32_t duk__get_min_grow_e(duk_uint32_t e_size) {
58174 duk_uint32_t res;
58175
58177 DUK_ASSERT(res >= 1); /* important for callers */
58178 return res;
58179}
58180
58181/* Get minimum array part growth for a certain size. */
58182DUK_LOCAL duk_uint32_t duk__get_min_grow_a(duk_uint32_t a_size) {
58183 duk_uint32_t res;
58184
58186 DUK_ASSERT(res >= 1); /* important for callers */
58187 return res;
58188}
58189
58190/* Count actually used entry part entries (non-NULL keys). */
58193 duk_uint_fast32_t n = 0;
58194 duk_hstring **e;
58195
58196 DUK_ASSERT(obj != NULL);
58197 DUK_UNREF(thr);
58198
58199 e = DUK_HOBJECT_E_GET_KEY_BASE(thr->heap, obj);
58200 for (i = 0; i < DUK_HOBJECT_GET_ENEXT(obj); i++) {
58201 if (*e++) {
58202 n++;
58203 }
58204 }
58205 return (duk_uint32_t) n;
58206}
58207
58208/* Count actually used array part entries and array minimum size.
58209 * NOTE: 'out_min_size' can be computed much faster by starting from the
58210 * end and breaking out early when finding first used entry, but this is
58211 * not needed now.
58212 */
58213DUK_LOCAL void duk__compute_a_stats(duk_hthread *thr, duk_hobject *obj, duk_uint32_t *out_used, duk_uint32_t *out_min_size) {
58215 duk_uint_fast32_t used = 0;
58216 duk_uint_fast32_t highest_idx = (duk_uint_fast32_t) -1; /* see below */
58217 duk_tval *a;
58218
58219 DUK_ASSERT(obj != NULL);
58220 DUK_ASSERT(out_used != NULL);
58221 DUK_ASSERT(out_min_size != NULL);
58223
58224 a = DUK_HOBJECT_A_GET_BASE(thr->heap, obj);
58225 for (i = 0; i < DUK_HOBJECT_GET_ASIZE(obj); i++) {
58226 duk_tval *tv = a++;
58227 if (!DUK_TVAL_IS_UNUSED(tv)) {
58228 used++;
58229 highest_idx = i;
58230 }
58231 }
58232
58233 /* Initial value for highest_idx is -1 coerced to unsigned. This
58234 * is a bit odd, but (highest_idx + 1) will then wrap to 0 below
58235 * for out_min_size as intended.
58236 */
58237
58238 *out_used = (duk_uint32_t) used;
58239 *out_min_size = (duk_uint32_t) (highest_idx + 1); /* 0 if no used entries */
58240}
58241
58242/* Check array density and indicate whether or not the array part should be abandoned. */
58243DUK_LOCAL duk_bool_t duk__abandon_array_density_check(duk_uint32_t a_used, duk_uint32_t a_size) {
58244 /*
58245 * Array abandon check; abandon if:
58246 *
58247 * new_used / new_size < limit
58248 * new_used < limit * new_size || limit is 3 bits fixed point
58249 * new_used < limit' / 8 * new_size || *8
58250 * 8*new_used < limit' * new_size || :8
58251 * new_used < limit' * (new_size / 8)
58252 *
58253 * Here, new_used = a_used, new_size = a_size.
58254 *
58255 * Note: some callers use approximate values for a_used and/or a_size
58256 * (e.g. dropping a '+1' term). This doesn't affect the usefulness
58257 * of the check, but may confuse debugging.
58258 */
58259
58260 return (a_used < DUK_USE_HOBJECT_ARRAY_ABANDON_LIMIT * (a_size >> 3));
58261}
58262
58263/* Fast check for extending array: check whether or not a slow density check is required. */
58264DUK_LOCAL duk_bool_t duk__abandon_array_slow_check_required(duk_uint32_t arr_idx, duk_uint32_t old_size) {
58265 duk_uint32_t new_size_min;
58266
58267 /*
58268 * In a fast check we assume old_size equals old_used (i.e., existing
58269 * array is fully dense).
58270 *
58271 * Slow check if:
58273 * (new_size - old_size) / old_size > limit
58274 * new_size - old_size > limit * old_size
58275 * new_size > (1 + limit) * old_size || limit' is 3 bits fixed point
58276 * new_size > (1 + (limit' / 8)) * old_size || * 8
58277 * 8 * new_size > (8 + limit') * old_size || : 8
58278 * new_size > (8 + limit') * (old_size / 8)
58279 * new_size > limit'' * (old_size / 8) || limit'' = 9 -> max 25% increase
58280 * arr_idx + 1 > limit'' * (old_size / 8)
58281 *
58282 * This check doesn't work well for small values, so old_size is rounded
58283 * up for the check (and the '+ 1' of arr_idx can be ignored in practice):
58284 *
58285 * arr_idx > limit'' * ((old_size + 7) / 8)
58286 */
58287
58288 new_size_min = arr_idx + 1;
58289 return (new_size_min >= DUK_USE_HOBJECT_ARRAY_ABANDON_MINSIZE) &&
58290 (arr_idx > DUK_USE_HOBJECT_ARRAY_FAST_RESIZE_LIMIT * ((old_size + 7) >> 3));
58291}
58292
58293DUK_LOCAL duk_bool_t duk__abandon_array_check(duk_hthread *thr, duk_uint32_t arr_idx, duk_hobject *obj) {
58294 duk_uint32_t min_size;
58295 duk_uint32_t old_used;
58296 duk_uint32_t old_size;
58297
58299 DUK_DDD(DUK_DDDPRINT("=> fast resize is OK"));
58300 return 0;
58301 }
58302
58303 duk__compute_a_stats(thr, obj, &old_used, &old_size);
58304
58305 DUK_DDD(DUK_DDDPRINT("abandon check, array stats: old_used=%ld, old_size=%ld, arr_idx=%ld",
58306 (long) old_used,
58307 (long) old_size,
58308 (long) arr_idx));
58309
58310 min_size = arr_idx + 1;
58311#if defined(DUK_USE_OBJSIZES16)
58312 if (min_size > DUK_UINT16_MAX) {
58313 goto do_abandon;
58314 }
58315#endif
58316 DUK_UNREF(min_size);
58317
58318 /* Note: intentionally use approximations to shave a few instructions:
58319 * a_used = old_used (accurate: old_used + 1)
58320 * a_size = arr_idx (accurate: arr_idx + 1)
58322 if (duk__abandon_array_density_check(old_used, arr_idx)) {
58323 DUK_DD(DUK_DDPRINT("write to new array entry beyond current length, "
58324 "decided to abandon array part (would become too sparse)"));
58325
58326 /* Abandoning requires a props allocation resize and
58327 * 'rechecks' the valstack, invalidating any existing
58328 * valstack value pointers.
58329 */
58330 goto do_abandon;
58331 }
58332
58333 DUK_DDD(DUK_DDDPRINT("=> decided to keep array part"));
58334 return 0;
58335
58336do_abandon:
58337 duk__abandon_array_part(thr, obj);
58339 return 1;
58340}
58341
58343 /*
58344 * Array needs to grow, but we don't want it becoming too sparse.
58345 * If it were to become sparse, abandon array part, moving all
58346 * array entries into the entries part (for good).
58347 *
58348 * Since we don't keep track of actual density (used vs. size) of
58349 * the array part, we need to estimate somehow. The check is made
58350 * in two parts:
58351 *
58352 * - Check whether the resize need is small compared to the
58353 * current size (relatively); if so, resize without further
58354 * checking (essentially we assume that the original part is
58355 * "dense" so that the result would be dense enough).
58356 *
58357 * - Otherwise, compute the resize using an actual density
58358 * measurement based on counting the used array entries.
58359 */
58360
58361 DUK_DDD(DUK_DDDPRINT("write to new array requires array resize, decide whether to do a "
58362 "fast resize without abandon check (arr_idx=%ld, old_size=%ld)",
58363 (long) arr_idx,
58364 (long) DUK_HOBJECT_GET_ASIZE(obj)));
58365
58366 if (DUK_UNLIKELY(duk__abandon_array_check(thr, arr_idx, obj) != 0)) {
58368 return NULL;
58369 }
58370
58371 DUK_DD(DUK_DDPRINT("write to new array entry beyond current length, "
58372 "decided to extend current allocation"));
58373
58374 /* In principle it's possible to run out of memory extending the
58375 * array but with the allocation going through if we were to abandon
58376 * the array part and try again. In practice this should be rare
58377 * because abandoned arrays have a higher per-entry footprint.
58378 */
58380 duk__grow_props_for_array_item(thr, obj, arr_idx);
58381
58383 DUK_ASSERT(arr_idx < DUK_HOBJECT_GET_ASIZE(obj));
58384 return DUK_HOBJECT_A_GET_VALUE_PTR(thr->heap, obj, arr_idx);
58385}
58386
58388 if (DUK_LIKELY(arr_idx < DUK_HOBJECT_GET_ASIZE(obj))) {
58389 return DUK_HOBJECT_A_GET_VALUE_PTR(thr->heap, obj, arr_idx);
58390 } else {
58391 return duk__obtain_arridx_slot_slowpath(thr, arr_idx, obj);
58392 }
58393}
58394
58395/*
58396 * Proxy helpers
58397 */
58398
58399#if defined(DUK_USE_ES6_PROXY)
58401 duk_hproxy *h_proxy;
58402
58403 DUK_ASSERT(obj != NULL);
58404 DUK_ASSERT(out_target != NULL);
58405 DUK_ASSERT(out_handler != NULL);
58406
58407 /* Caller doesn't need to check exotic proxy behavior (but does so for
58408 * some fast paths).
58409 */
58410 if (DUK_LIKELY(!DUK_HOBJECT_IS_PROXY(obj))) {
58411 return 0;
58412 }
58413 h_proxy = (duk_hproxy *) obj;
58414 DUK_HPROXY_ASSERT_VALID(h_proxy);
58415
58416 DUK_ASSERT(h_proxy->handler != NULL);
58417 DUK_ASSERT(h_proxy->target != NULL);
58418 *out_handler = h_proxy->handler;
58419 *out_target = h_proxy->target;
58420
58421 return 1;
58422}
58423#endif /* DUK_USE_ES6_PROXY */
58424
58425/* Get Proxy target object. If the argument is not a Proxy, return it as is.
58426 * If a Proxy is revoked, an error is thrown.
58427 */
58428#if defined(DUK_USE_ES6_PROXY)
58430 DUK_ASSERT(obj != NULL);
58432 /* Resolve Proxy targets until Proxy chain ends. No explicit check for
58433 * a Proxy loop: user code cannot create such a loop (it would only be
58434 * possible by editing duk_hproxy references directly).
58435 */
58436
58437 while (DUK_HOBJECT_IS_PROXY(obj)) {
58438 duk_hproxy *h_proxy;
58439
58440 h_proxy = (duk_hproxy *) obj;
58441 DUK_HPROXY_ASSERT_VALID(h_proxy);
58442 obj = h_proxy->target;
58443 DUK_ASSERT(obj != NULL);
58444 }
58445
58446 DUK_ASSERT(obj != NULL);
58447 return obj;
58448}
58449#endif /* DUK_USE_ES6_PROXY */
58450
58451#if defined(DUK_USE_ES6_PROXY)
58453 duk_hobject *obj,
58454 duk_small_uint_t stridx_trap,
58455 duk_tval *tv_key,
58456 duk_hobject **out_target) {
58457 duk_hobject *h_handler;
58458
58459 DUK_ASSERT(thr != NULL);
58460 DUK_ASSERT(obj != NULL);
58461 DUK_ASSERT(tv_key != NULL);
58462 DUK_ASSERT(out_target != NULL);
58463
58464 if (!duk_hobject_proxy_check(obj, out_target, &h_handler)) {
58465 return 0;
58466 }
58467 DUK_ASSERT(*out_target != NULL);
58468 DUK_ASSERT(h_handler != NULL);
58469
58470 /* XXX: At the moment Duktape accesses internal keys like _Finalizer using a
58471 * normal property set/get which would allow a proxy handler to interfere with
58472 * such behavior and to get access to internal key strings. This is not a problem
58473 * as such because internal key strings can be created in other ways too (e.g.
58474 * through buffers). The best fix is to change Duktape internal lookups to
58475 * skip proxy behavior. Until that, internal property accesses bypass the
58476 * proxy and are applied to the target (as if the handler did not exist).
58477 * This has some side effects, see test-bi-proxy-internal-keys.js.
58478 */
58479
58480 if (DUK_TVAL_IS_STRING(tv_key)) {
58481 duk_hstring *h_key = (duk_hstring *) DUK_TVAL_GET_STRING(tv_key);
58482 DUK_ASSERT(h_key != NULL);
58483 if (DUK_HSTRING_HAS_HIDDEN(h_key)) {
58484 /* Symbol accesses must go through proxy lookup in ES2015.
58485 * Hidden symbols behave like Duktape 1.x internal keys
58486 * and currently won't.
58487 */
58488 DUK_DDD(DUK_DDDPRINT("hidden key, skip proxy handler and apply to target"));
58489 return 0;
58490 }
58491 }
58492
58493 /* The handler is looked up with a normal property lookup; it may be an
58494 * accessor or the handler object itself may be a proxy object. If the
58495 * handler is a proxy, we need to extend the valstack as we make a
58496 * recursive proxy check without a function call in between (in fact
58497 * there is no limit to the potential recursion here).
58498 *
58499 * (For sanity, proxy creation rejects another proxy object as either
58500 * the handler or the target at the moment so recursive proxy cases
58501 * are not realized now.)
58502 */
58503
58504 /* XXX: C recursion limit if proxies are allowed as handler/target values */
58505
58507 duk_push_hobject(thr, h_handler);
58508 if (duk_get_prop_stridx_short(thr, -1, stridx_trap)) {
58509 /* -> [ ... handler trap ] */
58510 duk_insert(thr, -2); /* -> [ ... trap handler ] */
58511
58512 /* stack prepped for func call: [ ... trap handler ] */
58513 return 1;
58514 } else {
58515 duk_pop_2_unsafe(thr);
58516 return 0;
58517 }
58518}
58519#endif /* DUK_USE_ES6_PROXY */
58520
58521/*
58522 * Reallocate property allocation, moving properties to the new allocation.
58523 *
58524 * Includes key compaction, rehashing, and can also optionally abandon
58525 * the array part, 'migrating' array entries into the beginning of the
58526 * new entry part.
58527 *
58528 * There is no support for in-place reallocation or just compacting keys
58529 * without resizing the property allocation. This is intentional to keep
58530 * code size minimal, but would be useful future work.
58531 *
58532 * The implementation is relatively straightforward, except for the array
58533 * abandonment process. Array abandonment requires that new string keys
58534 * are interned, which may trigger GC. All keys interned so far must be
58535 * reachable for GC at all times and correctly refcounted for; valstack is
58536 * used for that now.
58537 *
58538 * Also, a GC triggered during this reallocation process must not interfere
58539 * with the object being resized. This is currently controlled by preventing
58540 * finalizers (as they may affect ANY object) and object compaction in
58541 * mark-and-sweep. It would suffice to protect only this particular object
58542 * from compaction, however. DECREF refzero cascades are side effect free
58543 * and OK.
58544 *
58545 * Note: because we need to potentially resize the valstack (as part
58546 * of abandoning the array part), any tval pointers to the valstack
58547 * will become invalid after this call.
58548 */
58549
58551 duk_hobject *obj,
58552 duk_uint32_t new_e_size,
58553 duk_uint32_t new_a_size,
58554 duk_uint32_t new_h_size,
58555 duk_bool_t abandon_array) {
58556 duk_small_uint_t prev_ms_base_flags;
58557 duk_uint32_t new_alloc_size;
58558 duk_uint32_t new_e_size_adjusted;
58559 duk_uint8_t *new_p;
58560 duk_hstring **new_e_k;
58561 duk_propvalue *new_e_pv;
58562 duk_uint8_t *new_e_f;
58563 duk_tval *new_a;
58564 duk_uint32_t *new_h;
58565 duk_uint32_t new_e_next;
58567 duk_size_t array_copy_size;
58568#if defined(DUK_USE_ASSERTIONS)
58569 duk_bool_t prev_error_not_allowed;
58570#endif
58571
58572 DUK_ASSERT(thr != NULL);
58573 DUK_ASSERT(obj != NULL);
58574 DUK_ASSERT(!abandon_array || new_a_size == 0); /* if abandon_array, new_a_size must be 0 */
58575 DUK_ASSERT(DUK_HOBJECT_GET_PROPS(thr->heap, obj) != NULL ||
58576 (DUK_HOBJECT_GET_ESIZE(obj) == 0 && DUK_HOBJECT_GET_ASIZE(obj) == 0));
58577 DUK_ASSERT(new_h_size == 0 || new_h_size >= new_e_size); /* required to guarantee success of rehashing,
58578 * intentionally use unadjusted new_e_size
58579 */
58582
58583 DUK_STATS_INC(thr->heap, stats_object_realloc_props);
58584
58585 /*
58586 * Pre resize assertions.
58587 */
58588
58589#if defined(DUK_USE_ASSERTIONS)
58590 /* XXX: pre-checks (such as no duplicate keys) */
58591#endif
58592
58593 /*
58594 * For property layout 1, tweak e_size to ensure that the whole entry
58595 * part (key + val + flags) is a suitable multiple for alignment
58596 * (platform specific).
58597 *
58598 * Property layout 2 does not require this tweaking and is preferred
58599 * on low RAM platforms requiring alignment.
58600 */
58601
58602#if defined(DUK_USE_HOBJECT_LAYOUT_2) || defined(DUK_USE_HOBJECT_LAYOUT_3)
58603 DUK_DDD(DUK_DDDPRINT("using layout 2 or 3, no need to pad e_size: %ld", (long) new_e_size));
58604 new_e_size_adjusted = new_e_size;
58605#elif defined(DUK_USE_HOBJECT_LAYOUT_1) && (DUK_HOBJECT_ALIGN_TARGET == 1)
58606 DUK_DDD(DUK_DDDPRINT("using layout 1, but no need to pad e_size: %ld", (long) new_e_size));
58607 new_e_size_adjusted = new_e_size;
58608#elif defined(DUK_USE_HOBJECT_LAYOUT_1) && ((DUK_HOBJECT_ALIGN_TARGET == 4) || (DUK_HOBJECT_ALIGN_TARGET == 8))
58609 new_e_size_adjusted =
58610 (new_e_size + (duk_uint32_t) DUK_HOBJECT_ALIGN_TARGET - 1U) & (~((duk_uint32_t) DUK_HOBJECT_ALIGN_TARGET - 1U));
58611 DUK_DDD(DUK_DDDPRINT("using layout 1, and alignment target is %ld, adjusted e_size: %ld -> %ld",
58613 (long) new_e_size,
58614 (long) new_e_size_adjusted));
58615 DUK_ASSERT(new_e_size_adjusted >= new_e_size);
58616#else
58617#error invalid hobject layout defines
58618#endif
58619
58620 /*
58621 * Debug logging after adjustment.
58622 */
58623
58625 "attempt to resize hobject %p props (%ld -> %ld bytes), from {p=%p,e_size=%ld,e_next=%ld,a_size=%ld,h_size=%ld} to "
58626 "{e_size=%ld,a_size=%ld,h_size=%ld}, abandon_array=%ld, unadjusted new_e_size=%ld",
58627 (void *) obj,
58629 (long) DUK_HOBJECT_P_COMPUTE_SIZE(new_e_size_adjusted, new_a_size, new_h_size),
58630 (void *) DUK_HOBJECT_GET_PROPS(thr->heap, obj),
58631 (long) DUK_HOBJECT_GET_ESIZE(obj),
58632 (long) DUK_HOBJECT_GET_ENEXT(obj),
58633 (long) DUK_HOBJECT_GET_ASIZE(obj),
58634 (long) DUK_HOBJECT_GET_HSIZE(obj),
58635 (long) new_e_size_adjusted,
58636 (long) new_a_size,
58637 (long) new_h_size,
58638 (long) abandon_array,
58639 (long) new_e_size));
58640
58641 /*
58642 * Property count check. This is the only point where we ensure that
58643 * we don't get more (allocated) property space that we can handle.
58644 * There aren't hard limits as such, but some algorithms may fail
58645 * if we get too close to the 4G property limit.
58646 *
58647 * Since this works based on allocation size (not actually used size),
58648 * the limit is a bit approximate but good enough in practice.
58649 */
58650
58651 if (new_e_size_adjusted + new_a_size > DUK_HOBJECT_MAX_PROPERTIES) {
58653 DUK_WO_NORETURN(return;);
58654 }
58655#if defined(DUK_USE_OBJSIZES16)
58656 if (new_e_size_adjusted > DUK_UINT16_MAX || new_a_size > DUK_UINT16_MAX) {
58657 /* If caller gave us sizes larger than what we can store,
58658 * fail memory safely with an internal error rather than
58659 * truncating the sizes.
58660 */
58661 DUK_ERROR_INTERNAL(thr);
58662 DUK_WO_NORETURN(return;);
58663 }
58664#endif
58665
58666 /*
58667 * Compute new alloc size and alloc new area.
58668 *
58669 * The new area is not tracked in the heap at all, so it's critical
58670 * we get to free/keep it in a controlled manner.
58671 */
58672
58673#if defined(DUK_USE_ASSERTIONS)
58674 /* Whole path must be error throw free, but we may be called from
58675 * within error handling so can't assert for error_not_allowed == 0.
58676 */
58677 prev_error_not_allowed = thr->heap->error_not_allowed;
58678 thr->heap->error_not_allowed = 1;
58679#endif
58680 prev_ms_base_flags = thr->heap->ms_base_flags;
58681 thr->heap->ms_base_flags |=
58682 DUK_MS_FLAG_NO_OBJECT_COMPACTION; /* Avoid attempt to compact the current object (all objects really). */
58683 thr->heap->pf_prevent_count++; /* Avoid finalizers. */
58684 DUK_ASSERT(thr->heap->pf_prevent_count != 0); /* Wrap. */
58685
58686 new_alloc_size = DUK_HOBJECT_P_COMPUTE_SIZE(new_e_size_adjusted, new_a_size, new_h_size);
58687 DUK_DDD(DUK_DDDPRINT("new hobject allocation size is %ld", (long) new_alloc_size));
58688 if (new_alloc_size == 0) {
58689 DUK_ASSERT(new_e_size_adjusted == 0);
58690 DUK_ASSERT(new_a_size == 0);
58691 DUK_ASSERT(new_h_size == 0);
58692 new_p = NULL;
58693 } else {
58694 /* Alloc may trigger mark-and-sweep but no compaction, and
58695 * cannot throw.
58696 */
58697#if 0 /* XXX: inject test */
58698 if (1) {
58699 new_p = NULL;
58700 goto alloc_failed;
58701 }
58702#endif
58703 new_p = (duk_uint8_t *) DUK_ALLOC(thr->heap, new_alloc_size);
58704 if (new_p == NULL) {
58705 /* NULL always indicates alloc failure because
58706 * new_alloc_size > 0.
58707 */
58708 goto alloc_failed;
58709 }
58710 }
58711
58712 /* Set up pointers to the new property area: this is hidden behind a macro
58713 * because it is memory layout specific.
58714 */
58716 new_e_k,
58717 new_e_pv,
58718 new_e_f,
58719 new_a,
58720 new_h,
58721 new_e_size_adjusted,
58722 new_a_size,
58723 new_h_size);
58724 DUK_UNREF(new_h); /* happens when hash part dropped */
58725 new_e_next = 0;
58726
58727 /* if new_p == NULL, all of these pointers are NULL */
58728 DUK_ASSERT((new_p != NULL) || (new_e_k == NULL && new_e_pv == NULL && new_e_f == NULL && new_a == NULL && new_h == NULL));
58729
58730 DUK_DDD(DUK_DDDPRINT("new alloc size %ld, new_e_k=%p, new_e_pv=%p, new_e_f=%p, new_a=%p, new_h=%p",
58731 (long) new_alloc_size,
58732 (void *) new_e_k,
58733 (void *) new_e_pv,
58734 (void *) new_e_f,
58735 (void *) new_a,
58736 (void *) new_h));
58737
58738 /*
58739 * Migrate array part to start of entries if requested.
58740 *
58741 * Note: from an enumeration perspective the order of entry keys matters.
58742 * Array keys should appear wherever they appeared before the array abandon
58743 * operation. (This no longer matters much because keys are ES2015 sorted.)
58744 */
58745
58746 if (abandon_array) {
58747 /* Assuming new_a_size == 0, and that entry part contains
58748 * no conflicting keys, refcounts do not need to be adjusted for
58749 * the values, as they remain exactly the same.
58750 *
58751 * The keys, however, need to be interned, incref'd, and be
58752 * reachable for GC. Any intern attempt may trigger a GC and
58753 * claim any non-reachable strings, so every key must be reachable
58754 * at all times. Refcounts must be correct to satisfy refcount
58755 * assertions.
58756 *
58757 * A longjmp must not occur here, as the new_p allocation would
58758 * leak. Refcounts would come out correctly as the interned
58759 * strings are valstack tracked.
58760 */
58761 DUK_ASSERT(new_a_size == 0);
58762
58763 DUK_STATS_INC(thr->heap, stats_object_abandon_array);
58764
58765 for (i = 0; i < DUK_HOBJECT_GET_ASIZE(obj); i++) {
58766 duk_tval *tv1;
58767 duk_tval *tv2;
58768 duk_hstring *key;
58769
58770 DUK_ASSERT(DUK_HOBJECT_GET_PROPS(thr->heap, obj) != NULL);
58771
58772 tv1 = DUK_HOBJECT_A_GET_VALUE_PTR(thr->heap, obj, i);
58773 if (DUK_TVAL_IS_UNUSED(tv1)) {
58774 continue;
58775 }
58776
58777 DUK_ASSERT(new_p != NULL && new_e_k != NULL && new_e_pv != NULL && new_e_f != NULL);
58778
58779 /*
58780 * Intern key via the valstack to ensure reachability behaves
58781 * properly. We must avoid longjmp's here so use non-checked
58782 * primitives.
58783 *
58784 * Note: duk_check_stack() potentially reallocs the valstack,
58785 * invalidating any duk_tval pointers to valstack. Callers
58786 * must be careful.
58787 */
58788
58789#if 0 /* XXX: inject test */
58790 if (1) {
58791 goto abandon_error;
58792 }
58793#endif
58794 /* Never shrinks; auto-adds DUK_VALSTACK_INTERNAL_EXTRA, which
58795 * is generous.
58796 */
58797 if (!duk_check_stack(thr, 1)) {
58798 goto abandon_error;
58799 }
58801 key = duk_heap_strtable_intern_u32(thr->heap, (duk_uint32_t) i);
58802 if (key == NULL) {
58803 goto abandon_error;
58804 }
58805 duk_push_hstring(thr, key); /* keep key reachable for GC etc; guaranteed not to fail */
58806
58807 /* Key is now reachable in the valstack, don't INCREF
58808 * the new allocation yet (we'll steal the refcounts
58809 * from the value stack once all keys are done).
58810 */
58811
58812 new_e_k[new_e_next] = key;
58813 tv2 = &new_e_pv[new_e_next].v; /* array entries are all plain values */
58814 DUK_TVAL_SET_TVAL(tv2, tv1);
58815 new_e_f[new_e_next] =
58817 new_e_next++;
58818
58819 /* Note: new_e_next matches pushed temp key count, and nothing can
58820 * fail above between the push and this point.
58821 */
58822 }
58823
58824 /* Steal refcounts from value stack. */
58825 DUK_DDD(DUK_DDDPRINT("abandon array: pop %ld key temps from valstack", (long) new_e_next));
58826 duk_pop_n_nodecref_unsafe(thr, (duk_idx_t) new_e_next);
58827 }
58828
58829 /*
58830 * Copy keys and values in the entry part (compacting them at the same time).
58831 */
58832
58833 for (i = 0; i < DUK_HOBJECT_GET_ENEXT(obj); i++) {
58834 duk_hstring *key;
58835
58836 DUK_ASSERT(DUK_HOBJECT_GET_PROPS(thr->heap, obj) != NULL);
58837
58838 key = DUK_HOBJECT_E_GET_KEY(thr->heap, obj, i);
58839 if (key == NULL) {
58840 continue;
58841 }
58842
58843 DUK_ASSERT(new_p != NULL && new_e_k != NULL && new_e_pv != NULL && new_e_f != NULL);
58844
58845 new_e_k[new_e_next] = key;
58846 new_e_pv[new_e_next] = DUK_HOBJECT_E_GET_VALUE(thr->heap, obj, i);
58847 new_e_f[new_e_next] = DUK_HOBJECT_E_GET_FLAGS(thr->heap, obj, i);
58848 new_e_next++;
58849 }
58850 /* the entries [new_e_next, new_e_size_adjusted[ are left uninitialized on purpose (ok, not gc reachable) */
58851
58852 /*
58853 * Copy array elements to new array part. If the new array part is
58854 * larger, initialize the unused entries as UNUSED because they are
58855 * GC reachable.
58856 */
58857
58858#if defined(DUK_USE_ASSERTIONS)
58859 /* Caller must have decref'd values above new_a_size (if that is necessary). */
58860 if (!abandon_array) {
58861 for (i = new_a_size; i < DUK_HOBJECT_GET_ASIZE(obj); i++) {
58862 duk_tval *tv;
58863 tv = DUK_HOBJECT_A_GET_VALUE_PTR(thr->heap, obj, i);
58865 }
58866 }
58867#endif
58868 if (new_a_size > DUK_HOBJECT_GET_ASIZE(obj)) {
58869 array_copy_size = sizeof(duk_tval) * DUK_HOBJECT_GET_ASIZE(obj);
58870 } else {
58871 array_copy_size = sizeof(duk_tval) * new_a_size;
58872 }
58873
58874 DUK_ASSERT(new_a != NULL || array_copy_size == 0U);
58875 DUK_ASSERT(DUK_HOBJECT_GET_PROPS(thr->heap, obj) != NULL || array_copy_size == 0U);
58876 DUK_ASSERT(DUK_HOBJECT_GET_ASIZE(obj) > 0 || array_copy_size == 0U);
58877 duk_memcpy_unsafe((void *) new_a, (const void *) DUK_HOBJECT_A_GET_BASE(thr->heap, obj), array_copy_size);
58878
58879 for (i = DUK_HOBJECT_GET_ASIZE(obj); i < new_a_size; i++) {
58880 duk_tval *tv = &new_a[i];
58882 }
58883
58884 /*
58885 * Rebuild the hash part always from scratch (guaranteed to finish
58886 * as long as caller gave consistent parameters).
58887 *
58888 * Any resize of hash part requires rehashing. In addition, by rehashing
58889 * get rid of any elements marked deleted (DUK__HASH_DELETED) which is critical
58890 * to ensuring the hash part never fills up.
58891 */
58892
58893#if defined(DUK_USE_HOBJECT_HASH_PART)
58894 if (new_h_size == 0) {
58895 DUK_DDD(DUK_DDDPRINT("no hash part, no rehash"));
58896 } else {
58897 duk_uint32_t mask;
58898
58899 DUK_ASSERT(new_h != NULL);
58900
58901 /* fill new_h with u32 0xff = UNUSED */
58902 DUK_ASSERT(new_h_size > 0);
58903 duk_memset(new_h, 0xff, sizeof(duk_uint32_t) * new_h_size);
58904
58905 DUK_ASSERT(new_e_next <= new_h_size); /* equality not actually possible */
58906
58907 mask = new_h_size - 1;
58908 for (i = 0; i < new_e_next; i++) {
58909 duk_hstring *key = new_e_k[i];
58910 duk_uint32_t j, step;
58911
58912 DUK_ASSERT(key != NULL);
58913 j = DUK_HSTRING_GET_HASH(key) & mask;
58914 step = 1; /* Cache friendly but clustering prone. */
58915
58916 for (;;) {
58917 DUK_ASSERT(new_h[j] != DUK__HASH_DELETED); /* should never happen */
58918 if (new_h[j] == DUK__HASH_UNUSED) {
58919 DUK_DDD(DUK_DDDPRINT("rebuild hit %ld -> %ld", (long) j, (long) i));
58920 new_h[j] = (duk_uint32_t) i;
58921 break;
58922 }
58923 DUK_DDD(DUK_DDDPRINT("rebuild miss %ld, step %ld", (long) j, (long) step));
58924 j = (j + step) & mask;
58925
58926 /* Guaranteed to finish (hash is larger than #props). */
58927 }
58928 }
58929 }
58930#endif /* DUK_USE_HOBJECT_HASH_PART */
58931
58932 /*
58933 * Nice debug log.
58934 */
58935
58937 "resized hobject %p props (%ld -> %ld bytes), from {p=%p,e_size=%ld,e_next=%ld,a_size=%ld,h_size=%ld} to "
58938 "{p=%p,e_size=%ld,e_next=%ld,a_size=%ld,h_size=%ld}, abandon_array=%ld, unadjusted new_e_size=%ld",
58939 (void *) obj,
58941 (long) new_alloc_size,
58942 (void *) DUK_HOBJECT_GET_PROPS(thr->heap, obj),
58943 (long) DUK_HOBJECT_GET_ESIZE(obj),
58944 (long) DUK_HOBJECT_GET_ENEXT(obj),
58945 (long) DUK_HOBJECT_GET_ASIZE(obj),
58946 (long) DUK_HOBJECT_GET_HSIZE(obj),
58947 (void *) new_p,
58948 (long) new_e_size_adjusted,
58949 (long) new_e_next,
58950 (long) new_a_size,
58951 (long) new_h_size,
58952 (long) abandon_array,
58953 (long) new_e_size));
58954
58955 /*
58956 * All done, switch properties ('p') allocation to new one.
58957 */
58958
58959 DUK_FREE_CHECKED(thr, DUK_HOBJECT_GET_PROPS(thr->heap, obj)); /* NULL obj->p is OK */
58960 DUK_HOBJECT_SET_PROPS(thr->heap, obj, new_p);
58961 DUK_HOBJECT_SET_ESIZE(obj, new_e_size_adjusted);
58962 DUK_HOBJECT_SET_ENEXT(obj, new_e_next);
58963 DUK_HOBJECT_SET_ASIZE(obj, new_a_size);
58964 DUK_HOBJECT_SET_HSIZE(obj, new_h_size);
58965
58966 /* Clear array part flag only after switching. */
58967 if (abandon_array) {
58969 }
58970
58971 DUK_DDD(DUK_DDDPRINT("resize result: %!O", (duk_heaphdr *) obj));
58972
58973 DUK_ASSERT(thr->heap->pf_prevent_count > 0);
58974 thr->heap->pf_prevent_count--;
58975 thr->heap->ms_base_flags = prev_ms_base_flags;
58976#if defined(DUK_USE_ASSERTIONS)
58977 DUK_ASSERT(thr->heap->error_not_allowed == 1);
58978 thr->heap->error_not_allowed = prev_error_not_allowed;
58979#endif
58980
58981 /*
58982 * Post resize assertions.
58983 */
58984
58985#if defined(DUK_USE_ASSERTIONS)
58986 /* XXX: post-checks (such as no duplicate keys) */
58987#endif
58988 return;
58989
58990 /*
58991 * Abandon array failed. We don't need to DECREF anything
58992 * because the references in the new allocation are not
58993 * INCREF'd until abandon is complete. The string interned
58994 * keys are on the value stack and are handled normally by
58995 * unwind.
58996 */
58997
58998abandon_error:
58999alloc_failed:
59000 DUK_D(DUK_DPRINT("object property table resize failed"));
59001
59002 DUK_FREE_CHECKED(thr, new_p); /* OK for NULL. */
59003
59004 thr->heap->pf_prevent_count--;
59005 thr->heap->ms_base_flags = prev_ms_base_flags;
59006#if defined(DUK_USE_ASSERTIONS)
59007 DUK_ASSERT(thr->heap->error_not_allowed == 1);
59008 thr->heap->error_not_allowed = prev_error_not_allowed;
59009#endif
59010
59012 DUK_WO_NORETURN(return;);
59013}
59014
59015/*
59016 * Helpers to resize properties allocation on specific needs.
59017 */
59018
59019DUK_INTERNAL void duk_hobject_resize_entrypart(duk_hthread *thr, duk_hobject *obj, duk_uint32_t new_e_size) {
59020 duk_uint32_t old_e_size;
59021 duk_uint32_t new_a_size;
59022 duk_uint32_t new_h_size;
59023
59024 DUK_ASSERT(thr != NULL);
59025 DUK_ASSERT(obj != NULL);
59026
59027 old_e_size = DUK_HOBJECT_GET_ESIZE(obj);
59028 if (old_e_size > new_e_size) {
59029 new_e_size = old_e_size;
59030 }
59031#if defined(DUK_USE_HOBJECT_HASH_PART)
59032 new_h_size = duk__get_default_h_size(new_e_size);
59033#else
59034 new_h_size = 0;
59035#endif
59036 new_a_size = DUK_HOBJECT_GET_ASIZE(obj);
59037
59038 duk_hobject_realloc_props(thr, obj, new_e_size, new_a_size, new_h_size, 0);
59039}
59040
59041/* Grow entry part allocation for one additional entry. */
59043 duk_uint32_t old_e_used; /* actually used, non-NULL entries */
59044 duk_uint32_t new_e_size_minimum;
59045 duk_uint32_t new_e_size;
59046 duk_uint32_t new_a_size;
59047 duk_uint32_t new_h_size;
59048
59049 DUK_ASSERT(thr != NULL);
59050 DUK_ASSERT(obj != NULL);
59051
59052 /* Duktape 0.11.0 and prior tried to optimize the resize by not
59053 * counting the number of actually used keys prior to the resize.
59054 * This worked mostly well but also caused weird leak-like behavior
59055 * as in: test-bug-object-prop-alloc-unbounded.js. So, now we count
59056 * the keys explicitly to compute the new entry part size.
59057 */
59058
59059 old_e_used = duk__count_used_e_keys(thr, obj);
59060 new_e_size_minimum = old_e_used + 1;
59061 new_e_size = old_e_used + duk__get_min_grow_e(old_e_used);
59062#if defined(DUK_USE_HOBJECT_HASH_PART)
59063 new_h_size = duk__get_default_h_size(new_e_size);
59064#else
59065 new_h_size = 0;
59066#endif
59067 new_a_size = DUK_HOBJECT_GET_ASIZE(obj);
59068
59069#if defined(DUK_USE_OBJSIZES16)
59070 if (new_e_size > DUK_UINT16_MAX) {
59071 new_e_size = DUK_UINT16_MAX;
59072 }
59073 if (new_h_size > DUK_UINT16_MAX) {
59074 new_h_size = DUK_UINT16_MAX;
59075 }
59076 if (new_a_size > DUK_UINT16_MAX) {
59077 new_a_size = DUK_UINT16_MAX;
59078 }
59079#endif
59080 DUK_ASSERT(new_h_size == 0 || new_h_size >= new_e_size);
59081
59082 if (!(new_e_size >= new_e_size_minimum)) {
59084 DUK_WO_NORETURN(return;);
59085 }
59086
59087 duk_hobject_realloc_props(thr, obj, new_e_size, new_a_size, new_h_size, 0);
59088}
59089
59090/* Grow array part for a new highest array index. */
59091DUK_LOCAL void duk__grow_props_for_array_item(duk_hthread *thr, duk_hobject *obj, duk_uint32_t highest_arr_idx) {
59092 duk_uint32_t new_e_size;
59093 duk_uint32_t new_a_size;
59094 duk_uint32_t new_a_size_minimum;
59095 duk_uint32_t new_h_size;
59096
59097 DUK_ASSERT(thr != NULL);
59098 DUK_ASSERT(obj != NULL);
59099 DUK_ASSERT(highest_arr_idx >= DUK_HOBJECT_GET_ASIZE(obj));
59100
59101 new_e_size = DUK_HOBJECT_GET_ESIZE(obj);
59102 new_h_size = DUK_HOBJECT_GET_HSIZE(obj);
59103 new_a_size_minimum = highest_arr_idx + 1;
59104 new_a_size = highest_arr_idx + duk__get_min_grow_a(highest_arr_idx);
59105 DUK_ASSERT(new_a_size >= highest_arr_idx + 1); /* duk__get_min_grow_a() is always >= 1 */
59106
59107#if defined(DUK_USE_OBJSIZES16)
59108 if (new_e_size > DUK_UINT16_MAX) {
59109 new_e_size = DUK_UINT16_MAX;
59110 }
59111 if (new_h_size > DUK_UINT16_MAX) {
59112 new_h_size = DUK_UINT16_MAX;
59113 }
59114 if (new_a_size > DUK_UINT16_MAX) {
59115 new_a_size = DUK_UINT16_MAX;
59116 }
59117#endif
59118
59119 if (!(new_a_size >= new_a_size_minimum)) {
59121 DUK_WO_NORETURN(return;);
59122 }
59123
59124 duk_hobject_realloc_props(thr, obj, new_e_size, new_a_size, new_h_size, 0);
59125}
59126
59127/* Abandon array part, moving array entries into entries part.
59128 * This requires a props resize, which is a heavy operation.
59129 * We also compact the entries part while we're at it, although
59130 * this is not strictly required.
59131 */
59133 duk_uint32_t new_e_size_minimum;
59134 duk_uint32_t new_e_size;
59135 duk_uint32_t new_a_size;
59136 duk_uint32_t new_h_size;
59137 duk_uint32_t e_used; /* actually used, non-NULL keys */
59138 duk_uint32_t a_used;
59139 duk_uint32_t a_size;
59140
59141 DUK_ASSERT(thr != NULL);
59142 DUK_ASSERT(obj != NULL);
59143
59144 e_used = duk__count_used_e_keys(thr, obj);
59145 duk__compute_a_stats(thr, obj, &a_used, &a_size);
59146
59147 /*
59148 * Must guarantee all actually used array entries will fit into
59149 * new entry part. Add one growth step to ensure we don't run out
59150 * of space right away.
59151 */
59152
59153 new_e_size_minimum = e_used + a_used;
59154 new_e_size = new_e_size_minimum + duk__get_min_grow_e(new_e_size_minimum);
59155 new_a_size = 0;
59156#if defined(DUK_USE_HOBJECT_HASH_PART)
59157 new_h_size = duk__get_default_h_size(new_e_size);
59158#else
59159 new_h_size = 0;
59160#endif
59161
59162#if defined(DUK_USE_OBJSIZES16)
59163 if (new_e_size > DUK_UINT16_MAX) {
59164 new_e_size = DUK_UINT16_MAX;
59165 }
59166 if (new_h_size > DUK_UINT16_MAX) {
59167 new_h_size = DUK_UINT16_MAX;
59168 }
59169 if (new_a_size > DUK_UINT16_MAX) {
59170 new_a_size = DUK_UINT16_MAX;
59171 }
59172#endif
59173
59174 if (!(new_e_size >= new_e_size_minimum)) {
59176 DUK_WO_NORETURN(return;);
59177 }
59178
59179 DUK_DD(DUK_DDPRINT("abandon array part for hobject %p, "
59180 "array stats before: e_used=%ld, a_used=%ld, a_size=%ld; "
59181 "resize to e_size=%ld, a_size=%ld, h_size=%ld",
59182 (void *) obj,
59183 (long) e_used,
59184 (long) a_used,
59185 (long) a_size,
59186 (long) new_e_size,
59187 (long) new_a_size,
59188 (long) new_h_size));
59189
59190 duk_hobject_realloc_props(thr, obj, new_e_size, new_a_size, new_h_size, 1);
59191}
59192
59193/*
59194 * Compact an object. Minimizes allocation size for objects which are
59195 * not likely to be extended. This is useful for internal and non-
59196 * extensible objects, but can also be called for non-extensible objects.
59197 * May abandon the array part if it is computed to be too sparse.
59198 *
59199 * This call is relatively expensive, as it needs to scan both the
59200 * entries and the array part.
59201 *
59202 * The call may fail due to allocation error.
59203 */
59204
59206 duk_uint32_t e_size; /* currently used -> new size */
59207 duk_uint32_t a_size; /* currently required */
59208 duk_uint32_t a_used; /* actually used */
59209 duk_uint32_t h_size;
59210 duk_bool_t abandon_array;
59211
59212 DUK_ASSERT(thr != NULL);
59213 DUK_ASSERT(obj != NULL);
59214
59215#if defined(DUK_USE_ROM_OBJECTS)
59217 DUK_DD(DUK_DDPRINT("ignore attempt to compact a rom object"));
59218 return;
59219 }
59220#endif
59221
59222 e_size = duk__count_used_e_keys(thr, obj);
59223 duk__compute_a_stats(thr, obj, &a_used, &a_size);
59224
59225 DUK_DD(DUK_DDPRINT("compacting hobject, used e keys %ld, used a keys %ld, min a size %ld, "
59226 "resized array density would be: %ld/%ld = %lf",
59227 (long) e_size,
59228 (long) a_used,
59229 (long) a_size,
59230 (long) a_used,
59231 (long) a_size,
59232 (double) a_used / (double) a_size));
59233
59234 if (duk__abandon_array_density_check(a_used, a_size)) {
59235 DUK_DD(DUK_DDPRINT("decided to abandon array during compaction, a_used=%ld, a_size=%ld",
59236 (long) a_used,
59237 (long) a_size));
59238 abandon_array = 1;
59239 e_size += a_used;
59240 a_size = 0;
59241 } else {
59242 DUK_DD(DUK_DDPRINT("decided to keep array during compaction"));
59243 abandon_array = 0;
59244 }
59245
59246#if defined(DUK_USE_HOBJECT_HASH_PART)
59247 if (e_size >= DUK_USE_HOBJECT_HASH_PROP_LIMIT) {
59248 h_size = duk__get_default_h_size(e_size);
59249 } else {
59250 h_size = 0;
59251 }
59252#else
59253 h_size = 0;
59254#endif
59256 DUK_DD(DUK_DDPRINT("compacting hobject -> new e_size %ld, new a_size=%ld, new h_size=%ld, abandon_array=%ld",
59257 (long) e_size,
59258 (long) a_size,
59259 (long) h_size,
59260 (long) abandon_array));
59261
59262 duk_hobject_realloc_props(thr, obj, e_size, a_size, h_size, abandon_array);
59263}
59264
59265/*
59266 * Find an existing key from entry part either by linear scan or by
59267 * using the hash index (if it exists).
59268 *
59269 * Sets entry index (and possibly the hash index) to output variables,
59270 * which allows the caller to update the entry and hash entries in-place.
59271 * If entry is not found, both values are set to -1. If entry is found
59272 * but there is no hash part, h_idx is set to -1.
59273 */
59274
59276duk_hobject_find_entry(duk_heap *heap, duk_hobject *obj, duk_hstring *key, duk_int_t *e_idx, duk_int_t *h_idx) {
59277 DUK_ASSERT(obj != NULL);
59278 DUK_ASSERT(key != NULL);
59279 DUK_ASSERT(e_idx != NULL);
59280 DUK_ASSERT(h_idx != NULL);
59281 DUK_UNREF(heap);
59282
59283 if (DUK_LIKELY(DUK_HOBJECT_GET_HSIZE(obj) == 0)) {
59284 /* Linear scan: more likely because most objects are small.
59285 * This is an important fast path.
59286 *
59287 * XXX: this might be worth inlining for property lookups.
59288 */
59291 duk_hstring **h_keys_base;
59292 DUK_DDD(DUK_DDDPRINT("duk_hobject_find_entry() using linear scan for lookup"));
59293
59294 h_keys_base = DUK_HOBJECT_E_GET_KEY_BASE(heap, obj);
59295 n = DUK_HOBJECT_GET_ENEXT(obj);
59296 for (i = 0; i < n; i++) {
59297 if (h_keys_base[i] == key) {
59298 *e_idx = (duk_int_t) i;
59299 *h_idx = -1;
59300 return 1;
59301 }
59302 }
59303 }
59304#if defined(DUK_USE_HOBJECT_HASH_PART)
59305 else {
59306 /* hash lookup */
59307 duk_uint32_t n;
59308 duk_uint32_t i, step;
59309 duk_uint32_t *h_base;
59310 duk_uint32_t mask;
59311
59312 DUK_DDD(DUK_DDDPRINT("duk_hobject_find_entry() using hash part for lookup"));
59313
59314 h_base = DUK_HOBJECT_H_GET_BASE(heap, obj);
59315 n = DUK_HOBJECT_GET_HSIZE(obj);
59316 mask = n - 1;
59317 i = DUK_HSTRING_GET_HASH(key) & mask;
59318 step = 1; /* Cache friendly but clustering prone. */
59319
59320 for (;;) {
59321 duk_uint32_t t;
59322
59323 DUK_ASSERT_DISABLE(i >= 0); /* unsigned */
59325 t = h_base[i];
59327 (t < DUK_HOBJECT_GET_ESIZE(obj))); /* t >= 0 always true, unsigned */
59328
59329 if (t == DUK__HASH_UNUSED) {
59330 break;
59331 } else if (t == DUK__HASH_DELETED) {
59332 DUK_DDD(DUK_DDDPRINT("lookup miss (deleted) i=%ld, t=%ld", (long) i, (long) t));
59333 } else {
59335 if (DUK_HOBJECT_E_GET_KEY(heap, obj, t) == key) {
59336 DUK_DDD(
59337 DUK_DDDPRINT("lookup hit i=%ld, t=%ld -> key %p", (long) i, (long) t, (void *) key));
59338 *e_idx = (duk_int_t) t;
59339 *h_idx = (duk_int_t) i;
59340 return 1;
59341 }
59342 DUK_DDD(DUK_DDDPRINT("lookup miss i=%ld, t=%ld", (long) i, (long) t));
59343 }
59344 i = (i + step) & mask;
59345
59346 /* Guaranteed to finish (hash is larger than #props). */
59347 }
59348 }
59349#endif /* DUK_USE_HOBJECT_HASH_PART */
59350
59351 /* Not found, leave e_idx and h_idx unset. */
59352 return 0;
59353}
59354
59355/* For internal use: get non-accessor entry value */
59358 duk_int_t h_idx;
59359
59360 DUK_ASSERT(obj != NULL);
59361 DUK_ASSERT(key != NULL);
59362 DUK_UNREF(heap);
59363
59364 if (duk_hobject_find_entry(heap, obj, key, &e_idx, &h_idx)) {
59365 DUK_ASSERT(e_idx >= 0);
59366 if (!DUK_HOBJECT_E_SLOT_IS_ACCESSOR(heap, obj, e_idx)) {
59367 return DUK_HOBJECT_E_GET_VALUE_TVAL_PTR(heap, obj, e_idx);
59368 }
59369 }
59370 return NULL;
59371}
59372
59374 return duk_hobject_find_entry_tval_ptr(heap, obj, DUK_HEAP_GET_STRING(heap, stridx));
59375}
59376
59377/* For internal use: get non-accessor entry value and attributes */
59379 duk_hobject *obj,
59380 duk_hstring *key,
59381 duk_uint_t *out_attrs) {
59382 duk_int_t e_idx;
59383 duk_int_t h_idx;
59384
59385 DUK_ASSERT(obj != NULL);
59386 DUK_ASSERT(key != NULL);
59387 DUK_ASSERT(out_attrs != NULL);
59388 DUK_UNREF(heap);
59389
59390 if (duk_hobject_find_entry(heap, obj, key, &e_idx, &h_idx)) {
59391 DUK_ASSERT(e_idx >= 0);
59392 if (!DUK_HOBJECT_E_SLOT_IS_ACCESSOR(heap, obj, e_idx)) {
59393 *out_attrs = DUK_HOBJECT_E_GET_FLAGS(heap, obj, e_idx);
59394 return DUK_HOBJECT_E_GET_VALUE_TVAL_PTR(heap, obj, e_idx);
59395 }
59396 }
59397 /* If not found, out_attrs is left unset. */
59398 return NULL;
59399}
59400
59401/* For internal use: get array part value */
59403 duk_tval *tv;
59404
59405 DUK_ASSERT(obj != NULL);
59407
59408 if (!DUK_HOBJECT_HAS_ARRAY_PART(obj)) {
59409 return NULL;
59410 }
59411 if (i >= DUK_HOBJECT_GET_ASIZE(obj)) {
59412 return NULL;
59413 }
59414 tv = DUK_HOBJECT_A_GET_VALUE_PTR(heap, obj, i);
59415 return tv;
59416}
59417
59418/*
59419 * Allocate and initialize a new entry, resizing the properties allocation
59420 * if necessary. Returns entry index (e_idx) or throws an error if alloc fails.
59421 *
59422 * Sets the key of the entry (increasing the key's refcount), and updates
59423 * the hash part if it exists. Caller must set value and flags, and update
59424 * the entry value refcount. A decref for the previous value is not necessary.
59425 */
59426
59428 duk_uint32_t idx;
59429
59430 DUK_ASSERT(thr != NULL);
59431 DUK_ASSERT(obj != NULL);
59432 DUK_ASSERT(key != NULL);
59434
59435#if defined(DUK_USE_ASSERTIONS)
59436 /* key must not already exist in entry part */
59437 {
59439 for (i = 0; i < DUK_HOBJECT_GET_ENEXT(obj); i++) {
59440 DUK_ASSERT(DUK_HOBJECT_E_GET_KEY(thr->heap, obj, i) != key);
59441 }
59442 }
59443#endif
59444
59446 /* only need to guarantee 1 more slot, but allocation growth is in chunks */
59447 DUK_DDD(DUK_DDDPRINT("entry part full, allocate space for one more entry"));
59449 }
59451 idx = DUK_HOBJECT_POSTINC_ENEXT(obj);
59452
59453 /* previous value is assumed to be garbage, so don't touch it */
59454 DUK_HOBJECT_E_SET_KEY(thr->heap, obj, idx, key);
59455 DUK_HSTRING_INCREF(thr, key);
59456
59457#if defined(DUK_USE_HOBJECT_HASH_PART)
59458 if (DUK_UNLIKELY(DUK_HOBJECT_GET_HSIZE(obj) > 0)) {
59459 duk_uint32_t n, mask;
59460 duk_uint32_t i, step;
59461 duk_uint32_t *h_base = DUK_HOBJECT_H_GET_BASE(thr->heap, obj);
59462
59463 n = DUK_HOBJECT_GET_HSIZE(obj);
59464 mask = n - 1;
59465 i = DUK_HSTRING_GET_HASH(key) & mask;
59466 step = 1; /* Cache friendly but clustering prone. */
59467
59468 for (;;) {
59469 duk_uint32_t t = h_base[i];
59470 if (t == DUK__HASH_UNUSED || t == DUK__HASH_DELETED) {
59471 DUK_DDD(DUK_DDDPRINT("duk__hobject_alloc_entry_checked() inserted key into hash part, %ld -> %ld",
59472 (long) i,
59473 (long) idx));
59474 DUK_ASSERT_DISABLE(i >= 0); /* unsigned */
59476 DUK_ASSERT_DISABLE(idx >= 0);
59478 h_base[i] = idx;
59479 break;
59480 }
59481 DUK_DDD(DUK_DDDPRINT("duk__hobject_alloc_entry_checked() miss %ld", (long) i));
59482 i = (i + step) & mask;
59483
59484 /* Guaranteed to finish (hash is larger than #props). */
59486 }
59487#endif /* DUK_USE_HOBJECT_HASH_PART */
59488
59489 /* Note: we could return the hash index here too, but it's not
59490 * needed right now.
59491 */
59492
59493 DUK_ASSERT_DISABLE(idx >= 0);
59496 return (duk_int_t) idx;
59497}
59498
59499/*
59500 * Object internal value
59501 *
59502 * Returned value is guaranteed to be reachable / incref'd, caller does not need
59503 * to incref OR decref. No proxies or accessors are invoked, no prototype walk.
59504 */
59508}
59509
59511 duk_tval *tv;
59512
59513 DUK_ASSERT(heap != NULL);
59514 DUK_ASSERT(obj != NULL);
59517 if (tv != NULL) {
59519 DUK_ASSERT(h != NULL);
59520 return h;
59521 }
59522
59523 return NULL;
59524}
59525
59527 duk_hstring *h;
59530 if (h != NULL) {
59532 }
59533 return h;
59534}
59535
59537 duk_tval *tv;
59538 duk_hobject *h;
59540 tv = duk_hobject_find_entry_tval_ptr_stridx(heap, obj, stridx);
59541 if (tv != NULL && DUK_TVAL_IS_OBJECT(tv)) {
59542 h = DUK_TVAL_GET_OBJECT(tv);
59543 DUK_ASSERT(h != NULL);
59544 return h;
59545 }
59546 return NULL;
59547}
59548
59550 duk_harray *h;
59551
59553 if (h != NULL) {
59556 }
59557 return h;
59558}
59559
59561 duk_hobject *h;
59562
59564 return h;
59565}
59566
59567/*
59568 * Arguments handling helpers (argument map mainly).
59569 *
59570 * An arguments object has exotic behavior for some numeric indices.
59571 * Accesses may translate to identifier operations which may have
59572 * arbitrary side effects (potentially invalidating any duk_tval
59573 * pointers).
59574 */
59575
59576/* Lookup 'key' from arguments internal 'map', perform a variable lookup
59577 * if mapped, and leave the result on top of stack (and return non-zero).
59578 * Used in E5 Section 10.6 algorithms [[Get]] and [[GetOwnProperty]].
59579 */
59582 duk_hobject *obj,
59583 duk_hstring *key,
59584 duk_propdesc *temp_desc,
59585 duk_hobject **out_map,
59586 duk_hobject **out_varenv) {
59587 duk_hobject *map;
59588 duk_hobject *varenv;
59589 duk_bool_t rc;
59590
59592
59593 DUK_DDD(DUK_DDDPRINT("arguments map lookup: thr=%p, obj=%p, key=%p, temp_desc=%p "
59594 "(obj -> %!O, key -> %!O)",
59595 (void *) thr,
59596 (void *) obj,
59597 (void *) key,
59598 (void *) temp_desc,
59599 (duk_heaphdr *) obj,
59600 (duk_heaphdr *) key));
59601
59603 DUK_DDD(DUK_DDDPRINT("-> no 'map'"));
59604 return 0;
59605 }
59606
59607 map = duk_require_hobject(thr, -1);
59608 DUK_ASSERT(map != NULL);
59609 duk_pop_unsafe(thr); /* map is reachable through obj */
59610
59611 if (!duk_hobject_get_own_propdesc(thr, map, key, temp_desc, DUK_GETDESC_FLAG_PUSH_VALUE)) {
59612 DUK_DDD(DUK_DDDPRINT("-> 'map' exists, but key not in map"));
59613 return 0;
59614 }
59615
59616 /* [... varname] */
59617 DUK_DDD(DUK_DDDPRINT("-> 'map' exists, and contains key, key is mapped to argument/variable binding %!T",
59618 (duk_tval *) duk_get_tval(thr, -1)));
59619 DUK_ASSERT(duk_is_string(thr, -1)); /* guaranteed when building arguments */
59621 /* get varenv for varname (callee's declarative lexical environment) */
59623 DUK_UNREF(rc);
59624 DUK_ASSERT(rc != 0); /* arguments MUST have an initialized lexical environment reference */
59625 varenv = duk_require_hobject(thr, -1);
59626 DUK_ASSERT(varenv != NULL);
59627 duk_pop_unsafe(thr); /* varenv remains reachable through 'obj' */
59628
59629 DUK_DDD(DUK_DDDPRINT("arguments varenv is: %!dO", (duk_heaphdr *) varenv));
59630
59631 /* success: leave varname in stack */
59632 *out_map = map;
59633 *out_varenv = varenv;
59634 return 1; /* [... varname] */
59635}
59636
59637/* Lookup 'key' from arguments internal 'map', and leave replacement value
59638 * on stack top if mapped (and return non-zero).
59639 * Used in E5 Section 10.6 algorithm for [[GetOwnProperty]] (used by [[Get]]).
59640 */
59642 duk_hobject *obj,
59643 duk_hstring *key,
59644 duk_propdesc *temp_desc) {
59645 duk_hobject *map;
59646 duk_hobject *varenv;
59647 duk_hstring *varname;
59648
59650
59651 if (!duk__lookup_arguments_map(thr, obj, key, temp_desc, &map, &varenv)) {
59652 DUK_DDD(DUK_DDDPRINT("arguments: key not mapped, no exotic get behavior"));
59653 return 0;
59654 }
59655
59656 /* [... varname] */
59657
59658 varname = duk_require_hstring(thr, -1);
59659 DUK_ASSERT(varname != NULL);
59660 duk_pop_unsafe(thr); /* varname is still reachable */
59661
59662 DUK_DDD(DUK_DDDPRINT("arguments object automatic getvar for a bound variable; "
59663 "key=%!O, varname=%!O",
59664 (duk_heaphdr *) key,
59665 (duk_heaphdr *) varname));
59666
59667 (void) duk_js_getvar_envrec(thr, varenv, varname, 1 /*throw*/);
59668
59669 /* [... value this_binding] */
59670
59671 duk_pop_unsafe(thr);
59672
59673 /* leave result on stack top */
59674 return 1;
59675}
59676
59677/* Lookup 'key' from arguments internal 'map', perform a variable write if mapped.
59678 * Used in E5 Section 10.6 algorithm for [[DefineOwnProperty]] (used by [[Put]]).
59679 * Assumes stack top contains 'put' value (which is NOT popped).
59680 */
59682 duk_hobject *obj,
59683 duk_hstring *key,
59684 duk_propdesc *temp_desc,
59685 duk_bool_t throw_flag) {
59686 duk_hobject *map;
59687 duk_hobject *varenv;
59688 duk_hstring *varname;
59689
59691
59692 if (!duk__lookup_arguments_map(thr, obj, key, temp_desc, &map, &varenv)) {
59693 DUK_DDD(DUK_DDDPRINT("arguments: key not mapped, no exotic put behavior"));
59694 return;
59695 }
59696
59697 /* [... put_value varname] */
59698
59699 varname = duk_require_hstring(thr, -1);
59700 DUK_ASSERT(varname != NULL);
59701 duk_pop_unsafe(thr); /* varname is still reachable */
59702
59703 DUK_DDD(DUK_DDDPRINT("arguments object automatic putvar for a bound variable; "
59704 "key=%!O, varname=%!O, value=%!T",
59705 (duk_heaphdr *) key,
59706 (duk_heaphdr *) varname,
59708
59709 /* [... put_value] */
59710
59711 /*
59712 * Note: although arguments object variable mappings are only established
59713 * for non-strict functions (and a call to a non-strict function created
59714 * the arguments object in question), an inner strict function may be doing
59715 * the actual property write. Hence the throw_flag applied here comes from
59716 * the property write call.
59717 */
59718
59719 duk_js_putvar_envrec(thr, varenv, varname, duk_require_tval(thr, -1), throw_flag);
59720
59721 /* [... put_value] */
59722}
59723
59724/* Lookup 'key' from arguments internal 'map', delete mapping if found.
59725 * Used in E5 Section 10.6 algorithm for [[Delete]]. Note that the
59726 * variable/argument itself (where the map points) is not deleted.
59727 */
59729 duk_hobject *map;
59730
59732
59734 DUK_DDD(DUK_DDDPRINT("arguments: key not mapped, no exotic delete behavior"));
59735 return;
59736 }
59737
59738 map = duk_require_hobject(thr, -1);
59739 DUK_ASSERT(map != NULL);
59740 duk_pop_unsafe(thr); /* map is reachable through obj */
59741
59742 DUK_DDD(DUK_DDDPRINT("-> have 'map', delete key %!O from map (if exists)); ignore result", (duk_heaphdr *) key));
59743
59744 /* Note: no recursion issue, we can trust 'map' to behave */
59746 DUK_DDD(DUK_DDDPRINT("map before deletion: %!O", (duk_heaphdr *) map));
59747 (void) duk_hobject_delprop_raw(thr, map, key, 0); /* ignore result */
59748 DUK_DDD(DUK_DDDPRINT("map after deletion: %!O", (duk_heaphdr *) map));
59749}
59750
59751/*
59752 * ECMAScript compliant [[GetOwnProperty]](P), for internal use only.
59753 *
59754 * If property is found:
59755 * - Fills descriptor fields to 'out_desc'
59756 * - If DUK_GETDESC_FLAG_PUSH_VALUE is set, pushes a value related to the
59757 * property onto the stack ('undefined' for accessor properties).
59758 * - Returns non-zero
59759 *
59760 * If property is not found:
59761 * - 'out_desc' is left in untouched state (possibly garbage)
59762 * - Nothing is pushed onto the stack (not even with DUK_GETDESC_FLAG_PUSH_VALUE
59763 * set)
59764 * - Returns zero
59765 *
59766 * Notes:
59767 *
59768 * - Getting a property descriptor may cause an allocation (and hence
59769 * GC) to take place, hence reachability and refcount of all related
59770 * values matter. Reallocation of value stack, properties, etc may
59771 * invalidate many duk_tval pointers (concretely, those which reside
59772 * in memory areas subject to reallocation). However, heap object
59773 * pointers are never affected (heap objects have stable pointers).
59774 *
59775 * - The value of a plain property is always reachable and has a non-zero
59776 * reference count.
59777 *
59778 * - The value of a virtual property is not necessarily reachable from
59779 * elsewhere and may have a refcount of zero. Hence we push it onto
59780 * the valstack for the caller, which ensures it remains reachable
59781 * while it is needed.
59782 *
59783 * - There are no virtual accessor properties. Hence, all getters and
59784 * setters are always related to concretely stored properties, which
59785 * ensures that the get/set functions in the resulting descriptor are
59786 * reachable and have non-zero refcounts. Should there be virtual
59787 * accessor properties later, this would need to change.
59788 */
59789
59791 duk_hobject *obj,
59792 duk_hstring *key,
59793 duk_uint32_t arr_idx,
59794 duk_propdesc *out_desc,
59795 duk_small_uint_t flags) {
59796 duk_tval *tv;
59797
59798 DUK_DDD(DUK_DDDPRINT("duk_hobject_get_own_propdesc: thr=%p, obj=%p, key=%p, out_desc=%p, flags=%lx, "
59799 "arr_idx=%ld (obj -> %!O, key -> %!O)",
59800 (void *) thr,
59801 (void *) obj,
59802 (void *) key,
59803 (void *) out_desc,
59804 (long) flags,
59805 (long) arr_idx,
59806 (duk_heaphdr *) obj,
59807 (duk_heaphdr *) key));
59808
59809 DUK_ASSERT(thr != NULL);
59810 DUK_ASSERT(thr->heap != NULL);
59811 DUK_ASSERT(obj != NULL);
59812 DUK_ASSERT(key != NULL);
59813 DUK_ASSERT(out_desc != NULL);
59815
59816 DUK_STATS_INC(thr->heap, stats_getownpropdesc_count);
59817
59818 /* Each code path returning 1 (= found) must fill in all the output
59819 * descriptor fields. We don't do it beforehand because it'd be
59820 * unnecessary work if the property isn't found and would happen
59821 * multiple times for an inheritance chain.
59822 */
59823 DUK_ASSERT_SET_GARBAGE(out_desc, sizeof(*out_desc));
59824#if 0
59825 out_desc->flags = 0;
59826 out_desc->get = NULL;
59827 out_desc->set = NULL;
59828 out_desc->e_idx = -1;
59829 out_desc->h_idx = -1;
59830 out_desc->a_idx = -1;
59831#endif
59832
59833 /*
59834 * Try entries part first because it's the common case.
59835 *
59836 * Array part lookups are usually handled by the array fast path, and
59837 * are not usually inherited. Array and entry parts never contain the
59838 * same keys so the entry part vs. array part order doesn't matter.
59839 */
59840
59841 if (duk_hobject_find_entry(thr->heap, obj, key, &out_desc->e_idx, &out_desc->h_idx)) {
59842 duk_int_t e_idx = out_desc->e_idx;
59843 DUK_ASSERT(out_desc->e_idx >= 0);
59844 out_desc->a_idx = -1;
59845 out_desc->flags = DUK_HOBJECT_E_GET_FLAGS(thr->heap, obj, e_idx);
59846 out_desc->get = NULL;
59847 out_desc->set = NULL;
59849 DUK_DDD(DUK_DDDPRINT("-> found accessor property in entry part"));
59850 out_desc->get = DUK_HOBJECT_E_GET_VALUE_GETTER(thr->heap, obj, e_idx);
59851 out_desc->set = DUK_HOBJECT_E_GET_VALUE_SETTER(thr->heap, obj, e_idx);
59852 if (flags & DUK_GETDESC_FLAG_PUSH_VALUE) {
59853 /* a dummy undefined value is pushed to make valstack
59854 * behavior uniform for caller
59855 */
59856 duk_push_undefined(thr);
59857 }
59858 } else {
59859 DUK_DDD(DUK_DDDPRINT("-> found plain property in entry part"));
59860 tv = DUK_HOBJECT_E_GET_VALUE_TVAL_PTR(thr->heap, obj, e_idx);
59861 if (flags & DUK_GETDESC_FLAG_PUSH_VALUE) {
59862 duk_push_tval(thr, tv);
59863 }
59864 }
59865 goto prop_found;
59866 }
59867
59868 /*
59869 * Try array part.
59870 */
59871
59872 if (DUK_HOBJECT_HAS_ARRAY_PART(obj) && arr_idx != DUK__NO_ARRAY_INDEX) {
59873 if (arr_idx < DUK_HOBJECT_GET_ASIZE(obj)) {
59874 tv = DUK_HOBJECT_A_GET_VALUE_PTR(thr->heap, obj, arr_idx);
59875 if (!DUK_TVAL_IS_UNUSED(tv)) {
59876 DUK_DDD(DUK_DDDPRINT("-> found in array part"));
59877 if (flags & DUK_GETDESC_FLAG_PUSH_VALUE) {
59878 duk_push_tval(thr, tv);
59879 }
59880 /* implicit attributes */
59881 out_desc->flags =
59883 out_desc->get = NULL;
59884 out_desc->set = NULL;
59885 out_desc->e_idx = -1;
59886 out_desc->h_idx = -1;
59887 out_desc->a_idx = (duk_int_t) arr_idx; /* XXX: limit 2G due to being signed */
59888 goto prop_found;
59889 }
59890 }
59891 }
59892
59893 DUK_DDD(DUK_DDDPRINT("-> not found as a concrete property"));
59894
59895 /*
59896 * Not found as a concrete property, check for virtual properties.
59897 */
59898
59900 /* Quick skip. */
59901 goto prop_not_found;
59902 }
59903
59905 duk_harray *a;
59906
59907 DUK_DDD(DUK_DDDPRINT("array object exotic property get for key: %!O, arr_idx: %ld",
59908 (duk_heaphdr *) key,
59909 (long) arr_idx));
59910
59911 a = (duk_harray *) obj;
59913
59914 if (key == DUK_HTHREAD_STRING_LENGTH(thr)) {
59915 DUK_DDD(DUK_DDDPRINT("-> found, key is 'length', length exotic behavior"));
59916
59917 if (flags & DUK_GETDESC_FLAG_PUSH_VALUE) {
59918 duk_push_uint(thr, (duk_uint_t) a->length);
59919 }
59920 out_desc->flags = DUK_PROPDESC_FLAG_VIRTUAL;
59922 out_desc->flags |= DUK_PROPDESC_FLAG_WRITABLE;
59923 }
59924 out_desc->get = NULL;
59925 out_desc->set = NULL;
59926 out_desc->e_idx = -1;
59927 out_desc->h_idx = -1;
59928 out_desc->a_idx = -1;
59929
59931 goto prop_found_noexotic; /* cannot be arguments exotic */
59932 }
59933 } else if (DUK_HOBJECT_HAS_EXOTIC_STRINGOBJ(obj)) {
59934 DUK_DDD(DUK_DDDPRINT("string object exotic property get for key: %!O, arr_idx: %ld",
59935 (duk_heaphdr *) key,
59936 (long) arr_idx));
59937
59938 /* XXX: charlen; avoid multiple lookups? */
59939
59940 if (arr_idx != DUK__NO_ARRAY_INDEX) {
59941 duk_hstring *h_val;
59942
59943 DUK_DDD(DUK_DDDPRINT("array index exists"));
59944
59946 DUK_ASSERT(h_val);
59947 if (arr_idx < DUK_HSTRING_GET_CHARLEN(h_val)) {
59948 DUK_DDD(DUK_DDDPRINT("-> found, array index inside string"));
59949 if (flags & DUK_GETDESC_FLAG_PUSH_VALUE) {
59950 duk_push_hstring(thr, h_val);
59951 duk_substring(thr, -1, arr_idx, arr_idx + 1); /* [str] -> [substr] */
59952 }
59953 out_desc->flags = DUK_PROPDESC_FLAG_ENUMERABLE | /* E5 Section 15.5.5.2 */
59955 out_desc->get = NULL;
59956 out_desc->set = NULL;
59957 out_desc->e_idx = -1;
59958 out_desc->h_idx = -1;
59959 out_desc->a_idx = -1;
59960
59962 goto prop_found_noexotic; /* cannot be arguments exotic */
59963 } else {
59964 /* index is above internal string length -> property is fully normal */
59965 DUK_DDD(DUK_DDDPRINT("array index outside string -> normal property"));
59966 }
59967 } else if (key == DUK_HTHREAD_STRING_LENGTH(thr)) {
59968 duk_hstring *h_val;
59969
59970 DUK_DDD(DUK_DDDPRINT("-> found, key is 'length', length exotic behavior"));
59971
59973 DUK_ASSERT(h_val != NULL);
59974 if (flags & DUK_GETDESC_FLAG_PUSH_VALUE) {
59976 }
59977 out_desc->flags = DUK_PROPDESC_FLAG_VIRTUAL; /* E5 Section 15.5.5.1 */
59978 out_desc->get = NULL;
59979 out_desc->set = NULL;
59980 out_desc->e_idx = -1;
59981 out_desc->h_idx = -1;
59982 out_desc->a_idx = -1;
59983
59985 goto prop_found_noexotic; /* cannot be arguments exotic */
59986 }
59987 }
59988#if defined(DUK_USE_BUFFEROBJECT_SUPPORT)
59989 else if (DUK_HOBJECT_IS_BUFOBJ(obj)) {
59990 duk_hbufobj *h_bufobj;
59991 duk_uint_t byte_off;
59992 duk_small_uint_t elem_size;
59993
59994 h_bufobj = (duk_hbufobj *) obj;
59995 DUK_HBUFOBJ_ASSERT_VALID(h_bufobj);
59996 DUK_DDD(DUK_DDDPRINT("bufobj property get for key: %!O, arr_idx: %ld", (duk_heaphdr *) key, (long) arr_idx));
59997
59998 if (arr_idx != DUK__NO_ARRAY_INDEX && DUK_HBUFOBJ_HAS_VIRTUAL_INDICES(h_bufobj)) {
59999 DUK_DDD(DUK_DDDPRINT("array index exists"));
60000
60001 /* Careful with wrapping: arr_idx upshift may easily wrap, whereas
60002 * length downshift won't.
60003 */
60004 if (arr_idx < (h_bufobj->length >> h_bufobj->shift)) {
60005 byte_off = arr_idx << h_bufobj->shift; /* no wrap assuming h_bufobj->length is valid */
60006 elem_size = (duk_small_uint_t) (1U << h_bufobj->shift);
60007 if (flags & DUK_GETDESC_FLAG_PUSH_VALUE) {
60008 duk_uint8_t *data;
60009
60010 if (h_bufobj->buf != NULL &&
60011 DUK_HBUFOBJ_VALID_BYTEOFFSET_EXCL(h_bufobj, byte_off + elem_size)) {
60012 data = (duk_uint8_t *) DUK_HBUFFER_GET_DATA_PTR(thr->heap, h_bufobj->buf) +
60013 h_bufobj->offset + byte_off;
60014 duk_hbufobj_push_validated_read(thr, h_bufobj, data, elem_size);
60015 } else {
60016 DUK_D(DUK_DPRINT("bufobj access out of underlying buffer, ignoring (read zero)"));
60017 duk_push_uint(thr, 0);
60018 }
60019 }
60022 /* ArrayBuffer indices are non-standard and are
60023 * non-enumerable to avoid their serialization.
60024 */
60026 }
60027 out_desc->get = NULL;
60028 out_desc->set = NULL;
60029 out_desc->e_idx = -1;
60030 out_desc->h_idx = -1;
60031 out_desc->a_idx = -1;
60032
60034 goto prop_found_noexotic; /* cannot be e.g. arguments exotic, since exotic 'traits' are mutually
60035 exclusive */
60036 } else {
60037 /* index is above internal buffer length -> property is fully normal */
60038 DUK_DDD(DUK_DDDPRINT("array index outside buffer -> normal property"));
60039 }
60040 } else if (key == DUK_HTHREAD_STRING_LENGTH(thr) && DUK_HBUFOBJ_HAS_VIRTUAL_INDICES(h_bufobj)) {
60041 DUK_DDD(DUK_DDDPRINT("-> found, key is 'length', length exotic behavior"));
60042
60043 if (flags & DUK_GETDESC_FLAG_PUSH_VALUE) {
60044 /* Length in elements: take into account shift, but
60045 * intentionally don't check the underlying buffer here.
60046 */
60047 duk_push_uint(thr, h_bufobj->length >> h_bufobj->shift);
60048 }
60049 out_desc->flags = DUK_PROPDESC_FLAG_VIRTUAL;
60050 out_desc->get = NULL;
60051 out_desc->set = NULL;
60052 out_desc->e_idx = -1;
60053 out_desc->h_idx = -1;
60054 out_desc->a_idx = -1;
60055
60057 goto prop_found_noexotic; /* cannot be arguments exotic */
60058 }
60059 }
60060#endif /* DUK_USE_BUFFEROBJECT_SUPPORT */
60061
60062 /* Array properties have exotic behavior but they are concrete,
60063 * so no special handling here.
60064 *
60065 * Arguments exotic behavior (E5 Section 10.6, [[GetOwnProperty]]
60066 * is only relevant as a post-check implemented below; hence no
60067 * check here.
60068 */
60069
60070 /*
60071 * Not found as concrete or virtual.
60072 */
60073
60074prop_not_found:
60075 DUK_DDD(DUK_DDDPRINT("-> not found (virtual, entry part, or array part)"));
60076 DUK_STATS_INC(thr->heap, stats_getownpropdesc_miss);
60077 return 0;
60078
60079 /*
60080 * Found.
60081 *
60082 * Arguments object has exotic post-processing, see E5 Section 10.6,
60083 * description of [[GetOwnProperty]] variant for arguments.
60084 */
60085
60086prop_found:
60087 DUK_DDD(DUK_DDDPRINT("-> property found, checking for arguments exotic post-behavior"));
60088
60089 /* Notes:
60090 * - Only numbered indices are relevant, so arr_idx fast reject is good
60091 * (this is valid unless there are more than 4**32-1 arguments).
60092 * - Since variable lookup has no side effects, this can be skipped if
60093 * DUK_GETDESC_FLAG_PUSH_VALUE is not set.
60094 */
60095
60097 (flags & DUK_GETDESC_FLAG_PUSH_VALUE))) {
60098 duk_propdesc temp_desc;
60099
60100 /* Magically bound variable cannot be an accessor. However,
60101 * there may be an accessor property (or a plain property) in
60102 * place with magic behavior removed. This happens e.g. when
60103 * a magic property is redefined with defineProperty().
60104 * Cannot assert for "not accessor" here.
60105 */
60106
60107 /* replaces top of stack with new value if necessary */
60109
60110 /* This can perform a variable lookup but only into a declarative
60111 * environment which has no side effects.
60112 */
60113 if (duk__check_arguments_map_for_get(thr, obj, key, &temp_desc)) {
60114 DUK_DDD(DUK_DDDPRINT("-> arguments exotic behavior overrides result: %!T -> %!T",
60115 (duk_tval *) duk_get_tval(thr, -2),
60116 (duk_tval *) duk_get_tval(thr, -1)));
60117 /* [... old_result result] -> [... result] */
60118 duk_remove_m2(thr);
60119 }
60120 }
60121
60122prop_found_noexotic:
60123 DUK_STATS_INC(thr->heap, stats_getownpropdesc_hit);
60124 return 1;
60125}
60126
60129 DUK_ASSERT(thr != NULL);
60130 DUK_ASSERT(obj != NULL);
60131 DUK_ASSERT(key != NULL);
60132 DUK_ASSERT(out_desc != NULL);
60134
60135 return duk__get_own_propdesc_raw(thr, obj, key, DUK_HSTRING_GET_ARRIDX_SLOW(key), out_desc, flags);
60136}
60138/*
60139 * ECMAScript compliant [[GetProperty]](P), for internal use only.
60140 *
60141 * If property is found:
60142 * - Fills descriptor fields to 'out_desc'
60143 * - If DUK_GETDESC_FLAG_PUSH_VALUE is set, pushes a value related to the
60144 * property onto the stack ('undefined' for accessor properties).
60145 * - Returns non-zero
60146 *
60147 * If property is not found:
60148 * - 'out_desc' is left in untouched state (possibly garbage)
60149 * - Nothing is pushed onto the stack (not even with DUK_GETDESC_FLAG_PUSH_VALUE
60150 * set)
60151 * - Returns zero
60152 *
60153 * May cause arbitrary side effects and invalidate (most) duk_tval
60154 * pointers.
60155 */
60156
60159 duk_hobject *curr;
60160 duk_uint32_t arr_idx;
60161 duk_uint_t sanity;
60162
60163 DUK_ASSERT(thr != NULL);
60164 DUK_ASSERT(thr->heap != NULL);
60165 DUK_ASSERT(obj != NULL);
60166 DUK_ASSERT(key != NULL);
60167 DUK_ASSERT(out_desc != NULL);
60169
60170 DUK_STATS_INC(thr->heap, stats_getpropdesc_count);
60171
60172 arr_idx = DUK_HSTRING_GET_ARRIDX_FAST(key);
60173
60174 DUK_DDD(DUK_DDDPRINT("duk__get_propdesc: thr=%p, obj=%p, key=%p, out_desc=%p, flags=%lx, "
60175 "arr_idx=%ld (obj -> %!O, key -> %!O)",
60176 (void *) thr,
60177 (void *) obj,
60178 (void *) key,
60179 (void *) out_desc,
60180 (long) flags,
60181 (long) arr_idx,
60182 (duk_heaphdr *) obj,
60183 (duk_heaphdr *) key));
60184
60185 curr = obj;
60186 DUK_ASSERT(curr != NULL);
60188 do {
60189 if (duk__get_own_propdesc_raw(thr, curr, key, arr_idx, out_desc, flags)) {
60190 /* stack contains value (if requested), 'out_desc' is set */
60191 DUK_STATS_INC(thr->heap, stats_getpropdesc_hit);
60192 return 1;
60193 }
60194
60195 /* not found in 'curr', next in prototype chain; impose max depth */
60196 if (DUK_UNLIKELY(sanity-- == 0)) {
60198 /* treat like property not found */
60199 break;
60200 } else {
60202 DUK_WO_NORETURN(return 0;);
60203 }
60204 }
60205 curr = DUK_HOBJECT_GET_PROTOTYPE(thr->heap, curr);
60206 } while (curr != NULL);
60207
60208 /* out_desc is left untouched (possibly garbage), caller must use return
60209 * value to determine whether out_desc can be looked up
60210 */
60211
60212 DUK_STATS_INC(thr->heap, stats_getpropdesc_miss);
60213 return 0;
60214}
60215
60217 * Shallow fast path checks for accessing array elements with numeric
60218 * indices. The goal is to try to avoid coercing an array index to an
60219 * (interned) string for the most common lookups, in particular, for
60220 * standard Array objects.
60221 *
60222 * Interning is avoided but only for a very narrow set of cases:
60223 * - Object has array part, index is within array allocation, and
60224 * value is not unused (= key exists)
60225 * - Object has no interfering exotic behavior (e.g. arguments or
60226 * string object exotic behaviors interfere, array exotic
60227 * behavior does not).
60228 *
60229 * Current shortcoming: if key does not exist (even if it is within
60230 * the array allocation range) a slow path lookup with interning is
60231 * always required. This can probably be fixed so that there is a
60232 * quick fast path for non-existent elements as well, at least for
60233 * standard Array objects.
60234 */
60235
60236#if defined(DUK_USE_ARRAY_PROP_FASTPATH)
60238 duk_tval *tv;
60239 duk_uint32_t idx;
60240
60241 DUK_UNREF(thr);
60242
60245 /* Must have array part and no conflicting exotic behaviors.
60246 * Doesn't need to have array special behavior, e.g. Arguments
60247 * object has array part.
60248 */
60249 return NULL;
60250 }
60251
60252 /* Arrays never have other exotic behaviors. */
60253
60254 DUK_DDD(DUK_DDDPRINT("fast path attempt (no exotic string/arguments/buffer "
60255 "behavior, object has array part)"));
60256
60257#if defined(DUK_USE_FASTINT)
60258 if (DUK_TVAL_IS_FASTINT(tv_key)) {
60259 idx = duk__tval_fastint_to_arr_idx(tv_key);
60260 } else
60261#endif
60262 if (DUK_TVAL_IS_DOUBLE(tv_key)) {
60263 idx = duk__tval_number_to_arr_idx(tv_key);
60264 } else {
60265 DUK_DDD(DUK_DDDPRINT("key is not a number"));
60266 return NULL;
60267 }
60268
60269 /* If index is not valid, idx will be DUK__NO_ARRAY_INDEX which
60270 * is 0xffffffffUL. We don't need to check for that explicitly
60271 * because 0xffffffffUL will never be inside object 'a_size'.
60272 */
60273
60274 if (idx >= DUK_HOBJECT_GET_ASIZE(obj)) {
60275 DUK_DDD(DUK_DDDPRINT("key is not an array index or outside array part"));
60276 return NULL;
60277 }
60278 DUK_ASSERT(idx != 0xffffffffUL);
60280
60281 /* XXX: for array instances we could take a shortcut here and assume
60282 * Array.prototype doesn't contain an array index property.
60283 */
60284
60285 DUK_DDD(DUK_DDDPRINT("key is a valid array index and inside array part"));
60286 tv = DUK_HOBJECT_A_GET_VALUE_PTR(thr->heap, obj, idx);
60287 if (!DUK_TVAL_IS_UNUSED(tv)) {
60288 DUK_DDD(DUK_DDDPRINT("-> fast path successful"));
60289 return tv;
60290 }
60291
60292 DUK_DDD(DUK_DDDPRINT("fast path attempt failed, fall back to slow path"));
60293 return NULL;
60294}
60295
60297 duk_hobject *obj,
60298 duk_tval *tv_key,
60299 duk_tval *tv_val) {
60300 duk_tval *tv;
60301 duk_harray *a;
60302 duk_uint32_t idx;
60303 duk_uint32_t old_len, new_len;
60304
60306 return 0;
60307 }
60308 DUK_ASSERT(!DUK_HEAPHDR_HAS_READONLY((duk_heaphdr *) obj)); /* caller ensures */
60309
60310 a = (duk_harray *) obj;
60312
60313#if defined(DUK_USE_FASTINT)
60314 if (DUK_TVAL_IS_FASTINT(tv_key)) {
60315 idx = duk__tval_fastint_to_arr_idx(tv_key);
60316 } else
60317#endif
60318 if (DUK_TVAL_IS_DOUBLE(tv_key)) {
60319 idx = duk__tval_number_to_arr_idx(tv_key);
60320 } else {
60321 DUK_DDD(DUK_DDDPRINT("key is not a number"));
60322 return 0;
60323 }
60324
60325 /* If index is not valid, idx will be DUK__NO_ARRAY_INDEX which
60326 * is 0xffffffffUL. We don't need to check for that explicitly
60327 * because 0xffffffffUL will never be inside object 'a_size'.
60328 */
60329
60330 if (idx >= DUK_HOBJECT_GET_ASIZE(obj)) { /* for resizing of array part, use slow path */
60331 return 0;
60332 }
60333 DUK_ASSERT(idx != 0xffffffffUL);
60335
60336 old_len = a->length;
60337
60338 if (idx >= old_len) {
60339 DUK_DDD(DUK_DDDPRINT("write new array entry requires length update "
60340 "(arr_idx=%ld, old_len=%ld)",
60341 (long) idx,
60342 (long) old_len));
60344 /* The correct behavior here is either a silent error
60345 * or a TypeError, depending on strictness. Fall back
60346 * to the slow path to handle the situation.
60348 return 0;
60349 }
60350 new_len = idx + 1;
60351
60352 ((duk_harray *) obj)->length = new_len;
60353 }
60354
60355 tv = DUK_HOBJECT_A_GET_VALUE_PTR(thr->heap, obj, idx);
60356 DUK_TVAL_SET_TVAL_UPDREF(thr, tv, tv_val); /* side effects */
60357
60358 DUK_DDD(DUK_DDDPRINT("array fast path success for index %ld", (long) idx));
60359 return 1;
60360}
60361#endif /* DUK_USE_ARRAY_PROP_FASTPATH */
60362
60363/*
60364 * Fast path for bufobj getprop/putprop
60365 */
60366
60367#if defined(DUK_USE_BUFFEROBJECT_SUPPORT)
60369 duk_uint32_t idx;
60370 duk_hbufobj *h_bufobj;
60371 duk_uint_t byte_off;
60372 duk_small_uint_t elem_size;
60373 duk_uint8_t *data;
60374
60375 if (!DUK_HOBJECT_IS_BUFOBJ(obj)) {
60376 return 0;
60377 }
60378 h_bufobj = (duk_hbufobj *) obj;
60379 if (!DUK_HBUFOBJ_HAS_VIRTUAL_INDICES(h_bufobj)) {
60380 return 0;
60381 }
60382
60383#if defined(DUK_USE_FASTINT)
60384 if (DUK_TVAL_IS_FASTINT(tv_key)) {
60385 idx = duk__tval_fastint_to_arr_idx(tv_key);
60386 } else
60387#endif
60388 if (DUK_TVAL_IS_DOUBLE(tv_key)) {
60389 idx = duk__tval_number_to_arr_idx(tv_key);
60390 } else {
60391 return 0;
60392 }
60393
60394 /* If index is not valid, idx will be DUK__NO_ARRAY_INDEX which
60395 * is 0xffffffffUL. We don't need to check for that explicitly
60396 * because 0xffffffffUL will never be inside bufobj length.
60397 */
60398
60399 /* Careful with wrapping (left shifting idx would be unsafe). */
60400 if (idx >= (h_bufobj->length >> h_bufobj->shift)) {
60401 return 0;
60402 }
60404
60405 byte_off = idx << h_bufobj->shift; /* no wrap assuming h_bufobj->length is valid */
60406 elem_size = (duk_small_uint_t) (1U << h_bufobj->shift);
60407
60408 if (h_bufobj->buf != NULL && DUK_HBUFOBJ_VALID_BYTEOFFSET_EXCL(h_bufobj, byte_off + elem_size)) {
60409 data = (duk_uint8_t *) DUK_HBUFFER_GET_DATA_PTR(thr->heap, h_bufobj->buf) + h_bufobj->offset + byte_off;
60410 duk_hbufobj_push_validated_read(thr, h_bufobj, data, elem_size);
60411 } else {
60412 DUK_D(DUK_DPRINT("bufobj access out of underlying buffer, ignoring (read zero)"));
60413 duk_push_uint(thr, 0);
60414 }
60415
60416 return 1;
60417}
60418#endif /* DUK_USE_BUFFEROBJECT_SUPPORT */
60419
60420#if defined(DUK_USE_BUFFEROBJECT_SUPPORT)
60422 duk_uint32_t idx;
60423 duk_hbufobj *h_bufobj;
60424 duk_uint_t byte_off;
60425 duk_small_uint_t elem_size;
60426 duk_uint8_t *data;
60427
60428 if (!(DUK_HOBJECT_IS_BUFOBJ(obj) && DUK_TVAL_IS_NUMBER(tv_val))) {
60429 return 0;
60430 }
60431 DUK_ASSERT(!DUK_HEAPHDR_HAS_READONLY((duk_heaphdr *) obj)); /* caller ensures; rom objects are never bufobjs now */
60432
60433 h_bufobj = (duk_hbufobj *) obj;
60434 if (!DUK_HBUFOBJ_HAS_VIRTUAL_INDICES(h_bufobj)) {
60435 return 0;
60436 }
60437
60438#if defined(DUK_USE_FASTINT)
60439 if (DUK_TVAL_IS_FASTINT(tv_key)) {
60440 idx = duk__tval_fastint_to_arr_idx(tv_key);
60441 } else
60442#endif
60443 if (DUK_TVAL_IS_DOUBLE(tv_key)) {
60444 idx = duk__tval_number_to_arr_idx(tv_key);
60445 } else {
60446 return 0;
60447 }
60448
60449 /* If index is not valid, idx will be DUK__NO_ARRAY_INDEX which
60450 * is 0xffffffffUL. We don't need to check for that explicitly
60451 * because 0xffffffffUL will never be inside bufobj length.
60452 */
60453
60454 /* Careful with wrapping (left shifting idx would be unsafe). */
60455 if (idx >= (h_bufobj->length >> h_bufobj->shift)) {
60456 return 0;
60457 }
60459
60460 byte_off = idx << h_bufobj->shift; /* no wrap assuming h_bufobj->length is valid */
60461 elem_size = (duk_small_uint_t) (1U << h_bufobj->shift);
60462
60463 /* Value is required to be a number in the fast path so there
60464 * are no side effects in write coercion.
60465 */
60466 duk_push_tval(thr, tv_val);
60467 DUK_ASSERT(duk_is_number(thr, -1));
60468
60469 if (h_bufobj->buf != NULL && DUK_HBUFOBJ_VALID_BYTEOFFSET_EXCL(h_bufobj, byte_off + elem_size)) {
60470 data = (duk_uint8_t *) DUK_HBUFFER_GET_DATA_PTR(thr->heap, h_bufobj->buf) + h_bufobj->offset + byte_off;
60471 duk_hbufobj_validated_write(thr, h_bufobj, data, elem_size);
60472 } else {
60473 DUK_D(DUK_DPRINT("bufobj access out of underlying buffer, ignoring (write skipped)"));
60474 }
60475
60476 duk_pop_unsafe(thr);
60477 return 1;
60478}
60479#endif /* DUK_USE_BUFFEROBJECT_SUPPORT */
60480
60481/*
60482 * GETPROP: ECMAScript property read.
60483 */
60484
60486 duk_tval tv_obj_copy;
60487 duk_tval tv_key_copy;
60488 duk_hobject *curr = NULL;
60489 duk_hstring *key = NULL;
60490 duk_uint32_t arr_idx = DUK__NO_ARRAY_INDEX;
60491 duk_propdesc desc;
60492 duk_uint_t sanity;
60493
60494 DUK_DDD(DUK_DDDPRINT("getprop: thr=%p, obj=%p, key=%p (obj -> %!T, key -> %!T)",
60495 (void *) thr,
60496 (void *) tv_obj,
60497 (void *) tv_key,
60498 (duk_tval *) tv_obj,
60499 (duk_tval *) tv_key));
60500
60501 DUK_ASSERT(thr != NULL);
60502 DUK_ASSERT(thr->heap != NULL);
60503 DUK_ASSERT(tv_obj != NULL);
60504 DUK_ASSERT(tv_key != NULL);
60505
60507
60508 DUK_STATS_INC(thr->heap, stats_getprop_all);
60509
60510 /*
60511 * Make a copy of tv_obj, tv_key, and tv_val to avoid any issues of
60512 * them being invalidated by a valstack resize.
60513 *
60514 * XXX: this is now an overkill for many fast paths. Rework this
60515 * to be faster (although switching to a valstack discipline might
60516 * be a better solution overall).
60517 */
60518
60519 DUK_TVAL_SET_TVAL(&tv_obj_copy, tv_obj);
60520 DUK_TVAL_SET_TVAL(&tv_key_copy, tv_key);
60521 tv_obj = &tv_obj_copy;
60522 tv_key = &tv_key_copy;
60523
60524 /*
60525 * Coercion and fast path processing
60526 */
60527
60528 switch (DUK_TVAL_GET_TAG(tv_obj)) {
60529 case DUK_TAG_UNDEFINED:
60530 case DUK_TAG_NULL: {
60531 /* Note: unconditional throw */
60532 DUK_DDD(DUK_DDDPRINT("base object is undefined or null -> reject"));
60533#if defined(DUK_USE_PARANOID_ERRORS)
60535#else
60536 DUK_ERROR_FMT2(thr,
60538 "cannot read property %s of %s",
60539 duk_push_string_tval_readable(thr, tv_key),
60540 duk_push_string_tval_readable(thr, tv_obj));
60541#endif
60542 DUK_WO_NORETURN(return 0;);
60543 break;
60544 }
60545
60546 case DUK_TAG_BOOLEAN: {
60547 DUK_DDD(DUK_DDDPRINT("base object is a boolean, start lookup from boolean prototype"));
60548 curr = thr->builtins[DUK_BIDX_BOOLEAN_PROTOTYPE];
60549 break;
60550 }
60551
60552 case DUK_TAG_STRING: {
60553 duk_hstring *h = DUK_TVAL_GET_STRING(tv_obj);
60554 duk_int_t pop_count;
60555
60557 /* Symbols (ES2015 or hidden) don't have virtual properties. */
60558 DUK_DDD(DUK_DDDPRINT("base object is a symbol, start lookup from symbol prototype"));
60559 curr = thr->builtins[DUK_BIDX_SYMBOL_PROTOTYPE];
60560 break;
60561 }
60562
60563#if defined(DUK_USE_FASTINT)
60564 if (DUK_TVAL_IS_FASTINT(tv_key)) {
60565 arr_idx = duk__tval_fastint_to_arr_idx(tv_key);
60566 DUK_DDD(DUK_DDDPRINT("base object string, key is a fast-path fastint; arr_idx %ld", (long) arr_idx));
60567 pop_count = 0;
60568 } else
60569#endif
60570 if (DUK_TVAL_IS_NUMBER(tv_key)) {
60571 arr_idx = duk__tval_number_to_arr_idx(tv_key);
60572 DUK_DDD(DUK_DDDPRINT("base object string, key is a fast-path number; arr_idx %ld", (long) arr_idx));
60573 pop_count = 0;
60574 } else {
60575 arr_idx = duk__push_tval_to_property_key(thr, tv_key, &key);
60576 DUK_ASSERT(key != NULL);
60577 DUK_DDD(DUK_DDDPRINT("base object string, key is a non-fast-path number; after "
60578 "coercion key is %!T, arr_idx %ld",
60579 (duk_tval *) duk_get_tval(thr, -1),
60580 (long) arr_idx));
60581 pop_count = 1;
60582 }
60583
60584 if (arr_idx != DUK__NO_ARRAY_INDEX && arr_idx < DUK_HSTRING_GET_CHARLEN(h)) {
60585 duk_pop_n_unsafe(thr, pop_count);
60586 duk_push_hstring(thr, h);
60587 duk_substring(thr, -1, arr_idx, arr_idx + 1); /* [str] -> [substr] */
60588
60589 DUK_STATS_INC(thr->heap, stats_getprop_stringidx);
60590 DUK_DDD(DUK_DDDPRINT("-> %!T (base is string, key is an index inside string length "
60591 "after coercion -> return char)",
60592 (duk_tval *) duk_get_tval(thr, -1)));
60593 return 1;
60594 }
60595
60596 if (pop_count == 0) {
60597 /* This is a pretty awkward control flow, but we need to recheck the
60598 * key coercion here.
60599 */
60600 arr_idx = duk__push_tval_to_property_key(thr, tv_key, &key);
60601 DUK_ASSERT(key != NULL);
60602 DUK_DDD(DUK_DDDPRINT("base object string, key is a non-fast-path number; after "
60603 "coercion key is %!T, arr_idx %ld",
60604 (duk_tval *) duk_get_tval(thr, -1),
60605 (long) arr_idx));
60606 }
60607
60608 if (key == DUK_HTHREAD_STRING_LENGTH(thr)) {
60609 duk_pop_unsafe(thr); /* [key] -> [] */
60610 duk_push_uint(thr, (duk_uint_t) DUK_HSTRING_GET_CHARLEN(h)); /* [] -> [res] */
60611
60612 DUK_STATS_INC(thr->heap, stats_getprop_stringlen);
60613 DUK_DDD(DUK_DDDPRINT("-> %!T (base is string, key is 'length' after coercion -> "
60614 "return string length)",
60615 (duk_tval *) duk_get_tval(thr, -1)));
60616 return 1;
60617 }
60618
60619 DUK_DDD(DUK_DDDPRINT("base object is a string, start lookup from string prototype"));
60620 curr = thr->builtins[DUK_BIDX_STRING_PROTOTYPE];
60621 goto lookup; /* avoid double coercion */
60622 }
60623
60624 case DUK_TAG_OBJECT: {
60625#if defined(DUK_USE_ARRAY_PROP_FASTPATH)
60626 duk_tval *tmp;
60627#endif
60628
60629 curr = DUK_TVAL_GET_OBJECT(tv_obj);
60630 DUK_ASSERT(curr != NULL);
60631
60632 /* XXX: array .length fast path (important in e.g. loops)? */
60633
60634#if defined(DUK_USE_ARRAY_PROP_FASTPATH)
60635 tmp = duk__getprop_shallow_fastpath_array_tval(thr, curr, tv_key);
60636 if (tmp) {
60637 duk_push_tval(thr, tmp);
60638
60639 DUK_DDD(DUK_DDDPRINT("-> %!T (base is object, key is a number, array part "
60640 "fast path)",
60641 (duk_tval *) duk_get_tval(thr, -1)));
60642 DUK_STATS_INC(thr->heap, stats_getprop_arrayidx);
60643 return 1;
60644 }
60645#endif
60646
60647#if defined(DUK_USE_BUFFEROBJECT_SUPPORT)
60648 if (duk__getprop_fastpath_bufobj_tval(thr, curr, tv_key) != 0) {
60649 /* Read value pushed on stack. */
60650 DUK_DDD(DUK_DDDPRINT("-> %!T (base is bufobj, key is a number, bufobj "
60651 "fast path)",
60652 (duk_tval *) duk_get_tval(thr, -1)));
60653 DUK_STATS_INC(thr->heap, stats_getprop_bufobjidx);
60654 return 1;
60655 }
60656#endif
60657
60658#if defined(DUK_USE_ES6_PROXY)
60660 duk_hobject *h_target;
60661
60662 if (duk__proxy_check_prop(thr, curr, DUK_STRIDX_GET, tv_key, &h_target)) {
60663 /* -> [ ... trap handler ] */
60664 DUK_DDD(DUK_DDDPRINT("-> proxy object 'get' for key %!T", (duk_tval *) tv_key));
60665 DUK_STATS_INC(thr->heap, stats_getprop_proxy);
60666 duk_push_hobject(thr, h_target); /* target */
60667 duk_push_tval(thr, tv_key); /* P */
60668 duk_push_tval(thr, tv_obj); /* Receiver: Proxy object */
60669 duk_call_method(thr, 3 /*nargs*/);
60670
60671 /* Target object must be checked for a conflicting
60672 * non-configurable property.
60673 */
60674 arr_idx = duk__push_tval_to_property_key(thr, tv_key, &key);
60675 DUK_ASSERT(key != NULL);
60676
60677 if (duk__get_own_propdesc_raw(thr, h_target, key, arr_idx, &desc, DUK_GETDESC_FLAG_PUSH_VALUE)) {
60678 duk_tval *tv_hook = duk_require_tval(thr, -3); /* value from hook */
60679 duk_tval *tv_targ = duk_require_tval(thr, -1); /* value from target */
60680 duk_bool_t datadesc_reject;
60681 duk_bool_t accdesc_reject;
60682
60683 DUK_DDD(DUK_DDDPRINT("proxy 'get': target has matching property %!O, check for "
60684 "conflicting property; tv_hook=%!T, tv_targ=%!T, desc.flags=0x%08lx, "
60685 "desc.get=%p, desc.set=%p",
60686 (duk_heaphdr *) key,
60687 (duk_tval *) tv_hook,
60688 (duk_tval *) tv_targ,
60689 (unsigned long) desc.flags,
60690 (void *) desc.get,
60691 (void *) desc.set));
60692
60693 datadesc_reject = !(desc.flags & DUK_PROPDESC_FLAG_ACCESSOR) &&
60696 !duk_js_samevalue(tv_hook, tv_targ);
60697 accdesc_reject = (desc.flags & DUK_PROPDESC_FLAG_ACCESSOR) &&
60698 !(desc.flags & DUK_PROPDESC_FLAG_CONFIGURABLE) && (desc.get == NULL) &&
60699 !DUK_TVAL_IS_UNDEFINED(tv_hook);
60700 if (datadesc_reject || accdesc_reject) {
60702 DUK_WO_NORETURN(return 0;);
60703 }
60704
60705 duk_pop_2_unsafe(thr);
60706 } else {
60707 duk_pop_unsafe(thr);
60708 }
60709 return 1; /* return value */
60710 }
60711
60712 curr = h_target; /* resume lookup from target */
60713 DUK_TVAL_SET_OBJECT(tv_obj, curr);
60714 }
60715#endif /* DUK_USE_ES6_PROXY */
60716
60718 arr_idx = duk__push_tval_to_property_key(thr, tv_key, &key);
60719 DUK_ASSERT(key != NULL);
60720
60721 DUK_STATS_INC(thr->heap, stats_getprop_arguments);
60722 if (duk__check_arguments_map_for_get(thr, curr, key, &desc)) {
60723 DUK_DDD(DUK_DDDPRINT("-> %!T (base is object with arguments exotic behavior, "
60724 "key matches magically bound property -> skip standard "
60725 "Get with replacement value)",
60726 (duk_tval *) duk_get_tval(thr, -1)));
60727
60728 /* no need for 'caller' post-check, because 'key' must be an array index */
60729
60730 duk_remove_m2(thr); /* [key result] -> [result] */
60731 return 1;
60732 }
60733
60734 goto lookup; /* avoid double coercion */
60735 }
60736 break;
60737 }
60738
60739 /* Buffer has virtual properties similar to string, but indexed values
60740 * are numbers, not 1-byte buffers/strings which would perform badly.
60741 */
60742 case DUK_TAG_BUFFER: {
60743 duk_hbuffer *h = DUK_TVAL_GET_BUFFER(tv_obj);
60744 duk_int_t pop_count;
60745
60746 /*
60747 * Because buffer values are often looped over, a number fast path
60748 * is important.
60749 */
60750
60751#if defined(DUK_USE_FASTINT)
60752 if (DUK_TVAL_IS_FASTINT(tv_key)) {
60753 arr_idx = duk__tval_fastint_to_arr_idx(tv_key);
60754 DUK_DDD(DUK_DDDPRINT("base object buffer, key is a fast-path fastint; arr_idx %ld", (long) arr_idx));
60755 pop_count = 0;
60756 } else
60757#endif
60758 if (DUK_TVAL_IS_NUMBER(tv_key)) {
60759 arr_idx = duk__tval_number_to_arr_idx(tv_key);
60760 DUK_DDD(DUK_DDDPRINT("base object buffer, key is a fast-path number; arr_idx %ld", (long) arr_idx));
60761 pop_count = 0;
60762 } else {
60763 arr_idx = duk__push_tval_to_property_key(thr, tv_key, &key);
60764 DUK_ASSERT(key != NULL);
60765 DUK_DDD(DUK_DDDPRINT("base object buffer, key is a non-fast-path number; after "
60766 "coercion key is %!T, arr_idx %ld",
60767 (duk_tval *) duk_get_tval(thr, -1),
60768 (long) arr_idx));
60769 pop_count = 1;
60770 }
60771
60772 if (arr_idx != DUK__NO_ARRAY_INDEX && arr_idx < DUK_HBUFFER_GET_SIZE(h)) {
60773 duk_pop_n_unsafe(thr, pop_count);
60774 duk_push_uint(thr, ((duk_uint8_t *) DUK_HBUFFER_GET_DATA_PTR(thr->heap, h))[arr_idx]);
60775 DUK_STATS_INC(thr->heap, stats_getprop_bufferidx);
60776 DUK_DDD(DUK_DDDPRINT("-> %!T (base is buffer, key is an index inside buffer length "
60777 "after coercion -> return byte as number)",
60778 (duk_tval *) duk_get_tval(thr, -1)));
60779 return 1;
60780 }
60781
60782 if (pop_count == 0) {
60783 /* This is a pretty awkward control flow, but we need to recheck the
60784 * key coercion here.
60785 */
60786 arr_idx = duk__push_tval_to_property_key(thr, tv_key, &key);
60787 DUK_ASSERT(key != NULL);
60788 DUK_DDD(DUK_DDDPRINT("base object buffer, key is a non-fast-path number; after "
60789 "coercion key is %!T, arr_idx %ld",
60790 (duk_tval *) duk_get_tval(thr, -1),
60791 (long) arr_idx));
60792 }
60793
60794 if (key == DUK_HTHREAD_STRING_LENGTH(thr)) {
60795 duk_pop_unsafe(thr); /* [key] -> [] */
60796 duk_push_uint(thr, (duk_uint_t) DUK_HBUFFER_GET_SIZE(h)); /* [] -> [res] */
60797 DUK_STATS_INC(thr->heap, stats_getprop_bufferlen);
60798
60799 DUK_DDD(DUK_DDDPRINT("-> %!T (base is buffer, key is 'length' "
60800 "after coercion -> return buffer length)",
60801 (duk_tval *) duk_get_tval(thr, -1)));
60802 return 1;
60803 }
60804
60805 DUK_DDD(DUK_DDDPRINT("base object is a buffer, start lookup from Uint8Array prototype"));
60806 curr = thr->builtins[DUK_BIDX_UINT8ARRAY_PROTOTYPE];
60807 goto lookup; /* avoid double coercion */
60808 }
60809
60810 case DUK_TAG_POINTER: {
60811 DUK_DDD(DUK_DDDPRINT("base object is a pointer, start lookup from pointer prototype"));
60812 curr = thr->builtins[DUK_BIDX_POINTER_PROTOTYPE];
60813 break;
60814 }
60815
60816 case DUK_TAG_LIGHTFUNC: {
60817 /* Lightfuncs inherit getter .name and .length from %NativeFunctionPrototype%. */
60818 DUK_DDD(DUK_DDDPRINT("base object is a lightfunc, start lookup from function prototype"));
60819 curr = thr->builtins[DUK_BIDX_NATIVE_FUNCTION_PROTOTYPE];
60820 break;
60821 }
60822
60823#if defined(DUK_USE_FASTINT)
60824 case DUK_TAG_FASTINT:
60825#endif
60826 default: {
60827 /* number */
60828 DUK_DDD(DUK_DDDPRINT("base object is a number, start lookup from number prototype"));
60831 curr = thr->builtins[DUK_BIDX_NUMBER_PROTOTYPE];
60832 break;
60833 }
60834 }
60835
60836 /* key coercion (unless already coerced above) */
60837 DUK_ASSERT(key == NULL);
60838 arr_idx = duk__push_tval_to_property_key(thr, tv_key, &key);
60839 DUK_ASSERT(key != NULL);
60840 /*
60841 * Property lookup
60842 */
60843
60844lookup:
60845 /* [key] (coerced) */
60846 DUK_ASSERT(curr != NULL);
60847 DUK_ASSERT(key != NULL);
60848
60850 do {
60851 if (!duk__get_own_propdesc_raw(thr, curr, key, arr_idx, &desc, DUK_GETDESC_FLAG_PUSH_VALUE)) {
60852 goto next_in_chain;
60853 }
60854
60855 if (desc.get != NULL) {
60856 /* accessor with defined getter */
60858
60859 duk_pop_unsafe(thr); /* [key undefined] -> [key] */
60860 duk_push_hobject(thr, desc.get);
60861 duk_push_tval(thr, tv_obj); /* note: original, uncoerced base */
60862#if defined(DUK_USE_NONSTD_GETTER_KEY_ARGUMENT)
60863 duk_dup_m3(thr);
60864 duk_call_method(thr, 1); /* [key getter this key] -> [key retval] */
60865#else
60866 duk_call_method(thr, 0); /* [key getter this] -> [key retval] */
60867#endif
60868 } else {
60869 /* [key value] or [key undefined] */
60870
60871 /* data property or accessor without getter */
60872 DUK_ASSERT(((desc.flags & DUK_PROPDESC_FLAG_ACCESSOR) == 0) || (desc.get == NULL));
60873
60874 /* if accessor without getter, return value is undefined */
60875 DUK_ASSERT(((desc.flags & DUK_PROPDESC_FLAG_ACCESSOR) == 0) || duk_is_undefined(thr, -1));
60876
60877 /* Note: for an accessor without getter, falling through to
60878 * check for "caller" exotic behavior is unnecessary as
60879 * "undefined" will never activate the behavior. But it does
60880 * no harm, so we'll do it anyway.
60881 */
60882 }
60883
60884 goto found; /* [key result] */
60885
60886 next_in_chain:
60887 /* XXX: option to pretend property doesn't exist if sanity limit is
60888 * hit might be useful.
60889 */
60890 if (DUK_UNLIKELY(sanity-- == 0)) {
60892 DUK_WO_NORETURN(return 0;);
60893 }
60894 curr = DUK_HOBJECT_GET_PROTOTYPE(thr->heap, curr);
60895 } while (curr != NULL);
60896
60897 /*
60898 * Not found
60899 */
60900
60901 duk_to_undefined(thr, -1); /* [key] -> [undefined] (default value) */
60902
60903 DUK_DDD(DUK_DDDPRINT("-> %!T (not found)", (duk_tval *) duk_get_tval(thr, -1)));
60904 return 0;
60905
60906 /*
60907 * Found; post-processing (Function and arguments objects)
60908 */
60909
60910found:
60911 /* [key result] */
60912
60913#if !defined(DUK_USE_NONSTD_FUNC_CALLER_PROPERTY)
60914 /* Special behavior for 'caller' property of (non-bound) function objects
60915 * and non-strict Arguments objects: if 'caller' -value- (!) is a strict
60916 * mode function, throw a TypeError (E5 Sections 15.3.5.4, 10.6).
60917 * Quite interestingly, a non-strict function with no formal arguments
60918 * will get an arguments object -without- special 'caller' behavior!
60919 *
60920 * The E5.1 spec is a bit ambiguous if this special behavior applies when
60921 * a bound function is the base value (not the 'caller' value): Section
60922 * 15.3.4.5 (describing bind()) states that [[Get]] for bound functions
60923 * matches that of Section 15.3.5.4 ([[Get]] for Function instances).
60924 * However, Section 13.3.5.4 has "NOTE: Function objects created using
60925 * Function.prototype.bind use the default [[Get]] internal method."
60926 * The current implementation assumes this means that bound functions
60927 * should not have the special [[Get]] behavior.
60928 *
60929 * The E5.1 spec is also a bit unclear if the TypeError throwing is
60930 * applied if the 'caller' value is a strict bound function. The
60931 * current implementation will throw even for both strict non-bound
60932 * and strict bound functions.
60933 *
60934 * See test-dev-strict-func-as-caller-prop-value.js for quite extensive
60935 * tests.
60936 *
60937 * This exotic behavior is disabled when the non-standard 'caller' property
60938 * is enabled, as it conflicts with the free use of 'caller'.
60939 */
60940 if (key == DUK_HTHREAD_STRING_CALLER(thr) && DUK_TVAL_IS_OBJECT(tv_obj)) {
60941 duk_hobject *orig = DUK_TVAL_GET_OBJECT(tv_obj);
60942 DUK_ASSERT(orig != NULL);
60943
60945 duk_hobject *h;
60946
60947 /* XXX: The TypeError is currently not applied to bound
60948 * functions because the 'strict' flag is not copied by
60949 * bind(). This may or may not be correct, the specification
60950 * only refers to the value being a "strict mode Function
60951 * object" which is ambiguous.
60952 */
60954
60955 h = duk_get_hobject(thr, -1); /* NULL if not an object */
60957 /* XXX: sufficient to check 'strict', assert for 'is function' */
60959 DUK_WO_NORETURN(return 0;);
60960 }
60961 }
60962 }
60963#endif /* !DUK_USE_NONSTD_FUNC_CALLER_PROPERTY */
60964
60965 duk_remove_m2(thr); /* [key result] -> [result] */
60966
60967 DUK_DDD(DUK_DDDPRINT("-> %!T (found)", (duk_tval *) duk_get_tval(thr, -1)));
60968 return 1;
60969}
60970
60971/*
60972 * HASPROP: ECMAScript property existence check ("in" operator).
60973 *
60974 * Interestingly, the 'in' operator does not do any coercion of
60975 * the target object.
60976 */
60977
60979 duk_tval tv_key_copy;
60980 duk_hobject *obj;
60981 duk_hstring *key;
60982 duk_uint32_t arr_idx;
60983 duk_bool_t rc;
60984 duk_propdesc desc;
60985
60986 DUK_DDD(DUK_DDDPRINT("hasprop: thr=%p, obj=%p, key=%p (obj -> %!T, key -> %!T)",
60987 (void *) thr,
60988 (void *) tv_obj,
60989 (void *) tv_key,
60990 (duk_tval *) tv_obj,
60991 (duk_tval *) tv_key));
60992
60993 DUK_ASSERT(thr != NULL);
60994 DUK_ASSERT(thr->heap != NULL);
60995 DUK_ASSERT(tv_obj != NULL);
60996 DUK_ASSERT(tv_key != NULL);
60998
60999 DUK_TVAL_SET_TVAL(&tv_key_copy, tv_key);
61000 tv_key = &tv_key_copy;
61001
61002 /*
61003 * The 'in' operator requires an object as its right hand side,
61004 * throwing a TypeError unconditionally if this is not the case.
61005 *
61006 * However, lightfuncs need to behave like fully fledged objects
61007 * here to be maximally transparent, so we need to handle them
61008 * here. Same goes for plain buffers which behave like ArrayBuffers.
61009 */
61010
61011 /* XXX: Refactor key coercion so that it's only called once. It can't
61012 * be trivially lifted here because the object must be type checked
61013 * first.
61014 */
61015
61016 if (DUK_TVAL_IS_OBJECT(tv_obj)) {
61017 obj = DUK_TVAL_GET_OBJECT(tv_obj);
61018 DUK_ASSERT(obj != NULL);
61019
61020 arr_idx = duk__push_tval_to_property_key(thr, tv_key, &key);
61021 } else if (DUK_TVAL_IS_BUFFER(tv_obj)) {
61022 arr_idx = duk__push_tval_to_property_key(thr, tv_key, &key);
61023 if (duk__key_is_plain_buf_ownprop(thr, DUK_TVAL_GET_BUFFER(tv_obj), key, arr_idx)) {
61024 rc = 1;
61025 goto pop_and_return;
61026 }
61027 obj = thr->builtins[DUK_BIDX_UINT8ARRAY_PROTOTYPE];
61028 } else if (DUK_TVAL_IS_LIGHTFUNC(tv_obj)) {
61029 arr_idx = duk__push_tval_to_property_key(thr, tv_key, &key);
61030
61031 /* If not found, resume existence check from %NativeFunctionPrototype%.
61032 * We can just substitute the value in this case; nothing will
61033 * need the original base value (as would be the case with e.g.
61034 * setters/getters.
61035 */
61036 obj = thr->builtins[DUK_BIDX_NATIVE_FUNCTION_PROTOTYPE];
61037 } else {
61038 /* Note: unconditional throw */
61039 DUK_DDD(DUK_DDDPRINT("base object is not an object -> reject"));
61041 DUK_WO_NORETURN(return 0;);
61042 }
61043
61044 /* XXX: fast path for arrays? */
61045
61046 DUK_ASSERT(key != NULL);
61047 DUK_ASSERT(obj != NULL);
61048 DUK_UNREF(arr_idx);
61049
61050#if defined(DUK_USE_ES6_PROXY)
61052 duk_hobject *h_target;
61053 duk_bool_t tmp_bool;
61054
61055 /* XXX: the key in 'key in obj' is string coerced before we're called
61056 * (which is the required behavior in E5/E5.1/E6) so the key is a string
61057 * here already.
61058 */
61059
61060 if (duk__proxy_check_prop(thr, obj, DUK_STRIDX_HAS, tv_key, &h_target)) {
61061 /* [ ... key trap handler ] */
61062 DUK_DDD(DUK_DDDPRINT("-> proxy object 'has' for key %!T", (duk_tval *) tv_key));
61063 duk_push_hobject(thr, h_target); /* target */
61064 duk_push_tval(thr, tv_key); /* P */
61065 duk_call_method(thr, 2 /*nargs*/);
61066 tmp_bool = duk_to_boolean_top_pop(thr);
61067 if (!tmp_bool) {
61068 /* Target object must be checked for a conflicting
61069 * non-configurable property.
61070 */
61071
61072 if (duk__get_own_propdesc_raw(thr, h_target, key, arr_idx, &desc, 0 /*flags*/)) { /* don't push
61073 value */
61074 DUK_DDD(DUK_DDDPRINT("proxy 'has': target has matching property %!O, check for "
61075 "conflicting property; desc.flags=0x%08lx, "
61076 "desc.get=%p, desc.set=%p",
61077 (duk_heaphdr *) key,
61078 (unsigned long) desc.flags,
61079 (void *) desc.get,
61080 (void *) desc.set));
61081 /* XXX: Extensibility check for target uses IsExtensible(). If we
61082 * implemented the isExtensible trap and didn't reject proxies as
61083 * proxy targets, it should be respected here.
61084 */
61085 if (!((desc.flags & DUK_PROPDESC_FLAG_CONFIGURABLE) && /* property is configurable and */
61086 DUK_HOBJECT_HAS_EXTENSIBLE(h_target))) { /* ... target is extensible */
61088 DUK_WO_NORETURN(return 0;);
61089 }
61090 }
61091 }
61092
61093 duk_pop_unsafe(thr); /* [ key ] -> [] */
61094 return tmp_bool;
61095 }
61096
61097 obj = h_target; /* resume check from proxy target */
61098 }
61099#endif /* DUK_USE_ES6_PROXY */
61100
61101 /* XXX: inline into a prototype walking loop? */
61103 rc = duk__get_propdesc(thr, obj, key, &desc, 0 /*flags*/); /* don't push value */
61104 /* fall through */
61105
61106pop_and_return:
61107 duk_pop_unsafe(thr); /* [ key ] -> [] */
61108 return rc;
61109}
61110
61111/*
61112 * HASPROP variant used internally.
61113 *
61114 * This primitive must never throw an error, callers rely on this.
61115 * In particular, don't throw an error for prototype loops; instead,
61116 * pretend like the property doesn't exist if a prototype sanity limit
61117 * is reached.
61118 *
61119 * Does not implement proxy behavior: if applied to a proxy object,
61120 * returns key existence on the proxy object itself.
61121 */
61122
61124 duk_propdesc dummy;
61125
61126 DUK_ASSERT(thr != NULL);
61127 DUK_ASSERT(thr->heap != NULL);
61128 DUK_ASSERT(obj != NULL);
61129 DUK_ASSERT(key != NULL);
61130
61132
61133 return duk__get_propdesc(thr, obj, key, &dummy, DUK_GETDESC_FLAG_IGNORE_PROTOLOOP); /* don't push value */
61134}
61135
61136/*
61137 * Helper: handle Array object 'length' write which automatically
61138 * deletes properties, see E5 Section 15.4.5.1, step 3. This is
61139 * quite tricky to get right.
61140 *
61141 * Used by duk_hobject_putprop().
61142 */
61143
61144/* Coerce a new .length candidate to a number and check that it's a valid
61145 * .length.
61146 */
61148 duk_uint32_t res;
61149 duk_double_t d;
61150
61151#if !defined(DUK_USE_PREFER_SIZE)
61152#if defined(DUK_USE_FASTINT)
61153 /* When fastints are enabled, the most interesting case is assigning
61154 * a fastint to .length (e.g. arr.length = 0).
61155 */
61156 if (DUK_TVAL_IS_FASTINT(tv)) {
61157 /* Very common case. */
61158 duk_int64_t fi;
61159 fi = DUK_TVAL_GET_FASTINT(tv);
61160 if (fi < 0 || fi > DUK_I64_CONSTANT(0xffffffff)) {
61161 goto fail_range;
61162 }
61163 return (duk_uint32_t) fi;
61164 }
61165#else /* DUK_USE_FASTINT */
61166 /* When fastints are not enabled, the most interesting case is any
61167 * number.
61168 */
61169 if (DUK_TVAL_IS_DOUBLE(tv)) {
61170 d = DUK_TVAL_GET_NUMBER(tv);
61171 }
61172#endif /* DUK_USE_FASTINT */
61173 else
61174#endif /* !DUK_USE_PREFER_SIZE */
61175 {
61176 /* In all other cases, and when doing a size optimized build,
61177 * fall back to the comprehensive handler.
61178 */
61179 d = duk_js_tonumber(thr, tv);
61180 }
61181
61182 /* Refuse to update an Array's 'length' to a value outside the
61183 * 32-bit range. Negative zero is accepted as zero.
61185 res = duk_double_to_uint32_t(d);
61186 if (!duk_double_equals((duk_double_t) res, d)) {
61187 goto fail_range;
61188 }
61189
61190 return res;
61191
61192fail_range:
61194 DUK_WO_NORETURN(return 0;);
61195}
61196
61197/* Delete elements required by a smaller length, taking into account
61198 * potentially non-configurable elements. Returns non-zero if all
61199 * elements could be deleted, and zero if all or some elements could
61200 * not be deleted. Also writes final "target length" to 'out_result_len'.
61201 * This is the length value that should go into the 'length' property
61202 * (must be set by the caller). Never throws an error.
61203 */
61206 duk_hobject *obj,
61207 duk_uint32_t old_len,
61208 duk_uint32_t new_len,
61209 duk_bool_t force_flag,
61210 duk_uint32_t *out_result_len) {
61211 duk_uint32_t target_len;
61213 duk_uint32_t arr_idx;
61214 duk_hstring *key;
61215 duk_tval *tv;
61216 duk_bool_t rc;
61217
61218 DUK_DDD(DUK_DDDPRINT("new array length smaller than old (%ld -> %ld), "
61219 "probably need to remove elements",
61220 (long) old_len,
61221 (long) new_len));
61222
61223 /*
61224 * New length is smaller than old length, need to delete properties above
61225 * the new length.
61226 *
61227 * If array part exists, this is straightforward: array entries cannot
61228 * be non-configurable so this is guaranteed to work.
61229 *
61230 * If array part does not exist, array-indexed values are scattered
61231 * in the entry part, and some may not be configurable (preventing length
61232 * from becoming lower than their index + 1). To handle the algorithm
61233 * in E5 Section 15.4.5.1, step l correctly, we scan the entire property
61234 * set twice.
61235 */
61236
61237 DUK_ASSERT(thr != NULL);
61238 DUK_ASSERT(obj != NULL);
61239 DUK_ASSERT(new_len < old_len);
61240 DUK_ASSERT(out_result_len != NULL);
61242
61245
61246 if (DUK_HOBJECT_HAS_ARRAY_PART(obj)) {
61247 /*
61248 * All defined array-indexed properties are in the array part
61249 * (we assume the array part is comprehensive), and all array
61250 * entries are writable, configurable, and enumerable. Thus,
61251 * nothing can prevent array entries from being deleted.
61252 */
61253
61254 DUK_DDD(DUK_DDDPRINT("have array part, easy case"));
61255
61256 if (old_len < DUK_HOBJECT_GET_ASIZE(obj)) {
61257 /* XXX: assertion that entries >= old_len are already unused */
61258 i = old_len;
61259 } else {
61260 i = DUK_HOBJECT_GET_ASIZE(obj);
61261 }
61263
61264 while (i > new_len) {
61265 i--;
61266 tv = DUK_HOBJECT_A_GET_VALUE_PTR(thr->heap, obj, i);
61267 DUK_TVAL_SET_UNUSED_UPDREF(thr, tv); /* side effects */
61268 }
61269
61270 *out_result_len = new_len;
61271 return 1;
61272 } else {
61273 /*
61274 * Entries part is a bit more complex.
61275 */
61276
61277 /* Stage 1: find highest preventing non-configurable entry (if any).
61278 * When forcing, ignore non-configurability.
61279 */
61280
61281 DUK_DDD(DUK_DDDPRINT("no array part, slow case"));
61282
61283 DUK_DDD(DUK_DDDPRINT("array length write, no array part, stage 1: find target_len "
61284 "(highest preventing non-configurable entry (if any))"));
61285
61286 target_len = new_len;
61287 if (force_flag) {
61288 DUK_DDD(DUK_DDDPRINT("array length write, no array part; force flag -> skip stage 1"));
61289 goto skip_stage1;
61290 }
61291 for (i = 0; i < DUK_HOBJECT_GET_ENEXT(obj); i++) {
61292 key = DUK_HOBJECT_E_GET_KEY(thr->heap, obj, i);
61293 if (!key) {
61294 DUK_DDD(DUK_DDDPRINT("skip entry index %ld: null key", (long) i));
61295 continue;
61296 }
61297 if (!DUK_HSTRING_HAS_ARRIDX(key)) {
61298 DUK_DDD(DUK_DDDPRINT("skip entry index %ld: key not an array index", (long) i));
61299 continue;
61300 }
61301
61302 DUK_ASSERT(
61303 DUK_HSTRING_HAS_ARRIDX(key)); /* XXX: macro checks for array index flag, which is unnecessary here */
61304 arr_idx = DUK_HSTRING_GET_ARRIDX_SLOW(key);
61305 DUK_ASSERT(arr_idx != DUK__NO_ARRAY_INDEX);
61306 DUK_ASSERT(arr_idx < old_len); /* consistency requires this */
61307
61308 if (arr_idx < new_len) {
61309 DUK_DDD(DUK_DDDPRINT("skip entry index %ld: key is array index %ld, below new_len",
61310 (long) i,
61311 (long) arr_idx));
61312 continue;
61313 }
61314 if (DUK_HOBJECT_E_SLOT_IS_CONFIGURABLE(thr->heap, obj, i)) {
61315 DUK_DDD(DUK_DDDPRINT("skip entry index %ld: key is a relevant array index %ld, but configurable",
61316 (long) i,
61317 (long) arr_idx));
61318 continue;
61319 }
61320
61321 /* relevant array index is non-configurable, blocks write */
61322 if (arr_idx >= target_len) {
61323 DUK_DDD(DUK_DDDPRINT("entry at index %ld has arr_idx %ld, is not configurable, "
61324 "update target_len %ld -> %ld",
61325 (long) i,
61326 (long) arr_idx,
61327 (long) target_len,
61328 (long) (arr_idx + 1)));
61329 target_len = arr_idx + 1;
61330 }
61331 }
61332 skip_stage1:
61333
61334 /* stage 2: delete configurable entries above target length */
61335
61336 DUK_DDD(
61337 DUK_DDDPRINT("old_len=%ld, new_len=%ld, target_len=%ld", (long) old_len, (long) new_len, (long) target_len));
61338
61339 DUK_DDD(DUK_DDDPRINT("array length write, no array part, stage 2: remove "
61340 "entries >= target_len"));
61341
61342 for (i = 0; i < DUK_HOBJECT_GET_ENEXT(obj); i++) {
61343 key = DUK_HOBJECT_E_GET_KEY(thr->heap, obj, i);
61344 if (!key) {
61345 DUK_DDD(DUK_DDDPRINT("skip entry index %ld: null key", (long) i));
61346 continue;
61347 }
61348 if (!DUK_HSTRING_HAS_ARRIDX(key)) {
61349 DUK_DDD(DUK_DDDPRINT("skip entry index %ld: key not an array index", (long) i));
61350 continue;
61351 }
61352
61353 DUK_ASSERT(
61354 DUK_HSTRING_HAS_ARRIDX(key)); /* XXX: macro checks for array index flag, which is unnecessary here */
61355 arr_idx = DUK_HSTRING_GET_ARRIDX_SLOW(key);
61356 DUK_ASSERT(arr_idx != DUK__NO_ARRAY_INDEX);
61357 DUK_ASSERT(arr_idx < old_len); /* consistency requires this */
61358
61359 if (arr_idx < target_len) {
61360 DUK_DDD(DUK_DDDPRINT("skip entry index %ld: key is array index %ld, below target_len",
61361 (long) i,
61362 (long) arr_idx));
61363 continue;
61364 }
61365 DUK_ASSERT(force_flag || DUK_HOBJECT_E_SLOT_IS_CONFIGURABLE(thr->heap, obj, i)); /* stage 1 guarantees */
61366
61367 DUK_DDD(DUK_DDDPRINT("delete entry index %ld: key is array index %ld", (long) i, (long) arr_idx));
61368
61369 /*
61370 * Slow delete, but we don't care as we're already in a very slow path.
61371 * The delete always succeeds: key has no exotic behavior, property
61372 * is configurable, and no resize occurs.
61373 */
61374 rc = duk_hobject_delprop_raw(thr, obj, key, force_flag ? DUK_DELPROP_FLAG_FORCE : 0);
61375 DUK_UNREF(rc);
61376 DUK_ASSERT(rc != 0);
61378
61379 /* stage 3: update length (done by caller), decide return code */
61380
61381 DUK_DDD(DUK_DDDPRINT("array length write, no array part, stage 3: update length (done by caller)"));
61382
61383 *out_result_len = target_len;
61384
61385 if (target_len == new_len) {
61386 DUK_DDD(DUK_DDDPRINT("target_len matches new_len, return success"));
61387 return 1;
61388 }
61389 DUK_DDD(DUK_DDDPRINT("target_len does not match new_len (some entry prevented "
61390 "full length adjustment), return error"));
61391 return 0;
61392 }
61393
61395}
61396
61397/* XXX: is valstack top best place for argument? */
61399 duk_harray *a;
61400 duk_uint32_t old_len;
61401 duk_uint32_t new_len;
61402 duk_uint32_t result_len;
61403 duk_bool_t rc;
61404
61405 DUK_DDD(DUK_DDDPRINT("handling a put operation to array 'length' exotic property, "
61406 "new val: %!T",
61407 (duk_tval *) duk_get_tval(thr, -1)));
61408
61409 DUK_ASSERT(thr != NULL);
61410 DUK_ASSERT(obj != NULL);
61411
61413
61416 a = (duk_harray *) obj;
61418
61420
61421 /*
61422 * Get old and new length
61423 */
61424
61425 old_len = a->length;
61427 DUK_DDD(DUK_DDDPRINT("old_len=%ld, new_len=%ld", (long) old_len, (long) new_len));
61428
61429 /*
61430 * Writability check
61431 */
61432
61434 DUK_DDD(DUK_DDDPRINT("length is not writable, fail"));
61435 return 0;
61436 }
61437
61438 /*
61439 * New length not lower than old length => no changes needed
61440 * (not even array allocation).
61441 */
61442
61443 if (new_len >= old_len) {
61444 DUK_DDD(DUK_DDDPRINT("new length is same or higher than old length, just update length, no deletions"));
61445 a->length = new_len;
61446 return 1;
61447 }
61448
61449 DUK_DDD(DUK_DDDPRINT("new length is lower than old length, probably must delete entries"));
61450
61451 /*
61452 * New length lower than old length => delete elements, then
61453 * update length.
61454 *
61455 * Note: even though a bunch of elements have been deleted, the 'desc' is
61456 * still valid as properties haven't been resized (and entries compacted).
61457 */
61458
61459 rc = duk__handle_put_array_length_smaller(thr, obj, old_len, new_len, 0 /*force_flag*/, &result_len);
61460 DUK_ASSERT(result_len >= new_len && result_len <= old_len);
61461
61462 a->length = result_len;
61463
61464 /* XXX: shrink array allocation or entries compaction here? */
61465
61466 return rc;
61467}
61468
61469/*
61470 * PUTPROP: ECMAScript property write.
61471 *
61472 * Unlike ECMAScript primitive which returns nothing, returns 1 to indicate
61473 * success and 0 to indicate failure (assuming throw is not set).
61474 *
61475 * This is an extremely tricky function. Some examples:
61476 *
61477 * * Currently a decref may trigger a GC, which may compact an object's
61478 * property allocation. Consequently, any entry indices (e_idx) will
61479 * be potentially invalidated by a decref.
61480 *
61481 * * Exotic behaviors (strings, arrays, arguments object) require,
61482 * among other things:
61483 *
61484 * - Preprocessing before and postprocessing after an actual property
61485 * write. For example, array index write requires pre-checking the
61486 * array 'length' property for access control, and may require an
61487 * array 'length' update after the actual write has succeeded (but
61488 * not if it fails).
61489 *
61490 * - Deletion of multiple entries, as a result of array 'length' write.
61491 *
61492 * * Input values are taken as pointers which may point to the valstack.
61493 * If valstack is resized because of the put (this may happen at least
61494 * when the array part is abandoned), the pointers can be invalidated.
61495 * (We currently make a copy of all of the input values to avoid issues.)
61496 */
61497
61499duk_hobject_putprop(duk_hthread *thr, duk_tval *tv_obj, duk_tval *tv_key, duk_tval *tv_val, duk_bool_t throw_flag) {
61500 duk_tval tv_obj_copy;
61501 duk_tval tv_key_copy;
61502 duk_tval tv_val_copy;
61503 duk_hobject *orig = NULL; /* NULL if tv_obj is primitive */
61504 duk_hobject *curr;
61505 duk_hstring *key = NULL;
61506 duk_propdesc desc;
61507 duk_tval *tv;
61508 duk_uint32_t arr_idx;
61509 duk_bool_t rc;
61510 duk_int_t e_idx;
61511 duk_uint_t sanity;
61512 duk_uint32_t new_array_length = 0; /* 0 = no update */
61513
61514 DUK_DDD(DUK_DDDPRINT("putprop: thr=%p, obj=%p, key=%p, val=%p, throw=%ld "
61515 "(obj -> %!T, key -> %!T, val -> %!T)",
61516 (void *) thr,
61517 (void *) tv_obj,
61518 (void *) tv_key,
61519 (void *) tv_val,
61520 (long) throw_flag,
61521 (duk_tval *) tv_obj,
61522 (duk_tval *) tv_key,
61523 (duk_tval *) tv_val));
61524
61525 DUK_ASSERT(thr != NULL);
61526 DUK_ASSERT(thr->heap != NULL);
61527 DUK_ASSERT(tv_obj != NULL);
61528 DUK_ASSERT(tv_key != NULL);
61529 DUK_ASSERT(tv_val != NULL);
61530
61532
61533 DUK_STATS_INC(thr->heap, stats_putprop_all);
61534
61535 /*
61536 * Make a copy of tv_obj, tv_key, and tv_val to avoid any issues of
61537 * them being invalidated by a valstack resize.
61538 *
61539 * XXX: this is an overkill for some paths, so optimize this later
61540 * (or maybe switch to a stack arguments model entirely).
61541 */
61542
61543 DUK_TVAL_SET_TVAL(&tv_obj_copy, tv_obj);
61544 DUK_TVAL_SET_TVAL(&tv_key_copy, tv_key);
61545 DUK_TVAL_SET_TVAL(&tv_val_copy, tv_val);
61546 tv_obj = &tv_obj_copy;
61547 tv_key = &tv_key_copy;
61548 tv_val = &tv_val_copy;
61549
61550 /*
61551 * Coercion and fast path processing.
61552 */
61553
61554 switch (DUK_TVAL_GET_TAG(tv_obj)) {
61555 case DUK_TAG_UNDEFINED:
61556 case DUK_TAG_NULL: {
61557 /* Note: unconditional throw */
61558 DUK_DDD(DUK_DDDPRINT("base object is undefined or null -> reject (object=%!iT)", (duk_tval *) tv_obj));
61559#if defined(DUK_USE_PARANOID_ERRORS)
61561#else
61562 DUK_ERROR_FMT2(thr,
61564 "cannot write property %s of %s",
61565 duk_push_string_tval_readable(thr, tv_key),
61566 duk_push_string_tval_readable(thr, tv_obj));
61567#endif
61568 DUK_WO_NORETURN(return 0;);
61569 break;
61570 }
61571
61572 case DUK_TAG_BOOLEAN: {
61573 DUK_DDD(DUK_DDDPRINT("base object is a boolean, start lookup from boolean prototype"));
61575 break;
61576 }
61577
61578 case DUK_TAG_STRING: {
61579 duk_hstring *h = DUK_TVAL_GET_STRING(tv_obj);
61580
61581 /*
61582 * Note: currently no fast path for array index writes.
61583 * They won't be possible anyway as strings are immutable.
61584 */
61585
61586 DUK_ASSERT(key == NULL);
61587 arr_idx = duk__push_tval_to_property_key(thr, tv_key, &key);
61588 DUK_ASSERT(key != NULL);
61589
61591 /* Symbols (ES2015 or hidden) don't have virtual properties. */
61593 goto lookup;
61594 }
61595
61596 if (key == DUK_HTHREAD_STRING_LENGTH(thr)) {
61597 goto fail_not_writable;
61598 }
61599
61600 if (arr_idx != DUK__NO_ARRAY_INDEX && arr_idx < DUK_HSTRING_GET_CHARLEN(h)) {
61601 goto fail_not_writable;
61602 }
61603
61604 DUK_DDD(DUK_DDDPRINT("base object is a string, start lookup from string prototype"));
61606 goto lookup; /* avoid double coercion */
61607 }
61608
61609 case DUK_TAG_OBJECT: {
61610 orig = DUK_TVAL_GET_OBJECT(tv_obj);
61611 DUK_ASSERT(orig != NULL);
61612
61613#if defined(DUK_USE_ROM_OBJECTS)
61614 /* With this check in place fast paths won't need read-only
61615 * object checks. This is technically incorrect if there are
61616 * setters that cause no writes to ROM objects, but current
61617 * built-ins don't have such setters.
61618 */
61619 if (DUK_HEAPHDR_HAS_READONLY((duk_heaphdr *) orig)) {
61620 DUK_DD(DUK_DDPRINT("attempt to putprop on read-only target object"));
61621 goto fail_not_writable_no_pop; /* Must avoid duk_pop() in exit path */
61622 }
61623#endif
61624
61625 /* The fast path for array property put is not fully compliant:
61626 * If one places conflicting number-indexed properties into
61627 * Array.prototype (for example, a non-writable Array.prototype[7])
61628 * the fast path will incorrectly ignore them.
61629 *
61630 * This fast path could be made compliant by falling through
61631 * to the slow path if the previous value was UNUSED. This would
61632 * also remove the need to check for extensibility. Right now a
61633 * non-extensible array is slower than an extensible one as far
61634 * as writes are concerned.
61635 *
61636 * The fast path behavior is documented in more detail here:
61637 * tests/ecmascript/test-misc-array-fast-write.js
61638 */
61639
61640 /* XXX: array .length? */
61641
61642#if defined(DUK_USE_ARRAY_PROP_FASTPATH)
61643 if (duk__putprop_shallow_fastpath_array_tval(thr, orig, tv_key, tv_val) != 0) {
61644 DUK_DDD(DUK_DDDPRINT("array fast path success"));
61645 DUK_STATS_INC(thr->heap, stats_putprop_arrayidx);
61646 return 1;
61647 }
61648#endif
61649
61650#if defined(DUK_USE_BUFFEROBJECT_SUPPORT)
61651 if (duk__putprop_fastpath_bufobj_tval(thr, orig, tv_key, tv_val) != 0) {
61652 DUK_DDD(DUK_DDDPRINT("base is bufobj, key is a number, bufobj fast path"));
61653 DUK_STATS_INC(thr->heap, stats_putprop_bufobjidx);
61654 return 1;
61655 }
61656#endif
61657
61658#if defined(DUK_USE_ES6_PROXY)
61660 duk_hobject *h_target;
61661 duk_bool_t tmp_bool;
61662
61663 if (duk__proxy_check_prop(thr, orig, DUK_STRIDX_SET, tv_key, &h_target)) {
61664 /* -> [ ... trap handler ] */
61665 DUK_DDD(DUK_DDDPRINT("-> proxy object 'set' for key %!T", (duk_tval *) tv_key));
61666 DUK_STATS_INC(thr->heap, stats_putprop_proxy);
61667 duk_push_hobject(thr, h_target); /* target */
61668 duk_push_tval(thr, tv_key); /* P */
61669 duk_push_tval(thr, tv_val); /* V */
61670 duk_push_tval(thr, tv_obj); /* Receiver: Proxy object */
61671 duk_call_method(thr, 4 /*nargs*/);
61672 tmp_bool = duk_to_boolean_top_pop(thr);
61673 if (!tmp_bool) {
61674 goto fail_proxy_rejected;
61675 }
61676
61677 /* Target object must be checked for a conflicting
61678 * non-configurable property.
61679 */
61680 arr_idx = duk__push_tval_to_property_key(thr, tv_key, &key);
61681 DUK_ASSERT(key != NULL);
61682
61683 if (duk__get_own_propdesc_raw(thr, h_target, key, arr_idx, &desc, DUK_GETDESC_FLAG_PUSH_VALUE)) {
61684 duk_tval *tv_targ = duk_require_tval(thr, -1);
61685 duk_bool_t datadesc_reject;
61686 duk_bool_t accdesc_reject;
61687
61688 DUK_DDD(DUK_DDDPRINT("proxy 'set': target has matching property %!O, check for "
61689 "conflicting property; tv_val=%!T, tv_targ=%!T, desc.flags=0x%08lx, "
61690 "desc.get=%p, desc.set=%p",
61691 (duk_heaphdr *) key,
61692 (duk_tval *) tv_val,
61693 (duk_tval *) tv_targ,
61694 (unsigned long) desc.flags,
61695 (void *) desc.get,
61696 (void *) desc.set));
61697
61698 datadesc_reject = !(desc.flags & DUK_PROPDESC_FLAG_ACCESSOR) &&
61701 !duk_js_samevalue(tv_val, tv_targ);
61702 accdesc_reject = (desc.flags & DUK_PROPDESC_FLAG_ACCESSOR) &&
61703 !(desc.flags & DUK_PROPDESC_FLAG_CONFIGURABLE) && (desc.set == NULL);
61704 if (datadesc_reject || accdesc_reject) {
61706 DUK_WO_NORETURN(return 0;);
61707 }
61708
61709 duk_pop_2_unsafe(thr);
61710 } else {
61711 duk_pop_unsafe(thr);
61712 }
61713 return 1; /* success */
61714 }
61715
61716 orig = h_target; /* resume write to target */
61717 DUK_TVAL_SET_OBJECT(tv_obj, orig);
61718 }
61719#endif /* DUK_USE_ES6_PROXY */
61720
61721 curr = orig;
61722 break;
61723 }
61724
61725 case DUK_TAG_BUFFER: {
61726 duk_hbuffer *h = DUK_TVAL_GET_BUFFER(tv_obj);
61727 duk_int_t pop_count = 0;
61728
61729 /*
61730 * Because buffer values may be looped over and read/written
61731 * from, an array index fast path is important.
61732 */
61733
61734#if defined(DUK_USE_FASTINT)
61735 if (DUK_TVAL_IS_FASTINT(tv_key)) {
61736 arr_idx = duk__tval_fastint_to_arr_idx(tv_key);
61737 DUK_DDD(DUK_DDDPRINT("base object buffer, key is a fast-path fastint; arr_idx %ld", (long) arr_idx));
61738 pop_count = 0;
61739 } else
61740#endif
61741 if (DUK_TVAL_IS_NUMBER(tv_key)) {
61742 arr_idx = duk__tval_number_to_arr_idx(tv_key);
61743 DUK_DDD(DUK_DDDPRINT("base object buffer, key is a fast-path number; arr_idx %ld", (long) arr_idx));
61744 pop_count = 0;
61745 } else {
61746 arr_idx = duk__push_tval_to_property_key(thr, tv_key, &key);
61747 DUK_ASSERT(key != NULL);
61748 DUK_DDD(DUK_DDDPRINT("base object buffer, key is a non-fast-path number; after "
61749 "coercion key is %!T, arr_idx %ld",
61750 (duk_tval *) duk_get_tval(thr, -1),
61751 (long) arr_idx));
61752 pop_count = 1;
61753 }
61754
61755 if (arr_idx != DUK__NO_ARRAY_INDEX && arr_idx < DUK_HBUFFER_GET_SIZE(h)) {
61756 duk_uint8_t *data;
61757 DUK_DDD(DUK_DDDPRINT("writing to buffer data at index %ld", (long) arr_idx));
61758 data = (duk_uint8_t *) DUK_HBUFFER_GET_DATA_PTR(thr->heap, h);
61759
61760 /* XXX: duk_to_int() ensures we'll get 8 lowest bits as
61761 * as input is within duk_int_t range (capped outside it).
61762 */
61763#if defined(DUK_USE_FASTINT)
61764 /* Buffer writes are often integers. */
61765 if (DUK_TVAL_IS_FASTINT(tv_val)) {
61766 data[arr_idx] = (duk_uint8_t) DUK_TVAL_GET_FASTINT_U32(tv_val);
61767 } else
61768#endif
61769 {
61770 duk_push_tval(thr, tv_val);
61771 data[arr_idx] = (duk_uint8_t) duk_to_uint32(thr, -1);
61772 pop_count++;
61773 }
61774
61775 duk_pop_n_unsafe(thr, pop_count);
61776 DUK_DDD(DUK_DDDPRINT("result: success (buffer data write)"));
61777 DUK_STATS_INC(thr->heap, stats_putprop_bufferidx);
61778 return 1;
61779 }
61780
61781 if (pop_count == 0) {
61782 /* This is a pretty awkward control flow, but we need to recheck the
61783 * key coercion here.
61784 */
61785 arr_idx = duk__push_tval_to_property_key(thr, tv_key, &key);
61786 DUK_ASSERT(key != NULL);
61787 DUK_DDD(DUK_DDDPRINT("base object buffer, key is a non-fast-path number; after "
61788 "coercion key is %!T, arr_idx %ld",
61789 (duk_tval *) duk_get_tval(thr, -1),
61790 (long) arr_idx));
61791 }
61792
61793 if (key == DUK_HTHREAD_STRING_LENGTH(thr)) {
61794 goto fail_not_writable;
61795 }
61796
61797 DUK_DDD(DUK_DDDPRINT("base object is a buffer, start lookup from Uint8Array prototype"));
61799 goto lookup; /* avoid double coercion */
61800 }
61801
61802 case DUK_TAG_POINTER: {
61803 DUK_DDD(DUK_DDDPRINT("base object is a pointer, start lookup from pointer prototype"));
61805 break;
61806 }
61807
61808 case DUK_TAG_LIGHTFUNC: {
61809 /* Lightfuncs have no own properties and are considered non-extensible.
61810 * However, the write may be captured by an inherited setter which
61811 * means we can't stop the lookup here.
61812 */
61813 DUK_DDD(DUK_DDDPRINT("base object is a lightfunc, start lookup from function prototype"));
61815 break;
61816 }
61817
61818#if defined(DUK_USE_FASTINT)
61819 case DUK_TAG_FASTINT:
61820#endif
61821 default: {
61822 /* number */
61823 DUK_DDD(DUK_DDDPRINT("base object is a number, start lookup from number prototype"));
61826 break;
61827 }
61828 }
61829
61830 DUK_ASSERT(key == NULL);
61831 arr_idx = duk__push_tval_to_property_key(thr, tv_key, &key);
61832 DUK_ASSERT(key != NULL);
61833
61834lookup:
61835
61836 /*
61837 * Check whether the property already exists in the prototype chain.
61838 * Note that the actual write goes into the original base object
61839 * (except if an accessor property captures the write).
61840 */
61841
61842 /* [key] */
61843
61844 DUK_ASSERT(curr != NULL);
61846 do {
61847 if (!duk__get_own_propdesc_raw(thr, curr, key, arr_idx, &desc, 0 /*flags*/)) { /* don't push value */
61848 goto next_in_chain;
61849 }
61850
61851 if (desc.flags & DUK_PROPDESC_FLAG_ACCESSOR) {
61852 /*
61853 * Found existing accessor property (own or inherited).
61854 * Call setter with 'this' set to orig, and value as the only argument.
61855 * Setter calls are OK even for ROM objects.
61856 *
61857 * Note: no exotic arguments object behavior, because [[Put]] never
61858 * calls [[DefineOwnProperty]] (E5 Section 8.12.5, step 5.b).
61859 */
61860
61861 duk_hobject *setter;
61862
61863 DUK_DD(DUK_DDPRINT("put to an own or inherited accessor, calling setter"));
61864
61865 setter = DUK_HOBJECT_E_GET_VALUE_SETTER(thr->heap, curr, desc.e_idx);
61866 if (!setter) {
61867 goto fail_no_setter;
61868 }
61869 duk_push_hobject(thr, setter);
61870 duk_push_tval(thr, tv_obj); /* note: original, uncoerced base */
61871 duk_push_tval(thr, tv_val); /* [key setter this val] */
61872#if defined(DUK_USE_NONSTD_SETTER_KEY_ARGUMENT)
61873 duk_dup_m4(thr);
61874 duk_call_method(thr, 2); /* [key setter this val key] -> [key retval] */
61875#else
61876 duk_call_method(thr, 1); /* [key setter this val] -> [key retval] */
61877#endif
61878 duk_pop_unsafe(thr); /* ignore retval -> [key] */
61879 goto success_no_arguments_exotic;
61880 }
61881
61882 if (orig == NULL) {
61883 /*
61884 * Found existing own or inherited plain property, but original
61885 * base is a primitive value.
61886 */
61887 DUK_DD(DUK_DDPRINT("attempt to create a new property in a primitive base object"));
61888 goto fail_base_primitive;
61889 }
61890
61891 if (curr != orig) {
61892 /*
61893 * Found existing inherited plain property.
61894 * Do an access control check, and if OK, write
61895 * new property to 'orig'.
61896 */
61897 if (!DUK_HOBJECT_HAS_EXTENSIBLE(orig)) {
61898 DUK_DD(
61899 DUK_DDPRINT("found existing inherited plain property, but original object is not extensible"));
61900 goto fail_not_extensible;
61901 }
61902 if (!(desc.flags & DUK_PROPDESC_FLAG_WRITABLE)) {
61903 DUK_DD(DUK_DDPRINT("found existing inherited plain property, original object is extensible, but "
61904 "inherited property is not writable"));
61905 goto fail_not_writable;
61906 }
61907 DUK_DD(DUK_DDPRINT("put to new property, object extensible, inherited property found and is writable"));
61908 goto create_new;
61909 } else {
61910 /*
61911 * Found existing own (non-inherited) plain property.
61912 * Do an access control check and update in place.
61913 */
61914
61915 if (!(desc.flags & DUK_PROPDESC_FLAG_WRITABLE)) {
61916 DUK_DD(
61917 DUK_DDPRINT("found existing own (non-inherited) plain property, but property is not writable"));
61918 goto fail_not_writable;
61919 }
61920 if (desc.flags & DUK_PROPDESC_FLAG_VIRTUAL) {
61921 DUK_DD(DUK_DDPRINT("found existing own (non-inherited) virtual property, property is writable"));
61922
61923 if (DUK_HOBJECT_IS_ARRAY(curr)) {
61924 /*
61925 * Write to 'length' of an array is a very complex case
61926 * handled in a helper which updates both the array elements
61927 * and writes the new 'length'. The write may result in an
61928 * unconditional RangeError or a partial write (indicated
61929 * by a return code).
61930 *
61931 * Note: the helper has an unnecessary writability check
61932 * for 'length', we already know it is writable.
61933 */
61934 DUK_ASSERT(key == DUK_HTHREAD_STRING_LENGTH(thr)); /* only virtual array property */
61935
61937 "writing existing 'length' property to array exotic, invoke complex helper"));
61938
61939 /* XXX: the helper currently assumes stack top contains new
61940 * 'length' value and the whole calling convention is not very
61941 * compatible with what we need.
61942 */
61943
61944 duk_push_tval(thr, tv_val); /* [key val] */
61945 rc = duk__handle_put_array_length(thr, orig);
61946 duk_pop_unsafe(thr); /* [key val] -> [key] */
61947 if (!rc) {
61948 goto fail_array_length_partial;
61949 }
61950
61951 /* key is 'length', cannot match argument exotic behavior */
61952 goto success_no_arguments_exotic;
61953 }
61954#if defined(DUK_USE_BUFFEROBJECT_SUPPORT)
61955 else if (DUK_HOBJECT_IS_BUFOBJ(curr)) {
61956 duk_hbufobj *h_bufobj;
61957 duk_uint_t byte_off;
61958 duk_small_uint_t elem_size;
61959
61960 h_bufobj = (duk_hbufobj *) curr;
61961 DUK_HBUFOBJ_ASSERT_VALID(h_bufobj);
61962
61963 DUK_DD(DUK_DDPRINT("writable virtual property is in buffer object"));
61964
61965 /* Careful with wrapping: arr_idx upshift may easily wrap, whereas
61966 * length downshift won't.
61967 */
61968 if (arr_idx < (h_bufobj->length >> h_bufobj->shift) &&
61970 duk_uint8_t *data;
61971 DUK_DDD(DUK_DDDPRINT("writing to buffer data at index %ld", (long) arr_idx));
61972
61973 DUK_ASSERT(arr_idx != DUK__NO_ARRAY_INDEX); /* index/length check guarantees */
61974 byte_off = arr_idx
61975 << h_bufobj->shift; /* no wrap assuming h_bufobj->length is valid */
61976 elem_size = (duk_small_uint_t) (1U << h_bufobj->shift);
61977
61978 /* Coerce to number before validating pointers etc so that the
61979 * number coercions in duk_hbufobj_validated_write() are
61980 * guaranteed to be side effect free and not invalidate the
61981 * pointer checks we do here.
61982 */
61983 duk_push_tval(thr, tv_val);
61984 (void) duk_to_number_m1(thr);
61985
61986 if (h_bufobj->buf != NULL &&
61987 DUK_HBUFOBJ_VALID_BYTEOFFSET_EXCL(h_bufobj, byte_off + elem_size)) {
61988 data = (duk_uint8_t *) DUK_HBUFFER_GET_DATA_PTR(thr->heap, h_bufobj->buf) +
61989 h_bufobj->offset + byte_off;
61990 duk_hbufobj_validated_write(thr, h_bufobj, data, elem_size);
61991 } else {
61993 "bufobj access out of underlying buffer, ignoring (write skipped)"));
61994 }
61995 duk_pop_unsafe(thr);
61996 goto success_no_arguments_exotic;
61997 }
61998 }
61999#endif /* DUK_USE_BUFFEROBJECT_SUPPORT */
62000
62001 DUK_D(DUK_DPRINT("should not happen, key %!O", key));
62002 goto fail_internal; /* should not happen */
62003 }
62004 DUK_DD(DUK_DDPRINT("put to existing own plain property, property is writable"));
62005 goto update_old;
62006 }
62008
62009 next_in_chain:
62010 /* XXX: option to pretend property doesn't exist if sanity limit is
62011 * hit might be useful.
62012 */
62013 if (DUK_UNLIKELY(sanity-- == 0)) {
62015 DUK_WO_NORETURN(return 0;);
62016 }
62017 curr = DUK_HOBJECT_GET_PROTOTYPE(thr->heap, curr);
62018 } while (curr != NULL);
62019
62020 /*
62021 * Property not found in prototype chain.
62022 */
62023
62024 DUK_DDD(DUK_DDDPRINT("property not found in prototype chain"));
62025
62026 if (orig == NULL) {
62027 DUK_DD(DUK_DDPRINT("attempt to create a new property in a primitive base object"));
62028 goto fail_base_primitive;
62029 }
62030
62031 if (!DUK_HOBJECT_HAS_EXTENSIBLE(orig)) {
62032 DUK_DD(DUK_DDPRINT("put to a new property (not found in prototype chain), but original object not extensible"));
62033 goto fail_not_extensible;
62034 }
62035
62036 goto create_new;
62037
62038update_old:
62039
62040 /*
62041 * Update an existing property of the base object.
62042 */
62043
62044 /* [key] */
62045
62046 DUK_DDD(DUK_DDDPRINT("update an existing property of the original object"));
62047
62048 DUK_ASSERT(orig != NULL);
62049#if defined(DUK_USE_ROM_OBJECTS)
62050 /* This should not happen because DUK_TAG_OBJECT case checks
62051 * for this already, but check just in case.
62052 */
62053 if (DUK_HEAPHDR_HAS_READONLY((duk_heaphdr *) orig)) {
62054 goto fail_not_writable;
62055 }
62056#endif
62057
62058 /* Although there are writable virtual properties (e.g. plain buffer
62059 * and buffer object number indices), they are handled before we come
62060 * here.
62061 */
62063 DUK_ASSERT(desc.a_idx >= 0 || desc.e_idx >= 0);
62064
62065 /* Array own property .length is handled above. */
62067
62068 if (desc.e_idx >= 0) {
62069 tv = DUK_HOBJECT_E_GET_VALUE_TVAL_PTR(thr->heap, orig, desc.e_idx);
62070 DUK_DDD(DUK_DDDPRINT("previous entry value: %!iT", (duk_tval *) tv));
62071 DUK_TVAL_SET_TVAL_UPDREF(thr, tv, tv_val); /* side effects; e_idx may be invalidated */
62072 /* don't touch property attributes or hash part */
62073 DUK_DD(DUK_DDPRINT("put to an existing entry at index %ld -> new value %!iT", (long) desc.e_idx, (duk_tval *) tv));
62074 } else {
62075 /* Note: array entries are always writable, so the writability check
62076 * above is pointless for them. The check could be avoided with some
62077 * refactoring but is probably not worth it.
62078 */
62079
62080 DUK_ASSERT(desc.a_idx >= 0);
62081 tv = DUK_HOBJECT_A_GET_VALUE_PTR(thr->heap, orig, desc.a_idx);
62082 DUK_DDD(DUK_DDDPRINT("previous array value: %!iT", (duk_tval *) tv));
62083 DUK_TVAL_SET_TVAL_UPDREF(thr, tv, tv_val); /* side effects; a_idx may be invalidated */
62084 DUK_DD(DUK_DDPRINT("put to an existing array entry at index %ld -> new value %!iT",
62085 (long) desc.a_idx,
62086 (duk_tval *) tv));
62087 }
62088
62089 /* Regardless of whether property is found in entry or array part,
62090 * it may have arguments exotic behavior (array indices may reside
62091 * in entry part for abandoned / non-existent array parts).
62092 */
62093 goto success_with_arguments_exotic;
62094
62095create_new:
62096
62097 /*
62098 * Create a new property in the original object.
62099 *
62100 * Exotic properties need to be reconsidered here from a write
62101 * perspective (not just property attributes perspective).
62102 * However, the property does not exist in the object already,
62103 * so this limits the kind of exotic properties that apply.
62104 */
62105
62106 /* [key] */
62107
62108 DUK_DDD(DUK_DDDPRINT("create new property to original object"));
62109
62110 DUK_ASSERT(orig != NULL);
62111
62112 /* Array own property .length is handled above. */
62114
62115#if defined(DUK_USE_ROM_OBJECTS)
62116 /* This should not happen because DUK_TAG_OBJECT case checks
62117 * for this already, but check just in case.
62118 */
62119 if (DUK_HEAPHDR_HAS_READONLY((duk_heaphdr *) orig)) {
62120 goto fail_not_writable;
62121 }
62122#endif
62123
62124 /* Not possible because array object 'length' is present
62125 * from its creation and cannot be deleted, and is thus
62126 * caught as an existing property above.
62127 */
62129
62130 if (DUK_HOBJECT_HAS_EXOTIC_ARRAY(orig) && arr_idx != DUK__NO_ARRAY_INDEX) {
62131 /* automatic length update */
62132 duk_uint32_t old_len;
62133 duk_harray *a;
62134
62135 a = (duk_harray *) orig;
62137
62138 old_len = a->length;
62139
62140 if (arr_idx >= old_len) {
62141 DUK_DDD(DUK_DDDPRINT("write new array entry requires length update "
62142 "(arr_idx=%ld, old_len=%ld)",
62143 (long) arr_idx,
62144 (long) old_len));
62145
62147 DUK_DD(DUK_DDPRINT("attempt to extend array, but array 'length' is not writable"));
62148 goto fail_not_writable;
62149 }
62150
62151 /* Note: actual update happens once write has been completed
62152 * without error below. The write should always succeed
62153 * from a specification viewpoint, but we may e.g. run out
62154 * of memory. It's safer in this order.
62155 */
62156
62157 DUK_ASSERT(arr_idx != 0xffffffffUL);
62158 new_array_length = arr_idx + 1; /* flag for later write */
62159 } else {
62160 DUK_DDD(DUK_DDDPRINT("write new array entry does not require length update "
62161 "(arr_idx=%ld, old_len=%ld)",
62162 (long) arr_idx,
62163 (long) old_len));
62164 }
62165 }
62166
62167 /* write_to_array_part: */
62168
62169 /*
62170 * Write to array part?
62171 *
62172 * Note: array abandonding requires a property resize which uses
62173 * 'rechecks' valstack for temporaries and may cause any existing
62174 * valstack pointers to be invalidated. To protect against this,
62175 * tv_obj, tv_key, and tv_val are copies of the original inputs.
62176 */
62177
62178 if (arr_idx != DUK__NO_ARRAY_INDEX && DUK_HOBJECT_HAS_ARRAY_PART(orig)) {
62179 tv = duk__obtain_arridx_slot(thr, arr_idx, orig);
62180 if (tv == NULL) {
62182 goto write_to_entry_part;
62183 }
62184
62185 /* prev value must be unused, no decref */
62187 DUK_TVAL_SET_TVAL(tv, tv_val);
62188 DUK_TVAL_INCREF(thr, tv);
62189 DUK_DD(DUK_DDPRINT("put to new array entry: %ld -> %!T", (long) arr_idx, (duk_tval *) tv));
62190
62191 /* Note: array part values are [[Writable]], [[Enumerable]],
62192 * and [[Configurable]] which matches the required attributes
62193 * here.
62194 */
62195 goto entry_updated;
62196 }
62197
62198write_to_entry_part:
62199
62200 /*
62201 * Write to entry part
62202 */
62203
62204 /* entry allocation updates hash part and increases the key
62205 * refcount; may need a props allocation resize but doesn't
62206 * 'recheck' the valstack.
62207 */
62208 e_idx = duk__hobject_alloc_entry_checked(thr, orig, key);
62209 DUK_ASSERT(e_idx >= 0);
62210
62211 tv = DUK_HOBJECT_E_GET_VALUE_TVAL_PTR(thr->heap, orig, e_idx);
62212 /* prev value can be garbage, no decref */
62213 DUK_TVAL_SET_TVAL(tv, tv_val);
62214 DUK_TVAL_INCREF(thr, tv);
62216 goto entry_updated;
62217
62218entry_updated:
62219
62220 /*
62221 * Possible pending array length update, which must only be done
62222 * if the actual entry write succeeded.
62223 */
62224
62225 if (new_array_length > 0) {
62226 /* Note: zero works as a "no update" marker because the new length
62227 * can never be zero after a new property is written.
62228 */
62229
62231
62232 DUK_DDD(DUK_DDDPRINT("write successful, pending array length update to: %ld", (long) new_array_length));
62233
62234 ((duk_harray *) orig)->length = new_array_length;
62235 }
62236
62237 /*
62238 * Arguments exotic behavior not possible for new properties: all
62239 * magically bound properties are initially present in the arguments
62240 * object, and if they are deleted, the binding is also removed from
62241 * parameter map.
62242 */
62243
62244 goto success_no_arguments_exotic;
62245
62246success_with_arguments_exotic:
62247
62248 /*
62249 * Arguments objects have exotic [[DefineOwnProperty]] which updates
62250 * the internal 'map' of arguments for writes to currently mapped
62251 * arguments. More conretely, writes to mapped arguments generate
62252 * a write to a bound variable.
62253 *
62254 * The [[Put]] algorithm invokes [[DefineOwnProperty]] for existing
62255 * data properties and new properties, but not for existing accessors.
62256 * Hence, in E5 Section 10.6 ([[DefinedOwnProperty]] algorithm), we
62257 * have a Desc with 'Value' (and possibly other properties too), and
62258 * we end up in step 5.b.i.
62259 */
62260
62261 if (arr_idx != DUK__NO_ARRAY_INDEX && DUK_HOBJECT_HAS_EXOTIC_ARGUMENTS(orig)) {
62262 /* Note: only numbered indices are relevant, so arr_idx fast reject
62263 * is good (this is valid unless there are more than 4**32-1 arguments).
62264 */
62265
62266 DUK_DDD(DUK_DDDPRINT("putprop successful, arguments exotic behavior needed"));
62267
62268 /* Note: we can reuse 'desc' here */
62269
62270 /* XXX: top of stack must contain value, which helper doesn't touch,
62271 * rework to use tv_val directly?
62272 */
62273
62274 duk_push_tval(thr, tv_val);
62275 (void) duk__check_arguments_map_for_put(thr, orig, key, &desc, throw_flag);
62276 duk_pop_unsafe(thr);
62277 }
62278 /* fall thru */
62279
62280success_no_arguments_exotic:
62281 /* shared exit path now */
62282 DUK_DDD(DUK_DDDPRINT("result: success"));
62283 duk_pop_unsafe(thr); /* remove key */
62284 return 1;
62285
62286#if defined(DUK_USE_ES6_PROXY)
62287fail_proxy_rejected:
62288 DUK_DDD(DUK_DDDPRINT("result: error, proxy rejects"));
62289 if (throw_flag) {
62291 DUK_WO_NORETURN(return 0;);
62292 }
62293 /* Note: no key on stack */
62294 return 0;
62295#endif
62296
62297fail_base_primitive:
62298 DUK_DDD(DUK_DDDPRINT("result: error, base primitive"));
62299 if (throw_flag) {
62300#if defined(DUK_USE_PARANOID_ERRORS)
62302#else
62303 DUK_ERROR_FMT2(thr,
62305 "cannot write property %s of %s",
62306 duk_push_string_tval_readable(thr, tv_key),
62307 duk_push_string_tval_readable(thr, tv_obj));
62308#endif
62309 DUK_WO_NORETURN(return 0;);
62310 }
62311 duk_pop_unsafe(thr); /* remove key */
62312 return 0;
62313
62314fail_not_extensible:
62315 DUK_DDD(DUK_DDDPRINT("result: error, not extensible"));
62316 if (throw_flag) {
62318 DUK_WO_NORETURN(return 0;);
62319 }
62320 duk_pop_unsafe(thr); /* remove key */
62321 return 0;
62322
62323fail_not_writable:
62324 DUK_DDD(DUK_DDDPRINT("result: error, not writable"));
62325 if (throw_flag) {
62327 DUK_WO_NORETURN(return 0;);
62328 }
62329 duk_pop_unsafe(thr); /* remove key */
62330 return 0;
62331
62332#if defined(DUK_USE_ROM_OBJECTS)
62333fail_not_writable_no_pop:
62334 DUK_DDD(DUK_DDDPRINT("result: error, not writable"));
62335 if (throw_flag) {
62337 DUK_WO_NORETURN(return 0;);
62338 }
62339 return 0;
62340#endif
62341
62342fail_array_length_partial:
62343 DUK_DD(DUK_DDPRINT("result: error, array length write only partially successful"));
62344 if (throw_flag) {
62346 DUK_WO_NORETURN(return 0;);
62347 }
62348 duk_pop_unsafe(thr); /* remove key */
62349 return 0;
62350
62351fail_no_setter:
62352 DUK_DDD(DUK_DDDPRINT("result: error, accessor property without setter"));
62353 if (throw_flag) {
62355 DUK_WO_NORETURN(return 0;);
62356 }
62357 duk_pop_unsafe(thr); /* remove key */
62358 return 0;
62359
62360fail_internal:
62361 DUK_DDD(DUK_DDDPRINT("result: error, internal"));
62362 if (throw_flag) {
62363 DUK_ERROR_INTERNAL(thr);
62364 DUK_WO_NORETURN(return 0;);
62365 }
62366 duk_pop_unsafe(thr); /* remove key */
62367 return 0;
62368}
62369
62370/*
62371 * ECMAScript compliant [[Delete]](P, Throw).
62372 */
62373
62375 duk_propdesc desc;
62376 duk_tval *tv;
62377 duk_uint32_t arr_idx;
62378 duk_bool_t throw_flag;
62379 duk_bool_t force_flag;
62380
62381 throw_flag = (flags & DUK_DELPROP_FLAG_THROW);
62382 force_flag = (flags & DUK_DELPROP_FLAG_FORCE);
62383
62384 DUK_DDD(DUK_DDDPRINT("delprop_raw: thr=%p, obj=%p, key=%p, throw=%ld, force=%ld (obj -> %!O, key -> %!O)",
62385 (void *) thr,
62386 (void *) obj,
62387 (void *) key,
62388 (long) throw_flag,
62389 (long) force_flag,
62390 (duk_heaphdr *) obj,
62391 (duk_heaphdr *) key));
62392
62393 DUK_ASSERT(thr != NULL);
62394 DUK_ASSERT(thr->heap != NULL);
62395 DUK_ASSERT(obj != NULL);
62396 DUK_ASSERT(key != NULL);
62397
62399
62400 arr_idx = DUK_HSTRING_GET_ARRIDX_FAST(key);
62401
62402 /* 0 = don't push current value */
62403 if (!duk__get_own_propdesc_raw(thr, obj, key, arr_idx, &desc, 0 /*flags*/)) { /* don't push value */
62404 DUK_DDD(DUK_DDDPRINT("property not found, succeed always"));
62405 goto success;
62406 }
62407
62408#if defined(DUK_USE_ROM_OBJECTS)
62410 DUK_DD(DUK_DDPRINT("attempt to delprop on read-only target object"));
62411 goto fail_not_configurable;
62412 }
62413#endif
62414
62415 if ((desc.flags & DUK_PROPDESC_FLAG_CONFIGURABLE) == 0 && !force_flag) {
62416 goto fail_not_configurable;
62417 }
62418 if (desc.a_idx < 0 && desc.e_idx < 0) {
62419 /* Currently there are no deletable virtual properties, but
62420 * with force_flag we might attempt to delete one.
62421 */
62422 DUK_DD(DUK_DDPRINT("delete failed: property found, force flag, but virtual (and implicitly non-configurable)"));
62423 goto fail_virtual;
62424 }
62425
62426 if (desc.a_idx >= 0) {
62427 DUK_ASSERT(desc.e_idx < 0);
62428
62429 tv = DUK_HOBJECT_A_GET_VALUE_PTR(thr->heap, obj, desc.a_idx);
62430 DUK_TVAL_SET_UNUSED_UPDREF(thr, tv); /* side effects */
62431 goto success;
62432 } else {
62433 DUK_ASSERT(desc.a_idx < 0);
62434
62435 /* remove hash entry (no decref) */
62436#if defined(DUK_USE_HOBJECT_HASH_PART)
62437 if (desc.h_idx >= 0) {
62438 duk_uint32_t *h_base = DUK_HOBJECT_H_GET_BASE(thr->heap, obj);
62439
62440 DUK_DDD(DUK_DDDPRINT("removing hash entry at h_idx %ld", (long) desc.h_idx));
62442 DUK_ASSERT((duk_uint32_t) desc.h_idx < DUK_HOBJECT_GET_HSIZE(obj));
62443 h_base[desc.h_idx] = DUK__HASH_DELETED;
62444 } else {
62446 }
62447#else
62449#endif
62450
62451 /* Remove value. This requires multiple writes so avoid side
62452 * effects via no-refzero macros so that e_idx is not
62453 * invalidated.
62454 */
62455 DUK_DDD(DUK_DDDPRINT("before removing value, e_idx %ld, key %p, key at slot %p",
62456 (long) desc.e_idx,
62457 (void *) key,
62458 (void *) DUK_HOBJECT_E_GET_KEY(thr->heap, obj, desc.e_idx)));
62459 DUK_DDD(DUK_DDDPRINT("removing value at e_idx %ld", (long) desc.e_idx));
62460 if (DUK_HOBJECT_E_SLOT_IS_ACCESSOR(thr->heap, obj, desc.e_idx)) {
62461 duk_hobject *tmp;
62462
62463 tmp = DUK_HOBJECT_E_GET_VALUE_GETTER(thr->heap, obj, desc.e_idx);
62464 DUK_HOBJECT_E_SET_VALUE_GETTER(thr->heap, obj, desc.e_idx, NULL);
62465 DUK_UNREF(tmp);
62467
62468 tmp = DUK_HOBJECT_E_GET_VALUE_SETTER(thr->heap, obj, desc.e_idx);
62469 DUK_HOBJECT_E_SET_VALUE_SETTER(thr->heap, obj, desc.e_idx, NULL);
62470 DUK_UNREF(tmp);
62472 } else {
62473 tv = DUK_HOBJECT_E_GET_VALUE_TVAL_PTR(thr->heap, obj, desc.e_idx);
62475 }
62476#if 0
62477 /* Not strictly necessary because if key == NULL, flag MUST be ignored. */
62478 DUK_HOBJECT_E_SET_FLAGS(thr->heap, obj, desc.e_idx, 0);
62479#endif
62480
62481 /* Remove key. */
62482 DUK_DDD(DUK_DDDPRINT("before removing key, e_idx %ld, key %p, key at slot %p",
62483 (long) desc.e_idx,
62484 (void *) key,
62485 (void *) DUK_HOBJECT_E_GET_KEY(thr->heap, obj, desc.e_idx)));
62486 DUK_DDD(DUK_DDDPRINT("removing key at e_idx %ld", (long) desc.e_idx));
62487 DUK_ASSERT(key == DUK_HOBJECT_E_GET_KEY(thr->heap, obj, desc.e_idx));
62488 DUK_HOBJECT_E_SET_KEY(thr->heap, obj, desc.e_idx, NULL);
62489 DUK_HSTRING_DECREF_NORZ(thr, key);
62490
62491 /* Trigger refzero side effects only when we're done as a
62492 * finalizer might operate on the object and affect the
62493 * e_idx we're supposed to use.
62494 */
62496 goto success;
62497 }
62498
62500
62501success:
62502 /*
62503 * Argument exotic [[Delete]] behavior (E5 Section 10.6) is
62504 * a post-check, keeping arguments internal 'map' in sync with
62505 * any successful deletes (note that property does not need to
62506 * exist for delete to 'succeed').
62507 *
62508 * Delete key from 'map'. Since 'map' only contains array index
62509 * keys, we can use arr_idx for a fast skip.
62510 */
62511
62512 DUK_DDD(DUK_DDDPRINT("delete successful, check for arguments exotic behavior"));
62513
62515 /* Note: only numbered indices are relevant, so arr_idx fast reject
62516 * is good (this is valid unless there are more than 4**32-1 arguments).
62517 */
62518
62519 DUK_DDD(DUK_DDDPRINT("delete successful, arguments exotic behavior needed"));
62520
62521 /* Note: we can reuse 'desc' here */
62522 (void) duk__check_arguments_map_for_delete(thr, obj, key, &desc);
62523 }
62524
62525 DUK_DDD(DUK_DDDPRINT("delete successful"));
62526 return 1;
62527
62528fail_virtual: /* just use the same "not configurable" error message */
62529fail_not_configurable:
62530 DUK_DDD(DUK_DDDPRINT("delete failed: property found, not configurable"));
62531
62532 if (throw_flag) {
62534 DUK_WO_NORETURN(return 0;);
62535 }
62536 return 0;
62537}
62538
62539/*
62540 * DELPROP: ECMAScript property deletion.
62541 */
62542
62544 duk_hstring *key = NULL;
62545#if defined(DUK_USE_ES6_PROXY)
62546 duk_propdesc desc;
62547#endif
62548 duk_int_t entry_top;
62549 duk_uint32_t arr_idx = DUK__NO_ARRAY_INDEX;
62550 duk_bool_t rc;
62551
62552 DUK_DDD(DUK_DDDPRINT("delprop: thr=%p, obj=%p, key=%p (obj -> %!T, key -> %!T)",
62553 (void *) thr,
62554 (void *) tv_obj,
62555 (void *) tv_key,
62556 (duk_tval *) tv_obj,
62557 (duk_tval *) tv_key));
62558
62559 DUK_ASSERT(thr != NULL);
62560 DUK_ASSERT(thr->heap != NULL);
62561 DUK_ASSERT(tv_obj != NULL);
62562 DUK_ASSERT(tv_key != NULL);
62563
62565
62566 /* Storing the entry top is cheaper here to ensure stack is correct at exit,
62567 * as there are several paths out.
62568 */
62569 entry_top = duk_get_top(thr);
62570
62571 if (DUK_TVAL_IS_UNDEFINED(tv_obj) || DUK_TVAL_IS_NULL(tv_obj)) {
62572 DUK_DDD(DUK_DDDPRINT("base object is undefined or null -> reject"));
62573 goto fail_invalid_base_uncond;
62574 }
62575
62576 duk_push_tval(thr, tv_obj);
62577 duk_push_tval(thr, tv_key);
62578
62579 tv_obj = DUK_GET_TVAL_NEGIDX(thr, -2);
62580 if (DUK_TVAL_IS_OBJECT(tv_obj)) {
62581 duk_hobject *obj = DUK_TVAL_GET_OBJECT(tv_obj);
62582 DUK_ASSERT(obj != NULL);
62583
62584#if defined(DUK_USE_ES6_PROXY)
62586 duk_hobject *h_target;
62587 duk_bool_t tmp_bool;
62588
62589 /* Note: proxy handling must happen before key is string coerced. */
62590
62591 if (duk__proxy_check_prop(thr, obj, DUK_STRIDX_DELETE_PROPERTY, tv_key, &h_target)) {
62592 /* -> [ ... obj key trap handler ] */
62593 DUK_DDD(DUK_DDDPRINT("-> proxy object 'deleteProperty' for key %!T", (duk_tval *) tv_key));
62594 duk_push_hobject(thr, h_target); /* target */
62595 duk_dup_m4(thr); /* P */
62596 duk_call_method(thr, 2 /*nargs*/);
62597 tmp_bool = duk_to_boolean_top_pop(thr);
62598 if (!tmp_bool) {
62599 goto fail_proxy_rejected; /* retval indicates delete failed */
62600 }
62601
62602 /* Target object must be checked for a conflicting
62603 * non-configurable property.
62604 */
62605 tv_key = DUK_GET_TVAL_NEGIDX(thr, -1);
62606 arr_idx = duk__push_tval_to_property_key(thr, tv_key, &key);
62607 DUK_ASSERT(key != NULL);
62608
62609 if (duk__get_own_propdesc_raw(thr, h_target, key, arr_idx, &desc, 0 /*flags*/)) { /* don't push
62610 value */
62611 duk_small_int_t desc_reject;
62612
62613 DUK_DDD(DUK_DDDPRINT("proxy 'deleteProperty': target has matching property %!O, check for "
62614 "conflicting property; desc.flags=0x%08lx, "
62615 "desc.get=%p, desc.set=%p",
62616 (duk_heaphdr *) key,
62617 (unsigned long) desc.flags,
62618 (void *) desc.get,
62619 (void *) desc.set));
62620
62621 desc_reject = !(desc.flags & DUK_PROPDESC_FLAG_CONFIGURABLE);
62622 if (desc_reject) {
62623 /* unconditional */
62625 DUK_WO_NORETURN(return 0;);
62626 }
62627 }
62628 rc = 1; /* success */
62629 goto done_rc;
62630 }
62631
62632 obj = h_target; /* resume delete to target */
62633 }
62634#endif /* DUK_USE_ES6_PROXY */
62635
62636 arr_idx = duk__to_property_key(thr, -1, &key);
62637 DUK_ASSERT(key != NULL);
62638
62639 rc = duk_hobject_delprop_raw(thr, obj, key, throw_flag ? DUK_DELPROP_FLAG_THROW : 0);
62640 goto done_rc;
62641 } else if (DUK_TVAL_IS_STRING(tv_obj)) {
62642 /* String has .length and array index virtual properties
62643 * which can't be deleted. No need for a symbol check;
62644 * no offending virtual symbols exist.
62645 */
62646 /* XXX: unnecessary string coercion for array indices,
62647 * intentional to keep small.
62648 */
62649 duk_hstring *h = DUK_TVAL_GET_STRING(tv_obj);
62650 DUK_ASSERT(h != NULL);
62651
62652 arr_idx = duk__to_property_key(thr, -1, &key);
62653 DUK_ASSERT(key != NULL);
62654
62655 if (key == DUK_HTHREAD_STRING_LENGTH(thr)) {
62656 goto fail_not_configurable;
62657 }
62658
62659 if (arr_idx != DUK__NO_ARRAY_INDEX && arr_idx < DUK_HSTRING_GET_CHARLEN(h)) {
62660 goto fail_not_configurable;
62661 }
62662 } else if (DUK_TVAL_IS_BUFFER(tv_obj)) {
62663 /* XXX: unnecessary string coercion for array indices,
62664 * intentional to keep small; some overlap with string
62665 * handling.
62666 */
62667 duk_hbuffer *h = DUK_TVAL_GET_BUFFER(tv_obj);
62668 DUK_ASSERT(h != NULL);
62669
62670 arr_idx = duk__to_property_key(thr, -1, &key);
62671 DUK_ASSERT(key != NULL);
62672
62673 if (key == DUK_HTHREAD_STRING_LENGTH(thr)) {
62674 goto fail_not_configurable;
62675 }
62676
62677 if (arr_idx != DUK__NO_ARRAY_INDEX && arr_idx < DUK_HBUFFER_GET_SIZE(h)) {
62678 goto fail_not_configurable;
62679 }
62680 } else if (DUK_TVAL_IS_LIGHTFUNC(tv_obj)) {
62681 /* Lightfunc has no virtual properties since Duktape 2.2
62682 * so success. Still must coerce key for side effects.
62683 */
62684
62685 arr_idx = duk__to_property_key(thr, -1, &key);
62686 DUK_ASSERT(key != NULL);
62687 DUK_UNREF(key);
62688 }
62689
62690 /* non-object base, no offending virtual property */
62691 rc = 1;
62692 goto done_rc;
62693
62694done_rc:
62695 duk_set_top_unsafe(thr, entry_top);
62696 return rc;
62697
62698fail_invalid_base_uncond:
62699 /* Note: unconditional throw */
62700 DUK_ASSERT(duk_get_top(thr) == entry_top);
62701#if defined(DUK_USE_PARANOID_ERRORS)
62703#else
62704 DUK_ERROR_FMT2(thr,
62706 "cannot delete property %s of %s",
62707 duk_push_string_tval_readable(thr, tv_key),
62708 duk_push_string_tval_readable(thr, tv_obj));
62709#endif
62710 DUK_WO_NORETURN(return 0;);
62711
62712#if defined(DUK_USE_ES6_PROXY)
62713fail_proxy_rejected:
62714 if (throw_flag) {
62716 DUK_WO_NORETURN(return 0;);
62717 }
62718 duk_set_top_unsafe(thr, entry_top);
62719 return 0;
62720#endif
62721
62722fail_not_configurable:
62723 if (throw_flag) {
62725 DUK_WO_NORETURN(return 0;);
62726 }
62727 duk_set_top_unsafe(thr, entry_top);
62728 return 0;
62730
62731/*
62732 * Internal helper to define a property with specific flags, ignoring
62733 * normal semantics such as extensibility, write protection etc.
62734 * Overwrites any existing value and attributes unless caller requests
62735 * that value only be updated if it doesn't already exists.
62736 *
62737 * Does not support:
62738 * - virtual properties (error if write attempted)
62739 * - getter/setter properties (error if write attempted)
62740 * - non-default (!= WEC) attributes for array entries (error if attempted)
62741 * - array abandoning: if array part exists, it is always extended
62742 * - array 'length' updating
62743 *
62744 * Stack: [... in_val] -> []
62745 *
62746 * Used for e.g. built-in initialization and environment record
62747 * operations.
62748 */
62749
62751 duk_hobject *obj,
62752 duk_hstring *key,
62753 duk_small_uint_t flags) {
62754 duk_propdesc desc;
62755 duk_uint32_t arr_idx;
62756 duk_int_t e_idx;
62757 duk_tval *tv1 = NULL;
62758 duk_tval *tv2 = NULL;
62759 duk_small_uint_t propflags = flags & DUK_PROPDESC_FLAGS_MASK; /* mask out flags not actually stored */
62760
62761 DUK_DDD(DUK_DDDPRINT("define new property (internal): thr=%p, obj=%!O, key=%!O, flags=0x%02lx, val=%!T",
62762 (void *) thr,
62763 (duk_heaphdr *) obj,
62764 (duk_heaphdr *) key,
62765 (unsigned long) flags,
62766 (duk_tval *) duk_get_tval(thr, -1)));
62767
62768 DUK_ASSERT(thr != NULL);
62769 DUK_ASSERT(thr->heap != NULL);
62770 DUK_ASSERT(obj != NULL);
62771 DUK_ASSERT(key != NULL);
62774 DUK_ASSERT(duk_is_valid_index(thr, -1)); /* contains value */
62775
62776 arr_idx = DUK_HSTRING_GET_ARRIDX_SLOW(key);
62777
62778 if (duk__get_own_propdesc_raw(thr, obj, key, arr_idx, &desc, 0 /*flags*/)) { /* don't push value */
62779 if (desc.e_idx >= 0) {
62780 if (flags & DUK_PROPDESC_FLAG_NO_OVERWRITE) {
62781 DUK_DDD(DUK_DDDPRINT("property already exists in the entry part -> skip as requested"));
62782 goto pop_exit;
62783 }
62784 DUK_DDD(DUK_DDDPRINT("property already exists in the entry part -> update value and attributes"));
62785 if (DUK_UNLIKELY(DUK_HOBJECT_E_SLOT_IS_ACCESSOR(thr->heap, obj, desc.e_idx))) {
62786 DUK_D(DUK_DPRINT("existing property is an accessor, not supported"));
62787 goto error_internal;
62788 }
62789
62790 DUK_HOBJECT_E_SET_FLAGS(thr->heap, obj, desc.e_idx, propflags);
62791 tv1 = DUK_HOBJECT_E_GET_VALUE_TVAL_PTR(thr->heap, obj, desc.e_idx);
62792 } else if (desc.a_idx >= 0) {
62793 if (flags & DUK_PROPDESC_FLAG_NO_OVERWRITE) {
62794 DUK_DDD(DUK_DDDPRINT("property already exists in the array part -> skip as requested"));
62795 goto pop_exit;
62796 }
62797 DUK_DDD(DUK_DDDPRINT("property already exists in the array part -> update value (assert attributes)"));
62798 if (propflags != DUK_PROPDESC_FLAGS_WEC) {
62799 DUK_D(DUK_DPRINT("existing property in array part, but propflags not WEC (0x%02lx)",
62800 (unsigned long) propflags));
62801 goto error_internal;
62802 }
62803
62804 tv1 = DUK_HOBJECT_A_GET_VALUE_PTR(thr->heap, obj, desc.a_idx);
62805 } else {
62806 if (flags & DUK_PROPDESC_FLAG_NO_OVERWRITE) {
62807 DUK_DDD(DUK_DDDPRINT("property already exists but is virtual -> skip as requested"));
62808 goto pop_exit;
62809 }
62811 duk_uint32_t new_len;
62812#if defined(DUK_USE_DEBUG)
62813 duk_uint32_t prev_len;
62814 prev_len = ((duk_harray *) obj)->length;
62815#endif
62817 ((duk_harray *) obj)->length = new_len;
62818 DUK_DD(DUK_DDPRINT("internal define property for array .length: %ld -> %ld",
62819 (long) prev_len,
62820 (long) ((duk_harray *) obj)->length));
62821 goto pop_exit;
62822 }
62823 DUK_DD(DUK_DDPRINT("property already exists but is virtual -> failure"));
62824 goto error_virtual;
62825 }
62826
62827 goto write_value;
62828 }
62829
62830 if (DUK_HOBJECT_HAS_ARRAY_PART(obj)) {
62831 if (arr_idx != DUK__NO_ARRAY_INDEX) {
62832 DUK_DDD(DUK_DDDPRINT("property does not exist, object has array part -> possibly extend array part and "
62833 "write value (assert attributes)"));
62834 DUK_ASSERT(propflags == DUK_PROPDESC_FLAGS_WEC);
62835
62836 tv1 = duk__obtain_arridx_slot(thr, arr_idx, obj);
62837 if (tv1 == NULL) {
62839 goto write_to_entry_part;
62840 }
62841
62842 tv1 = DUK_HOBJECT_A_GET_VALUE_PTR(thr->heap, obj, arr_idx);
62843 goto write_value;
62844 }
62845 }
62846
62847write_to_entry_part:
62849 "property does not exist, object belongs in entry part -> allocate new entry and write value and attributes"));
62850 e_idx = duk__hobject_alloc_entry_checked(thr, obj, key); /* increases key refcount */
62851 DUK_ASSERT(e_idx >= 0);
62852 DUK_HOBJECT_E_SET_FLAGS(thr->heap, obj, e_idx, propflags);
62853 tv1 = DUK_HOBJECT_E_GET_VALUE_TVAL_PTR(thr->heap, obj, e_idx);
62854 /* new entry: previous value is garbage; set to undefined to share write_value */
62856 goto write_value;
62857
62858write_value:
62859 /* tv1 points to value storage */
62860
62861 tv2 = duk_require_tval(thr, -1); /* late lookup, avoid side effects */
62862 DUK_DDD(DUK_DDDPRINT("writing/updating value: %!T -> %!T", (duk_tval *) tv1, (duk_tval *) tv2));
62863
62864 DUK_TVAL_SET_TVAL_UPDREF(thr, tv1, tv2); /* side effects */
62865 goto pop_exit;
62866
62867pop_exit:
62868 duk_pop_unsafe(thr); /* remove in_val */
62869 return;
62870
62871error_virtual: /* share error message */
62872error_internal:
62873 DUK_ERROR_INTERNAL(thr);
62874 DUK_WO_NORETURN(return;);
62875}
62876
62877/*
62878 * Fast path for defining array indexed values without interning the key.
62879 * This is used by e.g. code for Array prototype and traceback creation so
62880 * must avoid interning.
62881 */
62882
62884 duk_hobject *obj,
62885 duk_uarridx_t arr_idx,
62886 duk_small_uint_t flags) {
62887 duk_hstring *key;
62888 duk_tval *tv1, *tv2;
62889
62890 DUK_DDD(DUK_DDDPRINT("define new property (internal) arr_idx fast path: thr=%p, obj=%!O, "
62891 "arr_idx=%ld, flags=0x%02lx, val=%!T",
62892 (void *) thr,
62893 obj,
62894 (long) arr_idx,
62895 (unsigned long) flags,
62896 (duk_tval *) duk_get_tval(thr, -1)));
62897
62898 DUK_ASSERT(thr != NULL);
62899 DUK_ASSERT(thr->heap != NULL);
62900 DUK_ASSERT(obj != NULL);
62902
62903 if (DUK_HOBJECT_HAS_ARRAY_PART(obj) && arr_idx != DUK__NO_ARRAY_INDEX && flags == DUK_PROPDESC_FLAGS_WEC) {
62904 DUK_ASSERT((flags & DUK_PROPDESC_FLAG_NO_OVERWRITE) == 0); /* covered by comparison */
62905
62906 DUK_DDD(DUK_DDDPRINT("define property to array part (property may or may not exist yet)"));
62907
62908 tv1 = duk__obtain_arridx_slot(thr, arr_idx, obj);
62909 if (tv1 == NULL) {
62911 goto write_slow;
62912 }
62913 tv2 = duk_require_tval(thr, -1);
62914
62915 DUK_TVAL_SET_TVAL_UPDREF(thr, tv1, tv2); /* side effects */
62917 duk_pop_unsafe(thr); /* [ ...val ] -> [ ... ] */
62918 return;
62919 }
62920
62921write_slow:
62922 DUK_DDD(DUK_DDDPRINT("define property fast path didn't work, use slow path"));
62923
62924 key = duk_push_uint_to_hstring(thr, (duk_uint_t) arr_idx);
62925 DUK_ASSERT(key != NULL);
62926 duk_insert(thr, -2); /* [ ... val key ] -> [ ... key val ] */
62927
62928 duk_hobject_define_property_internal(thr, obj, key, flags);
62929
62930 duk_pop_unsafe(thr); /* [ ... key ] -> [ ... ] */
62931}
62932
62933/*
62934 * Internal helpers for managing object 'length'
62935 */
62936
62938 duk_double_t val;
62939
62941 DUK_ASSERT(obj != NULL);
62942
62943 /* Fast path for Arrays. */
62945 return ((duk_harray *) obj)->length;
62946 }
62947
62948 /* Slow path, .length can be e.g. accessor, obj can be a Proxy, etc. */
62949 duk_push_hobject(thr, obj);
62951 (void) duk_hobject_getprop(thr, DUK_GET_TVAL_NEGIDX(thr, -2), DUK_GET_TVAL_NEGIDX(thr, -1));
62953 duk_pop_3_unsafe(thr);
62954
62955 /* This isn't part of ECMAScript semantics; return a value within
62956 * duk_size_t range, or 0 otherwise.
62957 */
62958 if (val >= 0.0 && val <= (duk_double_t) DUK_SIZE_MAX) {
62959 return (duk_size_t) val;
62960 }
62961 return 0;
62962}
62963
62964/*
62965 * Fast finalizer check for an object. Walks the prototype chain, checking
62966 * for finalizer presence using DUK_HOBJECT_FLAG_HAVE_FINALIZER which is kept
62967 * in sync with the actual property when setting/removing the finalizer.
62968 */
62969
62970#if defined(DUK_USE_HEAPPTR16)
62972#else
62974#endif
62975 duk_uint_t sanity;
62976
62977 DUK_ASSERT(obj != NULL);
62978
62980 do {
62982 return 1;
62983 }
62984 if (DUK_UNLIKELY(sanity-- == 0)) {
62985 DUK_D(DUK_DPRINT("prototype loop when checking for finalizer existence; returning false"));
62986 return 0;
62987 }
62988#if defined(DUK_USE_HEAPPTR16)
62989 DUK_ASSERT(heap != NULL);
62990 obj = DUK_HOBJECT_GET_PROTOTYPE(heap, obj);
62991#else
62992 obj = DUK_HOBJECT_GET_PROTOTYPE(NULL, obj); /* 'heap' arg ignored */
62993#endif
62994 } while (obj != NULL);
62995
62996 return 0;
62997}
62998
62999/*
63000 * Object.getOwnPropertyDescriptor() (E5 Sections 15.2.3.3, 8.10.4)
63001 *
63002 * [ ... key ] -> [ ... desc/undefined ]
63003 */
63004
63006 duk_hobject *obj;
63007 duk_hstring *key;
63008 duk_propdesc pd;
63009
63010 DUK_ASSERT(thr != NULL);
63011 DUK_ASSERT(thr->heap != NULL);
63012
63014 key = duk_to_property_key_hstring(thr, -1);
63015 DUK_ASSERT(key != NULL);
63016
63018
63020 duk_push_undefined(thr);
63021 duk_remove_m2(thr);
63022 return;
63023 }
63024
63025 duk_push_object(thr);
63026
63027 /* [ ... key value desc ] */
63028
63029 if (DUK_PROPDESC_IS_ACCESSOR(&pd)) {
63030 /* If a setter/getter is missing (undefined), the descriptor must
63031 * still have the property present with the value 'undefined'.
63032 */
63033 if (pd.get) {
63034 duk_push_hobject(thr, pd.get);
63035 } else {
63036 duk_push_undefined(thr);
63037 }
63039 if (pd.set) {
63040 duk_push_hobject(thr, pd.set);
63041 } else {
63042 duk_push_undefined(thr);
63043 }
63045 } else {
63046 duk_dup_m2(thr);
63050 }
63055
63056 /* [ ... key value desc ] */
63057
63058 duk_replace(thr, -3);
63059 duk_pop_unsafe(thr); /* -> [ ... desc ] */
63060}
63061
63062/*
63063 * NormalizePropertyDescriptor() related helper.
63064 *
63065 * Internal helper which validates and normalizes a property descriptor
63066 * represented as an ECMAScript object (e.g. argument to defineProperty()).
63067 * The output of this conversion is a set of defprop_flags and possibly
63068 * some values pushed on the value stack to (1) ensure borrowed pointers
63069 * remain valid, and (2) avoid unnecessary pops for footprint reasons.
63070 * Caller must manage stack top carefully because the number of values
63071 * pushed depends on the input property descriptor.
63072 *
63073 * The original descriptor object must not be altered in the process.
63074 */
63075
63076/* XXX: very basic optimization -> duk_get_prop_stridx_top */
63077
63080 duk_idx_t idx_in,
63081 duk_uint_t *out_defprop_flags,
63082 duk_idx_t *out_idx_value,
63083 duk_hobject **out_getter,
63084 duk_hobject **out_setter) {
63085 duk_idx_t idx_value = -1;
63086 duk_hobject *getter = NULL;
63087 duk_hobject *setter = NULL;
63088 duk_bool_t is_data_desc = 0;
63089 duk_bool_t is_acc_desc = 0;
63090 duk_uint_t defprop_flags = 0;
63091
63092 DUK_ASSERT(out_defprop_flags != NULL);
63093 DUK_ASSERT(out_idx_value != NULL);
63094 DUK_ASSERT(out_getter != NULL);
63095 DUK_ASSERT(out_setter != NULL);
63096 DUK_ASSERT(idx_in <= 0x7fffL); /* short variants would be OK, but not used to avoid shifts */
63097
63098 /* Must be an object, otherwise TypeError (E5.1 Section 8.10.5, step 1). */
63099 idx_in = duk_require_normalize_index(thr, idx_in);
63100 (void) duk_require_hobject(thr, idx_in);
63101
63102 /* The coercion order must match the ToPropertyDescriptor() algorithm
63103 * so that side effects in coercion happen in the correct order.
63104 * (This order also happens to be compatible with duk_def_prop(),
63105 * although it doesn't matter in practice.)
63106 */
63107
63108 if (duk_get_prop_stridx(thr, idx_in, DUK_STRIDX_VALUE)) {
63109 is_data_desc = 1;
63110 defprop_flags |= DUK_DEFPROP_HAVE_VALUE;
63111 idx_value = duk_get_top_index(thr);
63112 }
63113
63114 if (duk_get_prop_stridx(thr, idx_in, DUK_STRIDX_WRITABLE)) {
63115 is_data_desc = 1;
63116 if (duk_to_boolean_top_pop(thr)) {
63118 } else {
63119 defprop_flags |= DUK_DEFPROP_HAVE_WRITABLE;
63120 }
63121 }
63122
63123 if (duk_get_prop_stridx(thr, idx_in, DUK_STRIDX_GET)) {
63124 duk_tval *tv = duk_require_tval(thr, -1);
63125 duk_hobject *h_get;
63126
63127 if (DUK_TVAL_IS_UNDEFINED(tv)) {
63128 /* undefined is accepted */
63129 DUK_ASSERT(getter == NULL);
63130 } else {
63131 /* NOTE: lightfuncs are coerced to full functions because
63132 * lightfuncs don't fit into a property value slot. This
63133 * has some side effects, see test-dev-lightfunc-accessor.js.
63134 */
63135 h_get = duk_get_hobject_promote_lfunc(thr, -1);
63136 if (h_get == NULL || !DUK_HOBJECT_IS_CALLABLE(h_get)) {
63137 goto type_error;
63138 }
63139 getter = h_get;
63140 }
63141 is_acc_desc = 1;
63142 defprop_flags |= DUK_DEFPROP_HAVE_GETTER;
63143 }
63144
63145 if (duk_get_prop_stridx(thr, idx_in, DUK_STRIDX_SET)) {
63146 duk_tval *tv = duk_require_tval(thr, -1);
63147 duk_hobject *h_set;
63148
63149 if (DUK_TVAL_IS_UNDEFINED(tv)) {
63150 /* undefined is accepted */
63151 DUK_ASSERT(setter == NULL);
63152 } else {
63153 /* NOTE: lightfuncs are coerced to full functions because
63154 * lightfuncs don't fit into a property value slot. This
63155 * has some side effects, see test-dev-lightfunc-accessor.js.
63156 */
63157 h_set = duk_get_hobject_promote_lfunc(thr, -1);
63158 if (h_set == NULL || !DUK_HOBJECT_IS_CALLABLE(h_set)) {
63159 goto type_error;
63160 }
63161 setter = h_set;
63162 }
63163 is_acc_desc = 1;
63164 defprop_flags |= DUK_DEFPROP_HAVE_SETTER;
63165 }
63166
63167 if (duk_get_prop_stridx(thr, idx_in, DUK_STRIDX_ENUMERABLE)) {
63168 if (duk_to_boolean_top_pop(thr)) {
63170 } else {
63171 defprop_flags |= DUK_DEFPROP_HAVE_ENUMERABLE;
63172 }
63173 }
63174
63175 if (duk_get_prop_stridx(thr, idx_in, DUK_STRIDX_CONFIGURABLE)) {
63176 if (duk_to_boolean_top_pop(thr)) {
63178 } else {
63179 defprop_flags |= DUK_DEFPROP_HAVE_CONFIGURABLE;
63180 }
63181 }
63182
63183 if (is_data_desc && is_acc_desc) {
63184 goto type_error;
63185 }
63186
63187 *out_defprop_flags = defprop_flags;
63188 *out_idx_value = idx_value;
63189 *out_getter = getter;
63190 *out_setter = setter;
63191
63192 /* [ ... [multiple values] ] */
63193 return;
63194
63195type_error:
63197 DUK_WO_NORETURN(return;);
63198}
63199
63201 * Object.defineProperty() related helper (E5 Section 15.2.3.6).
63202 * Also handles ES2015 Reflect.defineProperty().
63203 *
63204 * Inlines all [[DefineOwnProperty]] exotic behaviors.
63205 *
63206 * Note: ECMAScript compliant [[DefineOwnProperty]](P, Desc, Throw) is not
63207 * implemented directly, but Object.defineProperty() serves its purpose.
63208 * We don't need the [[DefineOwnProperty]] internally and we don't have a
63209 * property descriptor with 'missing values' so it's easier to avoid it
63210 * entirely.
63211 *
63212 * Note: this is only called for actual objects, not primitive values.
63213 * This must support virtual properties for full objects (e.g. Strings)
63214 * but not for plain values (e.g. strings). Lightfuncs, even though
63215 * primitive in a sense, are treated like objects and accepted as target
63216 * values.
63217 */
63218
63219/* XXX: this is a major target for size optimization */
63222 duk_uint_t defprop_flags,
63223 duk_hobject *obj,
63224 duk_hstring *key,
63225 duk_idx_t idx_value,
63226 duk_hobject *get,
63227 duk_hobject *set,
63228 duk_bool_t throw_flag) {
63229 duk_uint32_t arr_idx;
63230 duk_tval tv;
63231 duk_bool_t has_enumerable;
63232 duk_bool_t has_configurable;
63233 duk_bool_t has_writable;
63234 duk_bool_t has_value;
63235 duk_bool_t has_get;
63236 duk_bool_t has_set;
63237 duk_bool_t is_enumerable;
63238 duk_bool_t is_configurable;
63239 duk_bool_t is_writable;
63240 duk_bool_t force_flag;
63241 duk_small_uint_t new_flags;
63242 duk_propdesc curr;
63243 duk_uint32_t arridx_new_array_length; /* != 0 => post-update for array 'length' (used when key is an array index) */
63244 duk_uint32_t arrlen_old_len;
63245 duk_uint32_t arrlen_new_len;
63246 duk_bool_t pending_write_protect;
63247
63248 DUK_ASSERT(thr != NULL);
63249 DUK_ASSERT(thr->heap != NULL);
63250 DUK_ASSERT(obj != NULL);
63251 DUK_ASSERT(key != NULL);
63252 /* idx_value may be < 0 (no value), set and get may be NULL */
63253
63255
63256 /* All the flags fit in 16 bits, so will fit into duk_bool_t. */
63257
63258 has_writable = (defprop_flags & DUK_DEFPROP_HAVE_WRITABLE);
63259 has_enumerable = (defprop_flags & DUK_DEFPROP_HAVE_ENUMERABLE);
63260 has_configurable = (defprop_flags & DUK_DEFPROP_HAVE_CONFIGURABLE);
63261 has_value = (defprop_flags & DUK_DEFPROP_HAVE_VALUE);
63262 has_get = (defprop_flags & DUK_DEFPROP_HAVE_GETTER);
63263 has_set = (defprop_flags & DUK_DEFPROP_HAVE_SETTER);
63264 is_writable = (defprop_flags & DUK_DEFPROP_WRITABLE);
63265 is_enumerable = (defprop_flags & DUK_DEFPROP_ENUMERABLE);
63266 is_configurable = (defprop_flags & DUK_DEFPROP_CONFIGURABLE);
63267 force_flag = (defprop_flags & DUK_DEFPROP_FORCE);
63268
63269 arr_idx = DUK_HSTRING_GET_ARRIDX_SLOW(key);
63270
63271 arridx_new_array_length = 0;
63272 pending_write_protect = 0;
63273 arrlen_old_len = 0;
63274 arrlen_new_len = 0;
63275
63276 DUK_DDD(DUK_DDDPRINT("has_enumerable=%ld is_enumerable=%ld "
63277 "has_configurable=%ld is_configurable=%ld "
63278 "has_writable=%ld is_writable=%ld "
63279 "has_value=%ld value=%!T "
63280 "has_get=%ld get=%p=%!O "
63281 "has_set=%ld set=%p=%!O "
63282 "arr_idx=%ld throw_flag=!%ld",
63283 (long) has_enumerable,
63284 (long) is_enumerable,
63285 (long) has_configurable,
63286 (long) is_configurable,
63287 (long) has_writable,
63288 (long) is_writable,
63289 (long) has_value,
63290 (duk_tval *) (idx_value >= 0 ? duk_get_tval(thr, idx_value) : NULL),
63291 (long) has_get,
63292 (void *) get,
63293 (duk_heaphdr *) get,
63294 (long) has_set,
63295 (void *) set,
63296 (duk_heaphdr *) set,
63297 (long) arr_idx,
63298 (long) throw_flag));
63299
63300 /*
63301 * Array exotic behaviors can be implemented at this point. The local variables
63302 * are essentially a 'value copy' of the input descriptor (Desc), which is modified
63303 * by the Array [[DefineOwnProperty]] (E5 Section 15.4.5.1).
63304 */
63305
63306 if (!DUK_HOBJECT_HAS_EXOTIC_ARRAY(obj)) {
63307 goto skip_array_exotic;
63308 }
63309
63310 if (key == DUK_HTHREAD_STRING_LENGTH(thr)) {
63311 duk_harray *a;
63312
63313 /* E5 Section 15.4.5.1, step 3, steps a - i are implemented here, j - n at the end */
63314 if (!has_value) {
63315 DUK_DDD(DUK_DDDPRINT("exotic array behavior for 'length', but no value in descriptor -> normal behavior"));
63316 goto skip_array_exotic;
63317 }
63318
63319 DUK_DDD(DUK_DDDPRINT("exotic array behavior for 'length', value present in descriptor -> exotic behavior"));
63320
63321 /*
63322 * Get old and new length
63323 */
63324
63325 a = (duk_harray *) obj;
63327 arrlen_old_len = a->length;
63328
63329 DUK_ASSERT(idx_value >= 0);
63330 arrlen_new_len = duk__to_new_array_length_checked(thr, DUK_GET_TVAL_POSIDX(thr, idx_value));
63331 duk_push_u32(thr, arrlen_new_len);
63332 duk_replace(thr, idx_value); /* step 3.e: replace 'Desc.[[Value]]' */
63333
63334 DUK_DDD(DUK_DDDPRINT("old_len=%ld, new_len=%ld", (long) arrlen_old_len, (long) arrlen_new_len));
63335
63336 if (arrlen_new_len >= arrlen_old_len) {
63337 /* standard behavior, step 3.f.i */
63338 DUK_DDD(DUK_DDDPRINT("new length is same or higher as previous => standard behavior"));
63339 goto skip_array_exotic;
63340 }
63341 DUK_DDD(DUK_DDDPRINT("new length is smaller than previous => exotic post behavior"));
63342
63343 /* XXX: consolidated algorithm step 15.f -> redundant? */
63344 if (DUK_HARRAY_LENGTH_NONWRITABLE(a) && !force_flag) {
63345 /* Array .length is always non-configurable; if it's also
63346 * non-writable, don't allow it to be written.
63347 */
63348 goto fail_not_configurable;
63349 }
63350
63351 /* steps 3.h and 3.i */
63352 if (has_writable && !is_writable) {
63353 DUK_DDD(DUK_DDDPRINT("desc writable is false, force it back to true, and flag pending write protect"));
63354 is_writable = 1;
63355 pending_write_protect = 1;
63356 }
63357
63358 /* remaining actual steps are carried out if standard DefineOwnProperty succeeds */
63359 } else if (arr_idx != DUK__NO_ARRAY_INDEX) {
63360 /* XXX: any chance of unifying this with the 'length' key handling? */
63361
63362 /* E5 Section 15.4.5.1, step 4 */
63363 duk_uint32_t old_len;
63364 duk_harray *a;
63365
63366 a = (duk_harray *) obj;
63368
63369 old_len = a->length;
63370
63371 if (arr_idx >= old_len) {
63372 DUK_DDD(DUK_DDDPRINT("defineProperty requires array length update "
63373 "(arr_idx=%ld, old_len=%ld)",
63374 (long) arr_idx,
63375 (long) old_len));
63376
63377 if (DUK_HARRAY_LENGTH_NONWRITABLE(a) && !force_flag) {
63378 /* Array .length is always non-configurable, so
63379 * if it's also non-writable, don't allow a value
63380 * write. With force flag allow writing.
63381 */
63382 goto fail_not_configurable;
63383 }
63384
63385 /* actual update happens once write has been completed without
63386 * error below.
63387 */
63388 DUK_ASSERT(arr_idx != 0xffffffffUL);
63389 arridx_new_array_length = arr_idx + 1;
63390 } else {
63391 DUK_DDD(DUK_DDDPRINT("defineProperty does not require length update "
63392 "(arr_idx=%ld, old_len=%ld) -> standard behavior",
63393 (long) arr_idx,
63394 (long) old_len));
63395 }
63396 }
63397skip_array_exotic:
63398
63399 /* XXX: There is currently no support for writing buffer object
63400 * indexed elements here. Attempt to do so will succeed and
63401 * write a concrete property into the buffer object. This should
63402 * be fixed at some point but because buffers are a custom feature
63403 * anyway, this is relatively unimportant.
63404 */
63405
63406 /*
63407 * Actual Object.defineProperty() default algorithm.
63408 */
63409
63410 /*
63411 * First check whether property exists; if not, simple case. This covers
63412 * steps 1-4.
63413 */
63414
63415 if (!duk__get_own_propdesc_raw(thr, obj, key, arr_idx, &curr, DUK_GETDESC_FLAG_PUSH_VALUE)) {
63416 DUK_DDD(DUK_DDDPRINT("property does not exist"));
63417
63418 if (!DUK_HOBJECT_HAS_EXTENSIBLE(obj) && !force_flag) {
63419 goto fail_not_extensible;
63420 }
63421
63422#if defined(DUK_USE_ROM_OBJECTS)
63423 /* ROM objects are never extensible but force flag may
63424 * allow us to come here anyway.
63425 */
63428 DUK_D(DUK_DPRINT("attempt to define property on a read-only target object"));
63429 goto fail_not_configurable;
63430 }
63431#endif
63432
63433 /* XXX: share final setting code for value and flags? difficult because
63434 * refcount code is different. Share entry allocation? But can't allocate
63435 * until array index checked.
63436 */
63437
63438 /* steps 4.a and 4.b are tricky */
63439 if (has_set || has_get) {
63440 duk_int_t e_idx;
63441
63442 DUK_DDD(DUK_DDDPRINT("create new accessor property"));
63443
63444 DUK_ASSERT(has_set || set == NULL);
63445 DUK_ASSERT(has_get || get == NULL);
63446 DUK_ASSERT(!has_value);
63447 DUK_ASSERT(!has_writable);
63448
63449 new_flags = DUK_PROPDESC_FLAG_ACCESSOR; /* defaults, E5 Section 8.6.1, Table 7 */
63450 if (has_enumerable && is_enumerable) {
63451 new_flags |= DUK_PROPDESC_FLAG_ENUMERABLE;
63452 }
63453 if (has_configurable && is_configurable) {
63454 new_flags |= DUK_PROPDESC_FLAG_CONFIGURABLE;
63455 }
63456
63457 if (arr_idx != DUK__NO_ARRAY_INDEX && DUK_HOBJECT_HAS_ARRAY_PART(obj)) {
63458 DUK_DDD(DUK_DDDPRINT("accessor cannot go to array part, abandon array"));
63459 duk__abandon_array_part(thr, obj);
63460 }
63461
63462 /* write to entry part */
63463 e_idx = duk__hobject_alloc_entry_checked(thr, obj, key);
63464 DUK_ASSERT(e_idx >= 0);
63465
63466 DUK_HOBJECT_E_SET_VALUE_GETTER(thr->heap, obj, e_idx, get);
63467 DUK_HOBJECT_E_SET_VALUE_SETTER(thr->heap, obj, e_idx, set);
63470
63471 DUK_HOBJECT_E_SET_FLAGS(thr->heap, obj, e_idx, new_flags);
63472 goto success_exotics;
63473 } else {
63474 duk_int_t e_idx;
63475 duk_tval *tv2;
63476
63477 DUK_DDD(DUK_DDDPRINT("create new data property"));
63478
63479 DUK_ASSERT(!has_set);
63480 DUK_ASSERT(!has_get);
63481
63482 new_flags = 0; /* defaults, E5 Section 8.6.1, Table 7 */
63483 if (has_writable && is_writable) {
63484 new_flags |= DUK_PROPDESC_FLAG_WRITABLE;
63485 }
63486 if (has_enumerable && is_enumerable) {
63487 new_flags |= DUK_PROPDESC_FLAG_ENUMERABLE;
63488 }
63489 if (has_configurable && is_configurable) {
63490 new_flags |= DUK_PROPDESC_FLAG_CONFIGURABLE;
63491 }
63492 if (has_value) {
63493 duk_tval *tv_tmp = duk_require_tval(thr, idx_value);
63494 DUK_TVAL_SET_TVAL(&tv, tv_tmp);
63495 } else {
63496 DUK_TVAL_SET_UNDEFINED(&tv); /* default value */
63497 }
63498
63499 if (arr_idx != DUK__NO_ARRAY_INDEX && DUK_HOBJECT_HAS_ARRAY_PART(obj)) {
63500 if (new_flags == DUK_PROPDESC_FLAGS_WEC) {
63502 "new data property attributes match array defaults, attempt to write to array part"));
63503 tv2 = duk__obtain_arridx_slot(thr, arr_idx, obj);
63504 if (tv2 == NULL) {
63505 DUK_DDD(DUK_DDDPRINT("failed writing to array part, abandoned array"));
63506 } else {
63507 DUK_DDD(DUK_DDDPRINT("success in writing to array part"));
63510 DUK_TVAL_SET_TVAL(tv2, &tv);
63511 DUK_TVAL_INCREF(thr, tv2);
63512 goto success_exotics;
63513 }
63514 } else {
63515 DUK_DDD(DUK_DDDPRINT("new data property cannot go to array part, abandon array"));
63516 duk__abandon_array_part(thr, obj);
63517 }
63518 /* fall through */
63519 }
63520
63521 /* write to entry part */
63522 e_idx = duk__hobject_alloc_entry_checked(thr, obj, key);
63523 DUK_ASSERT(e_idx >= 0);
63524 tv2 = DUK_HOBJECT_E_GET_VALUE_TVAL_PTR(thr->heap, obj, e_idx);
63525 DUK_TVAL_SET_TVAL(tv2, &tv);
63526 DUK_TVAL_INCREF(thr, tv2);
63527
63528 DUK_HOBJECT_E_SET_FLAGS(thr->heap, obj, e_idx, new_flags);
63529 goto success_exotics;
63530 }
63532 }
63533
63534 /* we currently assume virtual properties are not configurable (as none of them are) */
63535 DUK_ASSERT((curr.e_idx >= 0 || curr.a_idx >= 0) || !(curr.flags & DUK_PROPDESC_FLAG_CONFIGURABLE));
63536
63537 /* [obj key desc value get set curr_value] */
63538
63539 /*
63540 * Property already exists. Steps 5-6 detect whether any changes need
63541 * to be made.
63542 */
63543
63544 if (has_enumerable) {
63545 if (is_enumerable) {
63546 if (!(curr.flags & DUK_PROPDESC_FLAG_ENUMERABLE)) {
63547 goto need_check;
63548 }
63549 } else {
63551 goto need_check;
63552 }
63553 }
63554 }
63555 if (has_configurable) {
63556 if (is_configurable) {
63557 if (!(curr.flags & DUK_PROPDESC_FLAG_CONFIGURABLE)) {
63558 goto need_check;
63559 }
63560 } else {
63562 goto need_check;
63563 }
63564 }
63565 }
63566 if (has_value) {
63567 duk_tval *tmp1;
63568 duk_tval *tmp2;
63569
63570 /* attempt to change from accessor to data property */
63571 if (curr.flags & DUK_PROPDESC_FLAG_ACCESSOR) {
63572 goto need_check;
63573 }
63574
63575 tmp1 = duk_require_tval(thr, -1); /* curr value */
63576 tmp2 = duk_require_tval(thr, idx_value); /* new value */
63577 if (!duk_js_samevalue(tmp1, tmp2)) {
63578 goto need_check;
63579 }
63580 }
63581 if (has_writable) {
63582 /* attempt to change from accessor to data property */
63583 if (curr.flags & DUK_PROPDESC_FLAG_ACCESSOR) {
63584 goto need_check;
63585 }
63586
63587 if (is_writable) {
63588 if (!(curr.flags & DUK_PROPDESC_FLAG_WRITABLE)) {
63589 goto need_check;
63590 }
63591 } else {
63592 if (curr.flags & DUK_PROPDESC_FLAG_WRITABLE) {
63593 goto need_check;
63594 }
63595 }
63596 }
63597 if (has_set) {
63598 if (curr.flags & DUK_PROPDESC_FLAG_ACCESSOR) {
63599 if (set != curr.set) {
63600 goto need_check;
63601 }
63602 } else {
63603 goto need_check;
63604 }
63605 }
63606 if (has_get) {
63607 if (curr.flags & DUK_PROPDESC_FLAG_ACCESSOR) {
63608 if (get != curr.get) {
63609 goto need_check;
63610 }
63611 } else {
63612 goto need_check;
63613 }
63614 }
63615
63616 /* property exists, either 'desc' is empty, or all values
63617 * match (SameValue)
63618 */
63619 goto success_no_exotics;
63620
63621need_check:
63622
63623 /*
63624 * Some change(s) need to be made. Steps 7-11.
63625 */
63626
63627 /* shared checks for all descriptor types */
63628 if (!(curr.flags & DUK_PROPDESC_FLAG_CONFIGURABLE) && !force_flag) {
63629 if (has_configurable && is_configurable) {
63630 goto fail_not_configurable;
63631 }
63632 if (has_enumerable) {
63634 if (!is_enumerable) {
63635 goto fail_not_configurable;
63636 }
63637 } else {
63638 if (is_enumerable) {
63639 goto fail_not_configurable;
63640 }
63641 }
63642 }
63643 }
63644
63645 /* Virtual properties don't have backing so they can't mostly be
63646 * edited. Some virtual properties are, however, writable: for
63647 * example, virtual index properties of buffer objects and Array
63648 * instance .length. These are not configurable so the checks
63649 * above mostly cover attempts to change them, except when the
63650 * duk_def_prop() call is used with DUK_DEFPROP_FORCE; even in
63651 * that case we can't forcibly change the property attributes
63652 * because they don't have concrete backing.
63653 */
63654
63655 /* XXX: for ROM objects too it'd be best if value modify was
63656 * allowed if the value matches SameValue.
63657 */
63658 /* Reject attempt to change a read-only object. */
63659#if defined(DUK_USE_ROM_OBJECTS)
63661 DUK_DD(DUK_DDPRINT("attempt to define property on read-only target object"));
63662 goto fail_not_configurable;
63663 }
63664#endif
63665
63666 /* descriptor type specific checks */
63667 if (has_set || has_get) {
63668 /* IsAccessorDescriptor(desc) == true */
63669 DUK_ASSERT(!has_writable);
63670 DUK_ASSERT(!has_value);
63671
63672 if (curr.flags & DUK_PROPDESC_FLAG_ACCESSOR) {
63673 /* curr and desc are accessors */
63674 if (!(curr.flags & DUK_PROPDESC_FLAG_CONFIGURABLE) && !force_flag) {
63675 if (has_set && set != curr.set) {
63676 goto fail_not_configurable;
63677 }
63678 if (has_get && get != curr.get) {
63679 goto fail_not_configurable;
63680 }
63681 }
63682 } else {
63683 duk_bool_t rc;
63684 duk_tval *tv1;
63685
63686 /* curr is data, desc is accessor */
63687 if (!(curr.flags & DUK_PROPDESC_FLAG_CONFIGURABLE) && !force_flag) {
63688 goto fail_not_configurable;
63689 }
63690
63691 DUK_DDD(DUK_DDDPRINT("convert property to accessor property"));
63692 if (curr.a_idx >= 0) {
63693 DUK_DDD(
63694 DUK_DDDPRINT("property to convert is stored in an array entry, abandon array and re-lookup"));
63695 duk__abandon_array_part(thr, obj);
63696 duk_pop_unsafe(thr); /* remove old value */
63697 rc = duk__get_own_propdesc_raw(thr, obj, key, arr_idx, &curr, DUK_GETDESC_FLAG_PUSH_VALUE);
63698 DUK_UNREF(rc);
63699 DUK_ASSERT(rc != 0);
63700 DUK_ASSERT(curr.e_idx >= 0 && curr.a_idx < 0);
63701 }
63702 if (curr.e_idx < 0) {
63703 DUK_ASSERT(curr.a_idx < 0 && curr.e_idx < 0);
63704 goto fail_virtual; /* safeguard for virtual property */
63705 }
63706
63707 DUK_ASSERT(curr.e_idx >= 0);
63709
63710 tv1 = DUK_HOBJECT_E_GET_VALUE_TVAL_PTR(thr->heap, obj, curr.e_idx);
63711 DUK_TVAL_SET_UNDEFINED_UPDREF_NORZ(thr, tv1); /* XXX: just decref */
63712
63713 DUK_HOBJECT_E_SET_VALUE_GETTER(thr->heap, obj, curr.e_idx, NULL);
63714 DUK_HOBJECT_E_SET_VALUE_SETTER(thr->heap, obj, curr.e_idx, NULL);
63717
63718 DUK_DDD(DUK_DDDPRINT("flags after data->accessor conversion: 0x%02lx",
63719 (unsigned long) DUK_HOBJECT_E_GET_FLAGS(thr->heap, obj, curr.e_idx)));
63720 /* Update curr.flags; faster than a re-lookup. */
63721 curr.flags &= ~DUK_PROPDESC_FLAG_WRITABLE;
63723 }
63724 } else if (has_value || has_writable) {
63725 /* IsDataDescriptor(desc) == true */
63726 DUK_ASSERT(!has_set);
63727 DUK_ASSERT(!has_get);
63728
63729 if (curr.flags & DUK_PROPDESC_FLAG_ACCESSOR) {
63730 duk_hobject *tmp;
63731
63732 /* curr is accessor, desc is data */
63733 if (!(curr.flags & DUK_PROPDESC_FLAG_CONFIGURABLE) && !force_flag) {
63734 goto fail_not_configurable;
63735 }
63736
63737 /* curr is accessor -> cannot be in array part. */
63738 DUK_ASSERT(curr.a_idx < 0);
63739 if (curr.e_idx < 0) {
63740 goto fail_virtual; /* safeguard; no virtual accessors now */
63741 }
63742
63743 DUK_DDD(DUK_DDDPRINT("convert property to data property"));
63744
63746 tmp = DUK_HOBJECT_E_GET_VALUE_GETTER(thr->heap, obj, curr.e_idx);
63747 DUK_UNREF(tmp);
63748 DUK_HOBJECT_E_SET_VALUE_GETTER(thr->heap, obj, curr.e_idx, NULL);
63750 tmp = DUK_HOBJECT_E_GET_VALUE_SETTER(thr->heap, obj, curr.e_idx);
63751 DUK_UNREF(tmp);
63752 DUK_HOBJECT_E_SET_VALUE_SETTER(thr->heap, obj, curr.e_idx, NULL);
63754
63758
63759 DUK_DDD(DUK_DDDPRINT("flags after accessor->data conversion: 0x%02lx",
63760 (unsigned long) DUK_HOBJECT_E_GET_FLAGS(thr->heap, obj, curr.e_idx)));
63761
63762 /* Update curr.flags; faster than a re-lookup. */
63764 } else {
63765 /* curr and desc are data */
63766 if (!(curr.flags & DUK_PROPDESC_FLAG_CONFIGURABLE) && !force_flag) {
63767 if (!(curr.flags & DUK_PROPDESC_FLAG_WRITABLE) && has_writable && is_writable) {
63768 goto fail_not_configurable;
63769 }
63770 /* Note: changing from writable to non-writable is OK */
63771 if (!(curr.flags & DUK_PROPDESC_FLAG_WRITABLE) && has_value) {
63772 duk_tval *tmp1 = duk_require_tval(thr, -1); /* curr value */
63773 duk_tval *tmp2 = duk_require_tval(thr, idx_value); /* new value */
63774 if (!duk_js_samevalue(tmp1, tmp2)) {
63775 goto fail_not_configurable;
63776 }
63777 }
63778 }
63779 }
63780 } else {
63781 /* IsGenericDescriptor(desc) == true; this means in practice that 'desc'
63782 * only has [[Enumerable]] or [[Configurable]] flag updates, which are
63783 * allowed at this point.
63784 */
63785
63786 DUK_ASSERT(!has_value && !has_writable && !has_get && !has_set);
63787 }
63788
63789 /*
63790 * Start doing property attributes updates. Steps 12-13.
63791 *
63792 * Start by computing new attribute flags without writing yet.
63793 * Property type conversion is done above if necessary.
63794 */
63795
63796 new_flags = curr.flags;
63797
63798 if (has_enumerable) {
63799 if (is_enumerable) {
63800 new_flags |= DUK_PROPDESC_FLAG_ENUMERABLE;
63801 } else {
63802 new_flags &= ~DUK_PROPDESC_FLAG_ENUMERABLE;
63803 }
63804 }
63805 if (has_configurable) {
63806 if (is_configurable) {
63807 new_flags |= DUK_PROPDESC_FLAG_CONFIGURABLE;
63808 } else {
63809 new_flags &= ~DUK_PROPDESC_FLAG_CONFIGURABLE;
63810 }
63811 }
63812 if (has_writable) {
63813 if (is_writable) {
63814 new_flags |= DUK_PROPDESC_FLAG_WRITABLE;
63815 } else {
63816 new_flags &= ~DUK_PROPDESC_FLAG_WRITABLE;
63817 }
63818 }
63819
63820 /* XXX: write protect after flag? -> any chance of handling it here? */
63821
63822 DUK_DDD(DUK_DDDPRINT("new flags that we want to write: 0x%02lx", (unsigned long) new_flags));
63823
63824 /*
63825 * Check whether we need to abandon an array part (if it exists)
63826 */
63827
63828 if (curr.a_idx >= 0) {
63829 duk_bool_t rc;
63830
63831 DUK_ASSERT(curr.e_idx < 0);
63832
63833 if (new_flags == DUK_PROPDESC_FLAGS_WEC) {
63834 duk_tval *tv1, *tv2;
63835
63836 DUK_DDD(DUK_DDDPRINT("array index, new property attributes match array defaults, update in-place"));
63837
63838 DUK_ASSERT(curr.flags == DUK_PROPDESC_FLAGS_WEC); /* must have been, since in array part */
63839 DUK_ASSERT(!has_set);
63840 DUK_ASSERT(!has_get);
63841 DUK_ASSERT(
63842 idx_value >=
63843 0); /* must be: if attributes match and we get here the value must differ (otherwise no change) */
63844
63845 tv2 = duk_require_tval(thr, idx_value);
63846 tv1 = DUK_HOBJECT_A_GET_VALUE_PTR(thr->heap, obj, curr.a_idx);
63847 DUK_TVAL_SET_TVAL_UPDREF(thr, tv1, tv2); /* side effects; may invalidate a_idx */
63848 goto success_exotics;
63849 }
63850
63851 DUK_DDD(
63852 DUK_DDDPRINT("array index, new property attributes do not match array defaults, abandon array and re-lookup"));
63853 duk__abandon_array_part(thr, obj);
63854 duk_pop_unsafe(thr); /* remove old value */
63855 rc = duk__get_own_propdesc_raw(thr, obj, key, arr_idx, &curr, DUK_GETDESC_FLAG_PUSH_VALUE);
63856 DUK_UNREF(rc);
63857 DUK_ASSERT(rc != 0);
63858 DUK_ASSERT(curr.e_idx >= 0 && curr.a_idx < 0);
63859 }
63860
63861 DUK_DDD(DUK_DDDPRINT("updating existing property in entry part"));
63862
63863 /* Array case is handled comprehensively above: either in entry
63864 * part or a virtual property.
63865 */
63866 DUK_ASSERT(curr.a_idx < 0);
63867
63868 DUK_DDD(DUK_DDDPRINT("update existing property attributes"));
63869 if (curr.e_idx >= 0) {
63870 DUK_HOBJECT_E_SET_FLAGS(thr->heap, obj, curr.e_idx, new_flags);
63871 } else {
63872 /* For Array .length the only allowed transition is for .length
63873 * to become non-writable.
63874 */
63876 duk_harray *a;
63877 a = (duk_harray *) obj;
63878 DUK_DD(DUK_DDPRINT("Object.defineProperty() attribute update for duk_harray .length -> %02lx",
63879 (unsigned long) new_flags));
63881 if ((new_flags & DUK_PROPDESC_FLAGS_EC) != (curr.flags & DUK_PROPDESC_FLAGS_EC)) {
63882 DUK_D(DUK_DPRINT("Object.defineProperty() attempt to change virtual array .length enumerable or "
63883 "configurable attribute, fail"));
63884 goto fail_virtual;
63885 }
63886 if (new_flags & DUK_PROPDESC_FLAG_WRITABLE) {
63888 } else {
63890 }
63891 }
63892 }
63893
63894 if (has_set) {
63895 duk_hobject *tmp;
63896
63897 /* Virtual properties are non-configurable but with a 'force'
63898 * flag we might come here so check explicitly for virtual.
63899 */
63900 if (curr.e_idx < 0) {
63901 goto fail_virtual;
63902 }
63903
63904 DUK_DDD(DUK_DDDPRINT("update existing property setter"));
63906
63907 tmp = DUK_HOBJECT_E_GET_VALUE_SETTER(thr->heap, obj, curr.e_idx);
63908 DUK_UNREF(tmp);
63909 DUK_HOBJECT_E_SET_VALUE_SETTER(thr->heap, obj, curr.e_idx, set);
63911 DUK_HOBJECT_DECREF_ALLOWNULL(thr, tmp); /* side effects; may invalidate e_idx */
63912 }
63913 if (has_get) {
63914 duk_hobject *tmp;
63915
63916 if (curr.e_idx < 0) {
63917 goto fail_virtual;
63918 }
63919
63920 DUK_DDD(DUK_DDDPRINT("update existing property getter"));
63922
63923 tmp = DUK_HOBJECT_E_GET_VALUE_GETTER(thr->heap, obj, curr.e_idx);
63924 DUK_UNREF(tmp);
63925 DUK_HOBJECT_E_SET_VALUE_GETTER(thr->heap, obj, curr.e_idx, get);
63927 DUK_HOBJECT_DECREF_ALLOWNULL(thr, tmp); /* side effects; may invalidate e_idx */
63928 }
63929 if (has_value) {
63930 duk_tval *tv1, *tv2;
63931
63932 DUK_DDD(DUK_DDDPRINT("update existing property value"));
63933
63934 if (curr.e_idx >= 0) {
63936 tv2 = duk_require_tval(thr, idx_value);
63937 tv1 = DUK_HOBJECT_E_GET_VALUE_TVAL_PTR(thr->heap, obj, curr.e_idx);
63938 DUK_TVAL_SET_TVAL_UPDREF(thr, tv1, tv2); /* side effects; may invalidate e_idx */
63939 } else {
63940 DUK_ASSERT(curr.a_idx < 0); /* array part case handled comprehensively previously */
63941
63942 DUK_DD(DUK_DDPRINT("Object.defineProperty(), value update for virtual property"));
63943 /* XXX: Uint8Array and other typed array virtual writes not currently
63944 * handled.
63945 */
63947 duk_harray *a;
63948 a = (duk_harray *) obj;
63949 DUK_DD(DUK_DDPRINT("Object.defineProperty() value update for duk_harray .length -> %ld",
63950 (long) arrlen_new_len));
63952 a->length = arrlen_new_len;
63953 } else {
63954 goto fail_virtual; /* should not happen */
63955 }
63956 }
63957 }
63958
63959 /*
63960 * Standard algorithm succeeded without errors, check for exotic post-behaviors.
63961 *
63962 * Arguments exotic behavior in E5 Section 10.6 occurs after the standard
63963 * [[DefineOwnProperty]] has completed successfully.
63964 *
63965 * Array exotic behavior in E5 Section 15.4.5.1 is implemented partly
63966 * prior to the default [[DefineOwnProperty]], but:
63967 * - for an array index key (e.g. "10") the final 'length' update occurs here
63968 * - for 'length' key the element deletion and 'length' update occurs here
63969 */
63970
63971success_exotics:
63972
63973 /* curr.a_idx or curr.e_idx may have been invalidated by side effects
63974 * above.
63975 */
63976
63977 /* [obj key desc value get set curr_value] */
63978
63980 duk_harray *a;
63981
63982 a = (duk_harray *) obj;
63984
63985 if (arridx_new_array_length > 0) {
63986 /*
63987 * Note: zero works as a "no update" marker because the new length
63988 * can never be zero after a new property is written.
63989 */
63990
63991 /* E5 Section 15.4.5.1, steps 4.e.i - 4.e.ii */
63992
63993 DUK_DDD(DUK_DDDPRINT("defineProperty successful, pending array length update to: %ld",
63994 (long) arridx_new_array_length));
63995
63996 a->length = arridx_new_array_length;
63997 }
63998
63999 if (key == DUK_HTHREAD_STRING_LENGTH(thr) && arrlen_new_len < arrlen_old_len) {
64000 /*
64001 * E5 Section 15.4.5.1, steps 3.k - 3.n. The order at the end combines
64002 * the error case 3.l.iii and the success case 3.m-3.n.
64003 */
64004
64005 /* XXX: investigate whether write protect can be handled above, if we
64006 * just update length here while ignoring its protected status
64007 */
64008
64009 duk_uint32_t result_len;
64010 duk_bool_t rc;
64011
64012 DUK_DDD(DUK_DDDPRINT("defineProperty successful, key is 'length', exotic array behavior, "
64013 "doing array element deletion and length update"));
64014
64015 rc =
64016 duk__handle_put_array_length_smaller(thr, obj, arrlen_old_len, arrlen_new_len, force_flag, &result_len);
64017
64018 /* update length (curr points to length, and we assume it's still valid) */
64019 DUK_ASSERT(result_len >= arrlen_new_len && result_len <= arrlen_old_len);
64020
64021 a->length = result_len;
64022
64023 if (pending_write_protect) {
64024 DUK_DDD(DUK_DDDPRINT("setting array length non-writable (pending writability update)"));
64026 }
64027
64028 /* XXX: shrink array allocation or entries compaction here? */
64029 if (!rc) {
64030 DUK_DD(DUK_DDPRINT("array length write only partially successful"));
64031 goto fail_not_configurable;
64032 }
64033 }
64034 } else if (arr_idx != DUK__NO_ARRAY_INDEX && DUK_HOBJECT_HAS_EXOTIC_ARGUMENTS(obj)) {
64035 duk_hobject *map;
64036 duk_hobject *varenv;
64037
64038 DUK_ASSERT(arridx_new_array_length == 0);
64039 DUK_ASSERT(!DUK_HOBJECT_HAS_EXOTIC_ARRAY(obj)); /* traits are separate; in particular, arguments not an array */
64040
64041 map = NULL;
64042 varenv = NULL;
64043 if (!duk__lookup_arguments_map(thr, obj, key, &curr, &map, &varenv)) {
64044 goto success_no_exotics;
64045 }
64046 DUK_ASSERT(map != NULL);
64047 DUK_ASSERT(varenv != NULL);
64048
64049 /* [obj key desc value get set curr_value varname] */
64050
64051 if (has_set || has_get) {
64052 /* = IsAccessorDescriptor(Desc) */
64053 DUK_DDD(DUK_DDDPRINT("defineProperty successful, key mapped to arguments 'map' "
64054 "changed to an accessor, delete arguments binding"));
64055
64056 (void) duk_hobject_delprop_raw(thr, map, key, 0); /* ignore result */
64057 } else {
64058 /* Note: this order matters (final value before deleting map entry must be done) */
64059 DUK_DDD(DUK_DDDPRINT("defineProperty successful, key mapped to arguments 'map', "
64060 "check for value update / binding deletion"));
64061
64062 if (has_value) {
64063 duk_hstring *varname;
64064
64065 DUK_DDD(DUK_DDDPRINT("defineProperty successful, key mapped to arguments 'map', "
64066 "update bound value (variable/argument)"));
64067
64068 varname = duk_require_hstring(thr, -1);
64069 DUK_ASSERT(varname != NULL);
64070
64071 DUK_DDD(DUK_DDDPRINT("arguments object automatic putvar for a bound variable; "
64072 "key=%!O, varname=%!O, value=%!T",
64073 (duk_heaphdr *) key,
64074 (duk_heaphdr *) varname,
64075 (duk_tval *) duk_require_tval(thr, idx_value)));
64076
64077 /* strict flag for putvar comes from our caller (currently: fixed) */
64078 duk_js_putvar_envrec(thr, varenv, varname, duk_require_tval(thr, idx_value), 1 /*throw_flag*/);
64079 }
64080 if (has_writable && !is_writable) {
64081 DUK_DDD(DUK_DDDPRINT("defineProperty successful, key mapped to arguments 'map', "
64082 "changed to non-writable, delete arguments binding"));
64083
64084 (void) duk_hobject_delprop_raw(thr, map, key, 0); /* ignore result */
64085 }
64086 }
64087
64088 /* 'varname' is in stack in this else branch, leaving an unbalanced stack below,
64089 * but this doesn't matter now.
64090 */
64091 }
64092
64093success_no_exotics:
64094 /* Some code paths use NORZ macros for simplicity, ensure refzero
64095 * handling is completed.
64096 */
64098 return 1;
64100fail_not_extensible:
64101 if (throw_flag) {
64103 DUK_WO_NORETURN(return 0;);
64104 }
64105 return 0;
64106
64107fail_virtual: /* just use the same "not configurable" error message" */
64108fail_not_configurable:
64109 if (throw_flag) {
64111 DUK_WO_NORETURN(return 0;);
64112 }
64113 return 0;
64114}
64115
64116/*
64117 * Object.prototype.hasOwnProperty() and Object.prototype.propertyIsEnumerable().
64118 */
64119
64121 duk_hstring *h_v;
64122 duk_hobject *h_obj;
64123 duk_propdesc desc;
64124 duk_bool_t ret;
64125
64126 /* coercion order matters */
64127 h_v = duk_to_hstring_acceptsymbol(thr, 0);
64128 DUK_ASSERT(h_v != NULL);
64129
64131 DUK_ASSERT(h_obj != NULL);
64132
64133 ret = duk_hobject_get_own_propdesc(thr, h_obj, h_v, &desc, 0 /*flags*/); /* don't push value */
64134
64135 duk_push_boolean(thr, ret && ((desc.flags & required_desc_flags) == required_desc_flags));
64136 return 1;
64137}
64138
64139/*
64140 * Object.seal() and Object.freeze() (E5 Sections 15.2.3.8 and 15.2.3.9)
64141 *
64142 * Since the algorithms are similar, a helper provides both functions.
64143 * Freezing is essentially sealing + making plain properties non-writable.
64144 *
64145 * Note: virtual (non-concrete) properties which are non-configurable but
64146 * writable would pose some problems, but such properties do not currently
64147 * exist (all virtual properties are non-configurable and non-writable).
64148 * If they did exist, the non-configurability does NOT prevent them from
64149 * becoming non-writable. However, this change should be recorded somehow
64150 * so that it would turn up (e.g. when getting the property descriptor),
64151 * requiring some additional flags in the object.
64152 */
64153
64156
64157 DUK_ASSERT(thr != NULL);
64158 DUK_ASSERT(thr->heap != NULL);
64159 DUK_ASSERT(obj != NULL);
64160
64162
64163#if defined(DUK_USE_ROM_OBJECTS)
64165 DUK_DD(DUK_DDPRINT("attempt to seal/freeze a readonly object, reject"));
64167 DUK_WO_NORETURN(return;);
64168 }
64169#endif
64170
64171 /*
64172 * Abandon array part because all properties must become non-configurable.
64173 * Note that this is now done regardless of whether this is always the case
64174 * (skips check, but performance problem if caller would do this many times
64175 * for the same object; not likely).
64176 */
64177
64178 duk__abandon_array_part(thr, obj);
64180
64181 for (i = 0; i < DUK_HOBJECT_GET_ENEXT(obj); i++) {
64182 duk_uint8_t *fp;
64183
64184 /* since duk__abandon_array_part() causes a resize, there should be no gaps in keys */
64185 DUK_ASSERT(DUK_HOBJECT_E_GET_KEY(thr->heap, obj, i) != NULL);
64186
64187 /* avoid multiple computations of flags address; bypasses macros */
64188 fp = DUK_HOBJECT_E_GET_FLAGS_PTR(thr->heap, obj, i);
64189 if (is_freeze && !((*fp) & DUK_PROPDESC_FLAG_ACCESSOR)) {
64191 } else {
64192 *fp &= ~DUK_PROPDESC_FLAG_CONFIGURABLE;
64193 }
64194 }
64197
64198 /* no need to compact since we already did that in duk__abandon_array_part()
64199 * (regardless of whether an array part existed or not.
64200 */
64201
64202 return;
64203}
64204
64205/*
64206 * Object.isSealed() and Object.isFrozen() (E5 Sections 15.2.3.11, 15.2.3.13)
64207 *
64208 * Since the algorithms are similar, a helper provides both functions.
64209 * Freezing is essentially sealing + making plain properties non-writable.
64210 *
64211 * Note: all virtual (non-concrete) properties are currently non-configurable
64212 * and non-writable (and there are no accessor virtual properties), so they don't
64213 * need to be considered here now.
64214 */
64215
64218
64219 DUK_ASSERT(obj != NULL);
64220 DUK_UNREF(thr);
64221
64222 /* Note: no allocation pressure, no need to check refcounts etc */
64223
64224 /* must not be extensible */
64225 if (DUK_HOBJECT_HAS_EXTENSIBLE(obj)) {
64226 return 0;
64227 }
64228
64229 /* all virtual properties are non-configurable and non-writable */
64230
64231 /* entry part must not contain any configurable properties, or
64232 * writable properties (if is_frozen).
64233 */
64234 for (i = 0; i < DUK_HOBJECT_GET_ENEXT(obj); i++) {
64235 duk_small_uint_t flags;
64236
64237 if (!DUK_HOBJECT_E_GET_KEY(thr->heap, obj, i)) {
64238 continue;
64239 }
64240
64241 /* avoid multiple computations of flags address; bypasses macros */
64242 flags = (duk_small_uint_t) DUK_HOBJECT_E_GET_FLAGS(thr->heap, obj, i);
64243
64244 if (flags & DUK_PROPDESC_FLAG_CONFIGURABLE) {
64245 return 0;
64246 }
64247 if (is_frozen && !(flags & DUK_PROPDESC_FLAG_ACCESSOR) && (flags & DUK_PROPDESC_FLAG_WRITABLE)) {
64248 return 0;
64249 }
64250 }
64251
64252 /* array part must not contain any non-unused properties, as they would
64253 * be configurable and writable.
64254 */
64255 for (i = 0; i < DUK_HOBJECT_GET_ASIZE(obj); i++) {
64256 duk_tval *tv = DUK_HOBJECT_A_GET_VALUE_PTR(thr->heap, obj, i);
64257 if (!DUK_TVAL_IS_UNUSED(tv)) {
64258 return 0;
64259 }
64260 }
64261
64262 return 1;
64263}
64264
64265/*
64266 * Object.preventExtensions() and Object.isExtensible() (E5 Sections 15.2.3.10, 15.2.3.13)
64267 *
64268 * Not needed, implemented by macros DUK_HOBJECT_{HAS,CLEAR,SET}_EXTENSIBLE
64269 * and the Object built-in bindings.
64270 */
64271
64272/* automatic undefs */
64273#undef DUK__HASH_DELETED
64274#undef DUK__HASH_UNUSED
64275#undef DUK__NO_ARRAY_INDEX
64276#undef DUK__VALSTACK_PROXY_LOOKUP
64277#undef DUK__VALSTACK_SPACE
64278/*
64279 * duk_hstring assertion helpers.
64281
64282/* #include duk_internal.h -> already included */
64283
64284#if defined(DUK_USE_ASSERTIONS)
64285
64286DUK_INTERNAL void duk_hstring_assert_valid(duk_hstring *h) {
64287 DUK_ASSERT(h != NULL);
64288}
64289
64290#endif /* DUK_USE_ASSERTIONS */
64291/*
64292 * Misc support functions
64293 */
64294
64295/* #include duk_internal.h -> already included */
64296
64297/*
64298 * duk_hstring charCodeAt, with and without surrogate awareness
64299 */
64300
64302 duk_hstring *h,
64303 duk_uint_t pos,
64304 duk_bool_t surrogate_aware) {
64305 duk_uint32_t boff;
64306 const duk_uint8_t *p, *p_start, *p_end;
64307 duk_ucodepoint_t cp1;
64308 duk_ucodepoint_t cp2;
64309
64310 /* Caller must check character offset to be inside the string. */
64311 DUK_ASSERT(thr != NULL);
64312 DUK_ASSERT(h != NULL);
64313 DUK_ASSERT_DISABLE(pos >= 0); /* unsigned */
64315
64316 boff = (duk_uint32_t) duk_heap_strcache_offset_char2byte(thr, h, (duk_uint32_t) pos);
64317 DUK_DDD(DUK_DDDPRINT("charCodeAt: pos=%ld -> boff=%ld, str=%!O", (long) pos, (long) boff, (duk_heaphdr *) h));
64318 DUK_ASSERT_DISABLE(boff >= 0);
64320
64321 p_start = DUK_HSTRING_GET_DATA(h);
64322 p_end = p_start + DUK_HSTRING_GET_BYTELEN(h);
64323 p = p_start + boff;
64324 DUK_DDD(DUK_DDDPRINT("p_start=%p, p_end=%p, p=%p", (const void *) p_start, (const void *) p_end, (const void *) p));
64325
64326 /* For invalid UTF-8 (never happens for standard ECMAScript strings)
64327 * return U+FFFD replacement character.
64328 */
64329 if (duk_unicode_decode_xutf8(thr, &p, p_start, p_end, &cp1)) {
64330 if (surrogate_aware && cp1 >= 0xd800UL && cp1 <= 0xdbffUL) {
64331 /* The decode helper is memory safe even if 'cp1' was
64332 * decoded at the end of the string and 'p' is no longer
64333 * within string memory range.
64334 */
64335 cp2 = 0; /* If call fails, this is left untouched and won't match cp2 check. */
64336 (void) duk_unicode_decode_xutf8(thr, &p, p_start, p_end, &cp2);
64337 if (cp2 >= 0xdc00UL && cp2 <= 0xdfffUL) {
64338 cp1 = (duk_ucodepoint_t) (((cp1 - 0xd800UL) << 10) + (cp2 - 0xdc00UL) + 0x10000UL);
64339 }
64340 }
64341 } else {
64343 }
64344
64345 return cp1;
64346}
64347
64348/*
64349 * duk_hstring charlen, when lazy charlen disabled
64350 */
64351
64352#if !defined(DUK_USE_HSTRING_LAZY_CLEN)
64353#if !defined(DUK_USE_HSTRING_CLEN)
64354#error non-lazy duk_hstring charlen but DUK_USE_HSTRING_CLEN not set
64355#endif
64356DUK_INTERNAL void duk_hstring_init_charlen(duk_hstring *h) {
64357 duk_uint32_t clen;
64358
64359 DUK_ASSERT(h != NULL);
64362
64364#if defined(DUK_USE_STRLEN16)
64365 DUK_ASSERT(clen <= 0xffffUL); /* Bytelength checked during interning. */
64366 h->clen16 = (duk_uint16_t) clen;
64367#else
64368 h->clen = (duk_uint32_t) clen;
64369#endif
64370 if (DUK_LIKELY(clen == DUK_HSTRING_GET_BYTELEN(h))) {
64372 }
64373}
64374
64376#if defined(DUK_USE_STRLEN16)
64377 return h->clen16;
64378#else
64379 return h->clen;
64380#endif
64381}
64382#endif /* !DUK_USE_HSTRING_LAZY_CLEN */
64383
64384/*
64385 * duk_hstring charlen, when lazy charlen enabled
64386 */
64387
64388#if defined(DUK_USE_HSTRING_LAZY_CLEN)
64389#if defined(DUK_USE_HSTRING_CLEN)
64391 duk_size_t res;
64392
64393 DUK_ASSERT(h->clen == 0); /* Checked by caller. */
64394
64395#if defined(DUK_USE_ROM_STRINGS)
64396 /* ROM strings have precomputed clen, but if the computed clen is zero
64397 * we can still come here and can't write anything.
64398 */
64400 return 0;
64401 }
64402#endif
64403
64405#if defined(DUK_USE_STRLEN16)
64406 DUK_ASSERT(res <= 0xffffUL); /* Bytelength checked during interning. */
64407 h->clen16 = (duk_uint16_t) res;
64408#else
64409 h->clen = (duk_uint32_t) res;
64410#endif
64411 if (DUK_LIKELY(res == DUK_HSTRING_GET_BYTELEN(h))) {
64413 }
64414 return res;
64415}
64416#else /* DUK_USE_HSTRING_CLEN */
64419 /* Most practical strings will go here. */
64420 return DUK_HSTRING_GET_BYTELEN(h);
64421 } else {
64422 /* ASCII flag is lazy, so set it here. */
64423 duk_size_t res;
64424
64425 /* XXX: here we could use the strcache to speed up the
64426 * computation (matters for 'i < str.length' loops).
64428
64430
64431#if defined(DUK_USE_ROM_STRINGS)
64433 /* For ROM strings, can't write anything; ASCII flag
64434 * is preset so we don't need to update it.
64435 */
64436 return res;
64437 }
64438#endif
64439 if (DUK_LIKELY(res == DUK_HSTRING_GET_BYTELEN(h))) {
64441 }
64442 return res;
64443 }
64444}
64445#endif /* DUK_USE_HSTRING_CLEN */
64446
64447#if defined(DUK_USE_HSTRING_CLEN)
64449#if defined(DUK_USE_STRLEN16)
64450 if (DUK_LIKELY(h->clen16 != 0)) {
64451 return h->clen16;
64452 }
64453#else
64454 if (DUK_LIKELY(h->clen != 0)) {
64455 return h->clen;
64456 }
64457#endif
64459}
64460#else /* DUK_USE_HSTRING_CLEN */
64462 /* Always use slow path. */
64464}
64465#endif /* DUK_USE_HSTRING_CLEN */
64466#endif /* DUK_USE_HSTRING_LAZY_CLEN */
64467
64468/*
64469 * Compare duk_hstring to an ASCII cstring.
64470 */
64471
64473 duk_size_t len;
64474
64475 DUK_ASSERT(h != NULL);
64476 DUK_ASSERT(cstr != NULL);
64477
64478 len = DUK_STRLEN(cstr);
64479 if (len != DUK_HSTRING_GET_BYTELEN(h)) {
64480 return 0;
64481 }
64482 if (duk_memcmp((const void *) cstr, (const void *) DUK_HSTRING_GET_DATA(h), len) == 0) {
64483 return 1;
64484 }
64485 return 0;
64486}
64487/*
64488 * duk_hthread allocation and freeing.
64489 */
64490
64491/* #include duk_internal.h -> already included */
64492
64493/*
64494 * Allocate initial stacks for a thread. Note that 'thr' must be reachable
64495 * as a garbage collection may be triggered by the allocation attempts.
64496 * Returns zero (without leaking memory) if init fails.
64497 */
64498
64500 duk_size_t alloc_size;
64501 duk_size_t i;
64502
64503 DUK_ASSERT(heap != NULL);
64504 DUK_ASSERT(thr != NULL);
64505 DUK_ASSERT(thr->valstack == NULL);
64506 DUK_ASSERT(thr->valstack_end == NULL);
64507 DUK_ASSERT(thr->valstack_alloc_end == NULL);
64508 DUK_ASSERT(thr->valstack_bottom == NULL);
64509 DUK_ASSERT(thr->valstack_top == NULL);
64510 DUK_ASSERT(thr->callstack_curr == NULL);
64511
64512 /* valstack */
64514 alloc_size = sizeof(duk_tval) * DUK_VALSTACK_INITIAL_SIZE;
64515 thr->valstack = (duk_tval *) DUK_ALLOC(heap, alloc_size);
64516 if (!thr->valstack) {
64517 goto fail;
64518 }
64519 duk_memzero(thr->valstack, alloc_size);
64522 thr->valstack_bottom = thr->valstack;
64523 thr->valstack_top = thr->valstack;
64524
64525 for (i = 0; i < DUK_VALSTACK_INITIAL_SIZE; i++) {
64527 }
64528
64529 return 1;
64530
64531fail:
64532 DUK_FREE(heap, thr->valstack);
64533 DUK_ASSERT(thr->callstack_curr == NULL);
64534
64535 thr->valstack = NULL;
64536 return 0;
64539/* For indirect allocs. */
64541DUK_INTERNAL void *duk_hthread_get_valstack_ptr(duk_heap *heap, void *ud) {
64543 DUK_UNREF(heap);
64544 return (void *) thr->valstack;
64547 * Initialize built-in objects. Current thread must have a valstack
64548 * and initialization errors may longjmp, so a setjmp() catch point
64549 * must exist.
64552/* #include duk_internal.h -> already included */
64553
64554/*
64555 * Encoding constants, must match genbuiltins.py
64556 */
64557
64558#define DUK__PROP_FLAGS_BITS 3
64559#define DUK__LENGTH_PROP_BITS 3
64560#define DUK__NARGS_BITS 3
64561#define DUK__PROP_TYPE_BITS 3
64562
64563#define DUK__NARGS_VARARGS_MARKER 0x07
64564
64565#define DUK__PROP_TYPE_DOUBLE 0
64566#define DUK__PROP_TYPE_STRING 1
64567#define DUK__PROP_TYPE_STRIDX 2
64568#define DUK__PROP_TYPE_BUILTIN 3
64569#define DUK__PROP_TYPE_UNDEFINED 4
64570#define DUK__PROP_TYPE_BOOLEAN_TRUE 5
64571#define DUK__PROP_TYPE_BOOLEAN_FALSE 6
64572#define DUK__PROP_TYPE_ACCESSOR 7
64573
64574/*
64575 * Create built-in objects by parsing an init bitstream generated
64576 * by genbuiltins.py.
64577 */
64578
64579#if defined(DUK_USE_ROM_OBJECTS)
64580#if defined(DUK_USE_ROM_GLOBAL_CLONE) || defined(DUK_USE_ROM_GLOBAL_INHERIT)
64581DUK_LOCAL void duk__duplicate_ram_global_object(duk_hthread *thr) {
64582 duk_hobject *h_global;
64583#if defined(DUK_USE_ROM_GLOBAL_CLONE)
64584 duk_hobject *h_oldglobal;
64585 duk_uint8_t *props;
64586 duk_size_t alloc_size;
64587#endif
64588 duk_hobject *h_objenv;
64589
64590 /* XXX: refactor into internal helper, duk_clone_hobject() */
64591
64592#if defined(DUK_USE_ROM_GLOBAL_INHERIT)
64593 /* Inherit from ROM-based global object: less RAM usage, less transparent. */
64594 h_global = duk_push_object_helper(thr,
64598 DUK_ASSERT(h_global != NULL);
64599#elif defined(DUK_USE_ROM_GLOBAL_CLONE)
64600 /* Clone the properties of the ROM-based global object to create a
64601 * fully RAM-based global object. Uses more memory than the inherit
64602 * model but more compliant.
64603 */
64604 h_global = duk_push_object_helper(thr,
64608 DUK_ASSERT(h_global != NULL);
64609 h_oldglobal = thr->builtins[DUK_BIDX_GLOBAL];
64610 DUK_ASSERT(h_oldglobal != NULL);
64611
64612 /* Copy the property table verbatim; this handles attributes etc.
64613 * For ROM objects it's not necessary (or possible) to update
64614 * refcounts so leave them as is.
64615 */
64616 alloc_size = DUK_HOBJECT_P_ALLOC_SIZE(h_oldglobal);
64617 DUK_ASSERT(alloc_size > 0);
64618 props = DUK_ALLOC_CHECKED(thr, alloc_size);
64619 DUK_ASSERT(props != NULL);
64620 DUK_ASSERT(DUK_HOBJECT_GET_PROPS(thr->heap, h_oldglobal) != NULL);
64621 duk_memcpy((void *) props, (const void *) DUK_HOBJECT_GET_PROPS(thr->heap, h_oldglobal), alloc_size);
64622
64623 /* XXX: keep property attributes or tweak them here?
64624 * Properties will now be non-configurable even when they're
64625 * normally configurable for the global object.
64626 */
64627
64628 DUK_ASSERT(DUK_HOBJECT_GET_PROPS(thr->heap, h_global) == NULL);
64629 DUK_HOBJECT_SET_PROPS(thr->heap, h_global, props);
64630 DUK_HOBJECT_SET_ESIZE(h_global, DUK_HOBJECT_GET_ESIZE(h_oldglobal));
64631 DUK_HOBJECT_SET_ENEXT(h_global, DUK_HOBJECT_GET_ENEXT(h_oldglobal));
64632 DUK_HOBJECT_SET_ASIZE(h_global, DUK_HOBJECT_GET_ASIZE(h_oldglobal));
64633 DUK_HOBJECT_SET_HSIZE(h_global, DUK_HOBJECT_GET_HSIZE(h_oldglobal));
64634#else
64635#error internal error in config defines
64636#endif
64637
64638 duk_hobject_compact_props(thr, h_global);
64639 DUK_ASSERT(thr->builtins[DUK_BIDX_GLOBAL] != NULL);
64640 DUK_ASSERT(
64641 !DUK_HEAPHDR_NEEDS_REFCOUNT_UPDATE((duk_heaphdr *) thr->builtins[DUK_BIDX_GLOBAL])); /* no need to decref: ROM object */
64642 thr->builtins[DUK_BIDX_GLOBAL] = h_global;
64643 DUK_HOBJECT_INCREF(thr, h_global);
64644 DUK_D(DUK_DPRINT("duplicated global object: %!O", h_global));
64645
64646 /* Create a fresh object environment for the global scope. This is
64647 * needed so that the global scope points to the newly created RAM-based
64648 * global object.
64649 */
64650 h_objenv =
64653 DUK_ASSERT(h_objenv != NULL);
64654 DUK_ASSERT(DUK_HOBJECT_GET_PROTOTYPE(thr->heap, h_objenv) == NULL);
64655 duk_push_hobject(thr, h_objenv);
64656
64657 DUK_ASSERT(h_global != NULL);
64658 ((duk_hobjenv *) h_objenv)->target = h_global;
64659 DUK_HOBJECT_INCREF(thr, h_global);
64660 DUK_ASSERT(((duk_hobjenv *) h_objenv)->has_this == 0);
64661
64664 (duk_heaphdr *) thr->builtins[DUK_BIDX_GLOBAL_ENV])); /* no need to decref: ROM object */
64665 thr->builtins[DUK_BIDX_GLOBAL_ENV] = h_objenv;
64666 DUK_HOBJECT_INCREF(thr, h_objenv);
64667 DUK_D(DUK_DPRINT("duplicated global env: %!O", h_objenv));
64668
64670
64671 duk_pop_2(thr); /* Pop global object and global env. */
64672}
64673#endif /* DUK_USE_ROM_GLOBAL_CLONE || DUK_USE_ROM_GLOBAL_INHERIT */
64674
64676 /* Setup builtins from ROM objects. All heaps/threads will share
64677 * the same readonly objects.
64678 */
64680
64681 for (i = 0; i < DUK_NUM_BUILTINS; i++) {
64682 duk_hobject *h;
64683 h = (duk_hobject *) DUK_LOSE_CONST(duk_rom_builtins_bidx[i]);
64684 DUK_ASSERT(h != NULL);
64685 thr->builtins[i] = h;
64686 }
64687
64688#if defined(DUK_USE_ROM_GLOBAL_CLONE) || defined(DUK_USE_ROM_GLOBAL_INHERIT)
64689 /* By default the global object is read-only which is often much
64690 * more of an issue than having read-only built-in objects (like
64691 * RegExp, Date, etc). Use a RAM-based copy of the global object
64692 * and the global environment object for convenience.
64693 */
64694 duk__duplicate_ram_global_object(thr);
64695#endif
64696}
64697#else /* DUK_USE_ROM_OBJECTS */
64700
64702 DUK_ASSERT_DISABLE(n >= 0); /* unsigned */
64705}
64707 /* XXX: built-ins data could provide a maximum length that is
64708 * actually needed; bitpacked max length is now 256 bytes.
64709 */
64710 duk_uint8_t tmp[DUK_BD_BITPACKED_STRING_MAXLEN];
64711 duk_small_uint_t len;
64712
64713 len = duk_bd_decode_bitpacked_string(bd, tmp);
64714 duk_push_lstring(thr, (const char *) tmp, (duk_size_t) len);
64715}
64718
64720 if (n == 0) {
64722 } else {
64723 n--;
64726 }
64727}
64731
64732 for (i = 0; i < 8; i++) {
64733 /* Encoding endianness must match target memory layout,
64734 * build scripts and genbuiltins.py must ensure this.
64735 */
64736 du.uc[i] = (duk_uint8_t) duk_bd_decode(bd, 8);
64737 }
64738
64739 duk_push_number(thr, du.d); /* push operation normalizes NaNs */
64740}
64741
64743 duk_bitdecoder_ctx bd_ctx;
64744 duk_bitdecoder_ctx *bd = &bd_ctx; /* convenience */
64745 duk_hobject *h;
64746 duk_small_uint_t i, j;
64747
64748 DUK_D(DUK_DPRINT("INITBUILTINS BEGIN: DUK_NUM_BUILTINS=%d, DUK_NUM_BUILTINS_ALL=%d",
64749 (int) DUK_NUM_BUILTINS,
64750 (int) DUK_NUM_ALL_BUILTINS));
64751
64752 duk_memzero(&bd_ctx, sizeof(bd_ctx));
64753 bd->data = (const duk_uint8_t *) duk_builtins_data;
64754 bd->length = (duk_size_t) DUK_BUILTINS_DATA_LENGTH;
64755
64756 /*
64757 * First create all built-in bare objects on the empty valstack.
64758 *
64759 * Built-ins in the index range [0,DUK_NUM_BUILTINS-1] have value
64760 * stack indices matching their eventual thr->builtins[] index.
64761 *
64762 * Built-ins in the index range [DUK_NUM_BUILTINS,DUK_NUM_ALL_BUILTINS]
64763 * will exist on the value stack during init but won't be placed
64764 * into thr->builtins[]. These are objects referenced in some way
64765 * from thr->builtins[] roots but which don't need to be indexed by
64766 * Duktape through thr->builtins[] (e.g. user custom objects).
64767 *
64768 * Internal prototypes will be incorrect (NULL) at this stage.
64769 */
64770
64772
64773 DUK_DD(DUK_DDPRINT("create empty built-ins"));
64774 DUK_ASSERT_TOP(thr, 0);
64775 for (i = 0; i < DUK_NUM_ALL_BUILTINS; i++) {
64776 duk_small_uint_t class_num;
64777 duk_small_int_t len = -1; /* must be signed */
64778
64779 class_num = (duk_small_uint_t) duk_bd_decode_varuint(bd);
64780 len = (duk_small_int_t) duk_bd_decode_flagged_signed(bd, DUK__LENGTH_PROP_BITS, (duk_int32_t) -1 /*def_value*/);
64781
64782 if (class_num == DUK_HOBJECT_CLASS_FUNCTION) {
64783 duk_small_uint_t natidx;
64784 duk_small_int_t c_nargs; /* must hold DUK_VARARGS */
64785 duk_c_function c_func;
64786 duk_int16_t magic;
64787
64788 DUK_DDD(DUK_DDDPRINT("len=%ld", (long) len));
64789 DUK_ASSERT(len >= 0);
64790
64792 DUK_ASSERT(natidx != 0);
64793 c_func = duk_bi_native_functions[natidx];
64794 DUK_ASSERT(c_func != NULL);
64795
64796 c_nargs = (duk_small_int_t) duk_bd_decode_flagged_signed(bd, DUK__NARGS_BITS, len /*def_value*/);
64797 if (c_nargs == DUK__NARGS_VARARGS_MARKER) {
64798 c_nargs = DUK_VARARGS;
64799 }
64800
64801 /* XXX: set magic directly here? (it could share the c_nargs arg) */
64802 (void) duk_push_c_function_builtin(thr, c_func, c_nargs);
64803 h = duk_known_hobject(thr, -1);
64804
64805 /* Currently all built-in native functions are strict.
64806 * duk_push_c_function() now sets strict flag, so
64807 * assert for it.
64808 */
64810
64811 /* XXX: function properties */
64812
64814#if defined(DUK_USE_FUNC_NAME_PROPERTY)
64816#else
64817 duk_pop(thr); /* Not very ideal but good enough for now. */
64818#endif
64819
64820 /* Almost all global level Function objects are constructable
64821 * but not all: Function.prototype is a non-constructable,
64822 * callable Function.
64823 */
64824 if (duk_bd_decode_flag(bd)) {
64826 } else {
64828 }
64829
64830 /* Cast converts magic to 16-bit signed value */
64831 magic = (duk_int16_t) duk_bd_decode_varuint(bd);
64832 ((duk_hnatfunc *) h)->magic = magic;
64833 } else if (class_num == DUK_HOBJECT_CLASS_ARRAY) {
64834 duk_push_array(thr);
64835 } else if (class_num == DUK_HOBJECT_CLASS_OBJENV) {
64836 duk_hobjenv *env;
64837 duk_hobject *global;
64838
64841
64842 env = duk_hobjenv_alloc(thr,
64844 DUK_ASSERT(env->target == NULL);
64845 duk_push_hobject(thr, (duk_hobject *) env);
64846
64847 global = duk_known_hobject(thr, DUK_BIDX_GLOBAL);
64848 DUK_ASSERT(global != NULL);
64849 env->target = global;
64850 DUK_HOBJECT_INCREF(thr, global);
64851 DUK_ASSERT(env->has_this == 0);
64852
64854 } else {
64856
64857 (void) duk_push_object_helper(thr,
64859 -1); /* no prototype or class yet */
64860 }
64861
64862 h = duk_known_hobject(thr, -1);
64863 DUK_HOBJECT_SET_CLASS_NUMBER(h, class_num);
64864
64865 if (i < DUK_NUM_BUILTINS) {
64866 thr->builtins[i] = h;
64867 DUK_HOBJECT_INCREF(thr, &h->hdr);
64868 }
64869
64870 if (len >= 0) {
64871 /* In ES2015+ built-in function object .length property
64872 * has property attributes C (configurable only):
64873 * http://www.ecma-international.org/ecma-262/7.0/#sec-ecmascript-standard-built-in-objects
64874 *
64875 * Array.prototype remains an Array instance in ES2015+
64876 * and its length has attributes W (writable only).
64877 * Because .length is now virtual for duk_harray, it is
64878 * not encoded explicitly in init data.
64879 */
64880
64881 DUK_ASSERT(class_num != DUK_HOBJECT_CLASS_ARRAY); /* .length is virtual */
64882 duk_push_int(thr, len);
64884 }
64885
64886 /* enable exotic behaviors last */
64887
64888 if (class_num == DUK_HOBJECT_CLASS_ARRAY) {
64889 DUK_ASSERT(DUK_HOBJECT_HAS_EXOTIC_ARRAY(h)); /* set by duk_push_array() */
64890 }
64891 if (class_num == DUK_HOBJECT_CLASS_STRING) {
64893 }
64894
64895 /* some assertions */
64896
64898 /* DUK_HOBJECT_FLAG_CONSTRUCTABLE varies */
64901 /* DUK_HOBJECT_FLAG_NATFUNC varies */
64905 /* DUK_HOBJECT_FLAG_STRICT varies */
64906 DUK_ASSERT(!DUK_HOBJECT_HAS_NATFUNC(h) || /* all native functions have NEWENV */
64910 /* DUK_HOBJECT_FLAG_EXOTIC_ARRAY varies */
64911 /* DUK_HOBJECT_FLAG_EXOTIC_STRINGOBJ varies */
64913
64914 DUK_DDD(DUK_DDDPRINT("created built-in %ld, class=%ld, length=%ld", (long) i, (long) class_num, (long) len));
64915 }
64916
64917 /*
64918 * Then decode the builtins init data (see genbuiltins.py) to
64919 * init objects. Internal prototypes are set at this stage,
64920 * with thr->builtins[] populated.
64921 */
64922
64923 DUK_DD(DUK_DDPRINT("initialize built-in object properties"));
64924 for (i = 0; i < DUK_NUM_ALL_BUILTINS; i++) {
64926 duk_small_uint_t num;
64927
64928 DUK_DDD(DUK_DDDPRINT("initializing built-in object at index %ld", (long) i));
64929 h = duk_known_hobject(thr, (duk_idx_t) i);
64930
64932 if (t > 0) {
64933 t--;
64934 DUK_DDD(DUK_DDDPRINT("set internal prototype: built-in %ld", (long) t));
64936 } else if (DUK_HOBJECT_IS_NATFUNC(h)) {
64937 /* Standard native built-ins cannot inherit from
64938 * %NativeFunctionPrototype%, they are required to
64939 * inherit from Function.prototype directly.
64940 */
64943 }
64944
64946 if (t > 0) {
64947 /* 'prototype' property for all built-in objects (which have it) has attributes:
64948 * [[Writable]] = false,
64949 * [[Enumerable]] = false,
64950 * [[Configurable]] = false
64951 */
64952 t--;
64953 DUK_DDD(DUK_DDDPRINT("set external prototype: built-in %ld", (long) t));
64954 duk_dup(thr, (duk_idx_t) t);
64956 }
64957
64959 if (t > 0) {
64960 /* 'constructor' property for all built-in objects (which have it) has attributes:
64961 * [[Writable]] = true,
64962 * [[Enumerable]] = false,
64963 * [[Configurable]] = true
64964 */
64965 t--;
64966 DUK_DDD(DUK_DDDPRINT("set external constructor: built-in %ld", (long) t));
64967 duk_dup(thr, (duk_idx_t) t);
64969 }
64970
64971 /* normal valued properties */
64973 DUK_DDD(DUK_DDDPRINT("built-in object %ld, %ld normal valued properties", (long) i, (long) num));
64974 for (j = 0; j < num; j++) {
64975 duk_small_uint_t defprop_flags;
64976
64978
64979 /*
64980 * Property attribute defaults are defined in E5 Section 15 (first
64981 * few pages); there is a default for all properties and a special
64982 * default for 'length' properties. Variation from the defaults is
64983 * signaled using a single flag bit in the bitstream.
64984 */
64985
64986 defprop_flags = (duk_small_uint_t) duk_bd_decode_flagged(bd,
64988 (duk_uint32_t) DUK_PROPDESC_FLAGS_WC);
64991 DUK_DEFPROP_HAVE_CONFIGURABLE; /* Defaults for data properties. */
64992
64993 /* The writable, enumerable, configurable flags in prop_flags
64994 * match both duk_def_prop() and internal property flags.
64995 */
64999
65001
65002 DUK_DDD(DUK_DDDPRINT("built-in %ld, normal-valued property %ld, key %!T, flags 0x%02lx, type %ld",
65003 (long) i,
65004 (long) j,
65005 duk_get_tval(thr, -1),
65006 (unsigned long) defprop_flags,
65007 (long) t));
65008
65009 switch (t) {
65010 case DUK__PROP_TYPE_DOUBLE: {
65011 duk__push_double(thr, bd);
65012 break;
65013 }
65014 case DUK__PROP_TYPE_STRING: {
65015 duk__push_string(thr, bd);
65016 break;
65017 }
65018 case DUK__PROP_TYPE_STRIDX: {
65019 duk__push_stridx(thr, bd);
65020 break;
65021 }
65023 duk_small_uint_t bidx;
65024
65026 duk_dup(thr, (duk_idx_t) bidx);
65027 break;
65028 }
65030 duk_push_undefined(thr);
65031 break;
65032 }
65034 duk_push_true(thr);
65035 break;
65036 }
65038 duk_push_false(thr);
65039 break;
65040 }
65045 duk_c_function c_func_getter;
65046 duk_c_function c_func_setter;
65047
65049 "built-in accessor property: objidx=%ld, key=%!T, getteridx=%ld, setteridx=%ld, flags=0x%04lx",
65050 (long) i,
65051 duk_get_tval(thr, -1),
65052 (long) natidx_getter,
65053 (long) natidx_setter,
65054 (unsigned long) defprop_flags));
65055
65056 c_func_getter = duk_bi_native_functions[natidx_getter];
65057 if (c_func_getter != NULL) {
65058 duk_push_c_function_builtin_noconstruct(thr, c_func_getter, 0); /* always 0 args */
65059 duk_set_magic(thr, -1, (duk_int_t) accessor_magic);
65060 defprop_flags |= DUK_DEFPROP_HAVE_GETTER;
65061 }
65062 c_func_setter = duk_bi_native_functions[natidx_setter];
65063 if (c_func_setter != NULL) {
65064 duk_push_c_function_builtin_noconstruct(thr, c_func_setter, 1); /* always 1 arg */
65065 duk_set_magic(thr, -1, (duk_int_t) accessor_magic);
65066 defprop_flags |= DUK_DEFPROP_HAVE_SETTER;
65067 }
65068
65069 /* Writable flag doesn't make sense for an accessor. */
65070 DUK_ASSERT((defprop_flags & DUK_PROPDESC_FLAG_WRITABLE) == 0); /* genbuiltins.py ensures */
65071
65074 break;
65075 }
65076 default: {
65077 /* exhaustive */
65079 }
65080 }
65081
65082 duk_def_prop(thr, (duk_idx_t) i, defprop_flags);
65084 }
65085
65086 /* native function properties */
65088 DUK_DDD(DUK_DDDPRINT("built-in object %ld, %ld function valued properties", (long) i, (long) num));
65089 for (j = 0; j < num; j++) {
65090 duk_hstring *h_key;
65091 duk_small_uint_t natidx;
65092 duk_int_t c_nargs; /* must hold DUK_VARARGS */
65093 duk_small_uint_t c_length;
65094 duk_int16_t magic;
65095 duk_c_function c_func;
65096 duk_hnatfunc *h_func;
65097#if defined(DUK_USE_LIGHTFUNC_BUILTINS)
65098 duk_small_int_t lightfunc_eligible;
65099#endif
65100 duk_small_uint_t defprop_flags;
65101
65103 h_key = duk_known_hstring(thr, -1);
65104 DUK_UNREF(h_key);
65106
65108 c_nargs = (duk_int_t) duk_bd_decode_flagged(bd, DUK__NARGS_BITS, (duk_uint32_t) c_length /*def_value*/);
65109 if (c_nargs == DUK__NARGS_VARARGS_MARKER) {
65110 c_nargs = DUK_VARARGS;
65111 }
65112
65113 c_func = duk_bi_native_functions[natidx];
65114
65115 DUK_DDD(
65116 DUK_DDDPRINT("built-in %ld, function-valued property %ld, key %!O, natidx %ld, length %ld, nargs %ld",
65117 (long) i,
65118 (long) j,
65119 (duk_heaphdr *) h_key,
65120 (long) natidx,
65121 (long) c_length,
65122 (c_nargs == DUK_VARARGS ? (long) -1 : (long) c_nargs)));
65123
65124 /* Cast converts magic to 16-bit signed value */
65125 magic = (duk_int16_t) duk_bd_decode_varuint(bd);
65126
65127#if defined(DUK_USE_LIGHTFUNC_BUILTINS)
65128 lightfunc_eligible =
65129 ((c_nargs >= DUK_LFUNC_NARGS_MIN && c_nargs <= DUK_LFUNC_NARGS_MAX) || (c_nargs == DUK_VARARGS)) &&
65130 (c_length <= DUK_LFUNC_LENGTH_MAX) && (magic >= DUK_LFUNC_MAGIC_MIN && magic <= DUK_LFUNC_MAGIC_MAX);
65131
65132 /* These functions have trouble working as lightfuncs.
65133 * Some of them have specific asserts and some may have
65134 * additional properties (e.g. 'require.id' may be written).
65135 */
65136 if (c_func == duk_bi_global_object_eval) {
65137 lightfunc_eligible = 0;
65138 }
65139#if defined(DUK_USE_COROUTINE_SUPPORT)
65140 if (c_func == duk_bi_thread_yield || c_func == duk_bi_thread_resume) {
65141 lightfunc_eligible = 0;
65142 }
65143#endif
65145 c_func == duk_bi_reflect_apply || c_func == duk_bi_reflect_construct) {
65146 lightfunc_eligible = 0;
65147 }
65148
65149 if (lightfunc_eligible) {
65150 duk_tval tv_lfunc;
65151 duk_small_uint_t lf_nargs =
65152 (duk_small_uint_t) (c_nargs == DUK_VARARGS ? DUK_LFUNC_NARGS_VARARGS : c_nargs);
65153 duk_small_uint_t lf_flags = DUK_LFUNC_FLAGS_PACK(magic, c_length, lf_nargs);
65154 DUK_TVAL_SET_LIGHTFUNC(&tv_lfunc, c_func, lf_flags);
65155 duk_push_tval(thr, &tv_lfunc);
65156 DUK_D(DUK_DPRINT("built-in function eligible as light function: i=%d, j=%d c_length=%ld, "
65157 "c_nargs=%ld, magic=%ld -> %!iT",
65158 (int) i,
65159 (int) j,
65160 (long) c_length,
65161 (long) c_nargs,
65162 (long) magic,
65163 duk_get_tval(thr, -1)));
65164 goto lightfunc_skip;
65165 }
65166
65168 "built-in function NOT ELIGIBLE as light function: i=%d, j=%d c_length=%ld, c_nargs=%ld, magic=%ld",
65169 (int) i,
65170 (int) j,
65171 (long) c_length,
65172 (long) c_nargs,
65173 (long) magic));
65174#endif /* DUK_USE_LIGHTFUNC_BUILTINS */
65175
65176 /* [ (builtin objects) name ] */
65177
65178 duk_push_c_function_builtin_noconstruct(thr, c_func, c_nargs);
65179 h_func = duk_known_hnatfunc(thr, -1);
65180 DUK_UNREF(h_func);
65181
65182 /* XXX: add into init data? */
65183
65184 /* Special call handling, not described in init data. */
65185 if (c_func == duk_bi_global_object_eval || c_func == duk_bi_function_prototype_call ||
65187 c_func == duk_bi_reflect_construct) {
65189 }
65190
65191 /* Currently all built-in native functions are strict.
65192 * This doesn't matter for many functions, but e.g.
65193 * String.prototype.charAt (and other string functions)
65194 * rely on being strict so that their 'this' binding is
65195 * not automatically coerced.
65196 */
65198
65199 /* No built-in functions are constructable except the top
65200 * level ones (Number, etc).
65201 */
65203
65204 /* XXX: any way to avoid decoding magic bit; there are quite
65205 * many function properties and relatively few with magic values.
65206 */
65207 h_func->magic = magic;
65208
65209 /* [ (builtin objects) name func ] */
65210
65211 duk_push_uint(thr, c_length);
65213
65214 duk_dup_m2(thr);
65216
65217 /* XXX: other properties of function instances; 'arguments', 'caller'. */
65218
65219 DUK_DD(DUK_DDPRINT("built-in object %ld, function property %ld -> %!T",
65220 (long) i,
65221 (long) j,
65222 (duk_tval *) duk_get_tval(thr, -1)));
65223
65224 /* [ (builtin objects) name func ] */
65225
65226 /*
65227 * The default property attributes are correct for all
65228 * function valued properties of built-in objects now.
65229 */
65230
65231#if defined(DUK_USE_LIGHTFUNC_BUILTINS)
65232 lightfunc_skip:
65233#endif
65234
65235 defprop_flags = (duk_small_uint_t) duk_bd_decode_flagged(bd,
65237 (duk_uint32_t) DUK_PROPDESC_FLAGS_WC);
65243
65244 duk_def_prop(thr, (duk_idx_t) i, defprop_flags);
65245
65246 /* [ (builtin objects) ] */
65247 }
65248 }
65249
65250 /*
65251 * Special post-tweaks, for cases not covered by the init data format.
65252 *
65253 * - Set Date.prototype.toGMTString to Date.prototype.toUTCString.
65254 * toGMTString is required to have the same Function object as
65255 * toUTCString in E5 Section B.2.6. Note that while Smjs respects
65256 * this, V8 does not (the Function objects are distinct).
65257 *
65258 * - Make DoubleError non-extensible.
65259 *
65260 * - Add info about most important effective compile options to Duktape.
65261 *
65262 * - Possibly remove some properties (values or methods) which are not
65263 * desirable with current feature options but are not currently
65264 * conditional in init data.
65265 */
65266
65267#if defined(DUK_USE_DATE_BUILTIN)
65270#endif
65271
65274
65275#if !defined(DUK_USE_ES6_OBJECT_PROTO_PROPERTY)
65276 DUK_DD(DUK_DDPRINT("delete Object.prototype.__proto__ built-in which is not enabled in features"));
65277 (void) duk_hobject_delprop_raw(thr,
65281#endif
65282
65283#if !defined(DUK_USE_ES6_OBJECT_SETPROTOTYPEOF)
65284 DUK_DD(DUK_DDPRINT("delete Object.setPrototypeOf built-in which is not enabled in features"));
65285 (void) duk_hobject_delprop_raw(thr,
65289#endif
65290
65291 /* XXX: relocate */
65292 duk_push_string(thr,
65293 /* Endianness indicator */
65294#if defined(DUK_USE_INTEGER_LE)
65295 "l"
65296#elif defined(DUK_USE_INTEGER_BE)
65297 "b"
65298#elif defined(DUK_USE_INTEGER_ME) /* integer mixed endian not really used now */
65299 "m"
65300#else
65301 "?"
65302#endif
65303#if defined(DUK_USE_DOUBLE_LE)
65304 "l"
65305#elif defined(DUK_USE_DOUBLE_BE)
65306 "b"
65307#elif defined(DUK_USE_DOUBLE_ME)
65308 "m"
65309#else
65310 "?"
65311#endif
65312 " "
65313 /* Packed or unpacked tval */
65314#if defined(DUK_USE_PACKED_TVAL)
65315 "p"
65316#else
65317 "u"
65318#endif
65319#if defined(DUK_USE_FASTINT)
65320 "f"
65321#endif
65322 " "
65323 /* Low memory/performance options */
65324#if defined(DUK_USE_STRTAB_PTRCOMP)
65325 "s"
65326#endif
65327#if !defined(DUK_USE_HEAPPTR16) && !defined(DUK_DATAPTR16) && !defined(DUK_FUNCPTR16)
65328 "n"
65329#endif
65330#if defined(DUK_USE_HEAPPTR16)
65331 "h"
65332#endif
65333#if defined(DUK_USE_DATAPTR16)
65334 "d"
65335#endif
65336#if defined(DUK_USE_FUNCPTR16)
65337 "f"
65338#endif
65339#if defined(DUK_USE_REFCOUNT16)
65340 "R"
65341#endif
65342#if defined(DUK_USE_STRHASH16)
65343 "H"
65344#endif
65345#if defined(DUK_USE_STRLEN16)
65346 "S"
65347#endif
65348#if defined(DUK_USE_BUFLEN16)
65349 "B"
65350#endif
65351#if defined(DUK_USE_OBJSIZES16)
65352 "O"
65353#endif
65354#if defined(DUK_USE_LIGHTFUNC_BUILTINS)
65355 "L"
65356#endif
65357#if defined(DUK_USE_ROM_STRINGS) || defined(DUK_USE_ROM_OBJECTS)
65358 /* XXX: This won't be shown in practice now
65359 * because this code is not run when builtins
65360 * are in ROM.
65361 */
65362 "Z"
65363#endif
65364#if defined(DUK_USE_LITCACHE_SIZE)
65365 "l"
65366#endif
65367 " "
65368 /* Object property allocation layout */
65369#if defined(DUK_USE_HOBJECT_LAYOUT_1)
65370 "p1"
65371#elif defined(DUK_USE_HOBJECT_LAYOUT_2)
65372 "p2"
65373#elif defined(DUK_USE_HOBJECT_LAYOUT_3)
65374 "p3"
65375#else
65376 "p?"
65377#endif
65378 " "
65379 /* Alignment guarantee */
65380#if (DUK_USE_ALIGN_BY == 4)
65381 "a4"
65382#elif (DUK_USE_ALIGN_BY == 8)
65383 "a8"
65384#elif (DUK_USE_ALIGN_BY == 1)
65385 "a1"
65386#else
65387#error invalid DUK_USE_ALIGN_BY
65388#endif
65389 " "
65390 /* Architecture, OS, and compiler strings */
65393
65394 /*
65395 * Since built-ins are not often extended, compact them.
65396 */
65397
65398 DUK_DD(DUK_DDPRINT("compact built-ins"));
65399 for (i = 0; i < DUK_NUM_ALL_BUILTINS; i++) {
65401 }
65402
65403 DUK_D(DUK_DPRINT("INITBUILTINS END"));
65404
65405#if defined(DUK_USE_DEBUG_LEVEL) && (DUK_USE_DEBUG_LEVEL >= 1)
65406 for (i = 0; i < DUK_NUM_ALL_BUILTINS; i++) {
65407 DUK_DD(DUK_DDPRINT("built-in object %ld after initialization and compacting: %!@iO",
65408 (long) i,
65410 }
65411#endif
65412
65413 /*
65414 * Pop built-ins from stack: they are now INCREF'd and
65415 * reachable from the builtins[] array or indirectly
65416 * through builtins[].
65417 */
65418
65419 duk_set_top(thr, 0);
65420 DUK_ASSERT_TOP(thr, 0);
65421}
65422#endif /* DUK_USE_ROM_OBJECTS */
65423
65426
65427 for (i = 0; i < DUK_NUM_BUILTINS; i++) {
65428 thr_to->builtins[i] = thr_from->builtins[i];
65429 DUK_HOBJECT_INCREF_ALLOWNULL(thr_to, thr_to->builtins[i]); /* side effect free */
65430 }
65431}
65433/* automatic undefs */
65434#undef DUK__LENGTH_PROP_BITS
65435#undef DUK__NARGS_BITS
65436#undef DUK__NARGS_VARARGS_MARKER
65437#undef DUK__PROP_FLAGS_BITS
65438#undef DUK__PROP_TYPE_ACCESSOR
65439#undef DUK__PROP_TYPE_BITS
65440#undef DUK__PROP_TYPE_BOOLEAN_FALSE
65441#undef DUK__PROP_TYPE_BOOLEAN_TRUE
65442#undef DUK__PROP_TYPE_BUILTIN
65443#undef DUK__PROP_TYPE_DOUBLE
65444#undef DUK__PROP_TYPE_STRIDX
65445#undef DUK__PROP_TYPE_STRING
65446#undef DUK__PROP_TYPE_UNDEFINED
65447/*
65448 * Thread support.
65449 */
65450
65451/* #include duk_internal.h -> already included */
65452
65454 DUK_ASSERT(thr != NULL);
65455
65456 while (thr->callstack_curr != NULL) {
65458 }
65459
65460 thr->valstack_bottom = thr->valstack;
65461 duk_set_top(thr, 0); /* unwinds valstack, updating refcounts */
65462
65464
65465 /* Here we could remove references to built-ins, but it may not be
65466 * worth the effort because built-ins are quite likely to be shared
65467 * with another (unterminated) thread, and terminated threads are also
65468 * usually garbage collected quite quickly.
65469 *
65470 * We could also shrink the value stack here, but that also may not
65471 * be worth the effort for the same reason.
65472 */
65475}
65476
65477#if defined(DUK_USE_DEBUGGER_SUPPORT)
65478DUK_INTERNAL duk_uint_fast32_t duk_hthread_get_act_curr_pc(duk_hthread *thr, duk_activation *act) {
65479 duk_instr_t *bcode;
65480
65481 DUK_ASSERT(thr != NULL);
65482 DUK_ASSERT(act != NULL);
65483 DUK_UNREF(thr);
65484
65485 /* XXX: store 'bcode' pointer to activation for faster lookup? */
65486 if (act->func && DUK_HOBJECT_IS_COMPFUNC(act->func)) {
65487 bcode = DUK_HCOMPFUNC_GET_CODE_BASE(thr->heap, (duk_hcompfunc *) (act->func));
65488 return (duk_uint_fast32_t) (act->curr_pc - bcode);
65489 }
65490 return 0;
65491}
65492#endif /* DUK_USE_DEBUGGER_SUPPORT */
65495 duk_instr_t *bcode;
65497
65498 DUK_ASSERT(thr != NULL);
65499 DUK_ASSERT(act != NULL);
65500 DUK_UNREF(thr);
65501
65502 if (act->func && DUK_HOBJECT_IS_COMPFUNC(act->func)) {
65503 bcode = DUK_HCOMPFUNC_GET_CODE_BASE(thr->heap, (duk_hcompfunc *) (act->func));
65504 ret = (duk_uint_fast32_t) (act->curr_pc - bcode);
65505 if (ret > 0) {
65506 ret--;
65507 }
65508 return ret;
65509 }
65510 return 0;
65511}
65512
65513/* Write bytecode executor's curr_pc back to topmost activation (if any). */
65515 duk_activation *act;
65516
65517 DUK_ASSERT(thr != NULL);
65518
65519 if (thr->ptr_curr_pc != NULL) {
65520 /* ptr_curr_pc != NULL only when bytecode executor is active. */
65521 DUK_ASSERT(thr->callstack_top > 0);
65522 DUK_ASSERT(thr->callstack_curr != NULL);
65523 act = thr->callstack_curr;
65524 DUK_ASSERT(act != NULL);
65525 act->curr_pc = *thr->ptr_curr_pc;
65526 }
65527}
65528
65530 duk_activation *act;
65531
65532 DUK_ASSERT(thr != NULL);
65533
65534 if (thr->ptr_curr_pc != NULL) {
65535 /* ptr_curr_pc != NULL only when bytecode executor is active. */
65536 DUK_ASSERT(thr->callstack_top > 0);
65537 DUK_ASSERT(thr->callstack_curr != NULL);
65538 act = thr->callstack_curr;
65539 DUK_ASSERT(act != NULL);
65540 act->curr_pc = *thr->ptr_curr_pc;
65541 thr->ptr_curr_pc = NULL;
65542 }
65543}
65544/*
65545 * Thread stack (mainly call stack) primitives: allocation of activations,
65546 * unwinding catchers and activations, etc.
65547 *
65548 * Value stack handling is a part of the API implementation.
65549 */
65550
65551/* #include duk_internal.h -> already included */
65552
65553/* Unwind the topmost catcher of the current activation (caller must check that
65554 * both exist) without side effects.
65555 */
65557 duk_catcher *cat;
65558
65559 DUK_ASSERT(thr != NULL);
65560 DUK_ASSERT(act != NULL);
65561 DUK_ASSERT(act->cat != NULL); /* caller must check */
65562 cat = act->cat;
65563 DUK_ASSERT(cat != NULL);
65564
65565 DUK_DDD(DUK_DDDPRINT("unwinding catch stack entry %p (lexenv check is done)", (void *) cat));
65566
65567 if (DUK_CAT_HAS_LEXENV_ACTIVE(cat)) {
65568 duk_hobject *env;
65569
65570 env = act->lex_env; /* current lex_env of the activation (created for catcher) */
65571 DUK_ASSERT(env != NULL); /* must be, since env was created when catcher was created */
65572 act->lex_env = DUK_HOBJECT_GET_PROTOTYPE(thr->heap, env); /* prototype is lex_env before catcher created */
65573 DUK_HOBJECT_INCREF(thr, act->lex_env);
65574 DUK_HOBJECT_DECREF_NORZ(thr, env);
65575
65576 /* There is no need to decref anything else than 'env': if 'env'
65577 * becomes unreachable, refzero will handle decref'ing its prototype.
65578 */
65579 }
65580
65581 act->cat = cat->parent;
65582 duk_hthread_catcher_free(thr, cat);
65583}
65584
65585/* Same as above, but caller is certain no catcher-related lexenv may exist. */
65587 duk_catcher *cat;
65588
65589 DUK_ASSERT(thr != NULL);
65590 DUK_ASSERT(act != NULL);
65591 DUK_ASSERT(act->cat != NULL); /* caller must check */
65592 cat = act->cat;
65593 DUK_ASSERT(cat != NULL);
65594
65595 DUK_DDD(DUK_DDDPRINT("unwinding catch stack entry %p (lexenv check is not done)", (void *) cat));
65596
65598
65599 act->cat = cat->parent;
65600 duk_hthread_catcher_free(thr, cat);
65601}
65602
65604#if defined(DUK_USE_CACHE_CATCHER)
65606#endif
65608 duk_catcher *cat;
65609
65610 cat = (duk_catcher *) DUK_ALLOC_CHECKED(thr, sizeof(duk_catcher));
65611 DUK_ASSERT(cat != NULL);
65612 return cat;
65613}
65615#if defined(DUK_USE_CACHE_CATCHER)
65617 duk_catcher *cat;
65618
65619 DUK_ASSERT(thr != NULL);
65620
65621 cat = thr->heap->catcher_free;
65622 if (DUK_LIKELY(cat != NULL)) {
65623 thr->heap->catcher_free = cat->parent;
65624 return cat;
65625 }
65626
65628}
65629#else /* DUK_USE_CACHE_CATCHER */
65632}
65633#endif /* DUK_USE_CACHE_CATCHER */
65634
65636 DUK_ASSERT(thr != NULL);
65637 DUK_ASSERT(cat != NULL);
65638
65639#if defined(DUK_USE_CACHE_CATCHER)
65640 /* Unconditional caching for now; freed in mark-and-sweep. */
65641 cat->parent = thr->heap->catcher_free;
65642 thr->heap->catcher_free = cat;
65643#else
65644 DUK_FREE_CHECKED(thr, (void *) cat);
65645#endif
65646}
65647
65649#if defined(DUK_USE_CACHE_ACTIVATION)
65651#endif
65653 duk_activation *act;
65654
65655 act = (duk_activation *) DUK_ALLOC_CHECKED(thr, sizeof(duk_activation));
65656 DUK_ASSERT(act != NULL);
65657 return act;
65658}
65660#if defined(DUK_USE_CACHE_ACTIVATION)
65662 duk_activation *act;
65663
65664 DUK_ASSERT(thr != NULL);
65665
65666 act = thr->heap->activation_free;
65667 if (DUK_LIKELY(act != NULL)) {
65668 thr->heap->activation_free = act->parent;
65669 return act;
65670 }
65671
65673}
65674#else /* DUK_USE_CACHE_ACTIVATION */
65677}
65678#endif /* DUK_USE_CACHE_ACTIVATION */
65679
65681 DUK_ASSERT(thr != NULL);
65682 DUK_ASSERT(act != NULL);
65683
65684#if defined(DUK_USE_CACHE_ACTIVATION)
65685 /* Unconditional caching for now; freed in mark-and-sweep. */
65686 act->parent = thr->heap->activation_free;
65687 thr->heap->activation_free = act;
65688#else
65689 DUK_FREE_CHECKED(thr, (void *) act);
65690#endif
65691}
65692
65693/* Internal helper: process the unwind for the topmost activation of a thread,
65694 * but leave the duk_activation in place for possible tailcall reuse.
65695 */
65697#if defined(DUK_USE_DEBUGGER_SUPPORT)
65698 duk_heap *heap;
65699#endif
65700 duk_activation *act;
65701 duk_hobject *func;
65702 duk_hobject *tmp;
65703
65704 DUK_ASSERT(thr != NULL);
65705 DUK_ASSERT(thr->callstack_curr != NULL); /* caller must check */
65706 DUK_ASSERT(thr->callstack_top > 0);
65707 act = thr->callstack_curr;
65708 DUK_ASSERT(act != NULL);
65709 /* With lightfuncs, act 'func' may be NULL. */
65710
65711 /* With duk_activation records allocated separately, 'act' is a stable
65712 * pointer and not affected by side effects.
65713 */
65714
65715#if defined(DUK_USE_NONSTD_FUNC_CALLER_PROPERTY)
65716 /*
65717 * Restore 'caller' property for non-strict callee functions.
65718 */
65719
65720 func = DUK_ACT_GET_FUNC(act);
65721 if (func != NULL && !DUK_HOBJECT_HAS_STRICT(func)) {
65722 duk_tval *tv_caller;
65723 duk_tval tv_tmp;
65724 duk_hobject *h_tmp;
65725
65727
65728 /* The act->prev_caller should only be set if the entry for 'caller'
65729 * exists (as it is only set in that case, and the property is not
65730 * configurable), but handle all the cases anyway.
65731 */
65732
65733 if (tv_caller) {
65734 DUK_TVAL_SET_TVAL(&tv_tmp, tv_caller);
65735 if (act->prev_caller) {
65736 /* Just transfer the refcount from act->prev_caller to tv_caller,
65737 * so no need for a refcount update. This is the expected case.
65738 */
65739 DUK_TVAL_SET_OBJECT(tv_caller, act->prev_caller);
65740 act->prev_caller = NULL;
65741 } else {
65742 DUK_TVAL_SET_NULL(tv_caller); /* no incref needed */
65743 DUK_ASSERT(act->prev_caller == NULL);
65744 }
65745 DUK_TVAL_DECREF_NORZ(thr, &tv_tmp);
65746 } else {
65747 h_tmp = act->prev_caller;
65748 if (h_tmp) {
65749 act->prev_caller = NULL;
65750 DUK_HOBJECT_DECREF_NORZ(thr, h_tmp);
65751 }
65752 }
65753 DUK_ASSERT(act->prev_caller == NULL);
65754 }
65755#endif
65756
65757 /*
65758 * Unwind debugger state. If we unwind while stepping
65759 * (for any step type), pause execution. This is the
65760 * only place explicitly handling a step out.
65761 */
65762
65763#if defined(DUK_USE_DEBUGGER_SUPPORT)
65764 heap = thr->heap;
65765 if (heap->dbg_pause_act == thr->callstack_curr) {
65766 if (heap->dbg_pause_flags & DUK_PAUSE_FLAG_FUNC_EXIT) {
65767 DUK_D(DUK_DPRINT("PAUSE TRIGGERED by function exit"));
65768 duk_debug_set_paused(heap);
65769 } else {
65770 DUK_D(DUK_DPRINT("unwound past dbg_pause_act, set to NULL"));
65771 heap->dbg_pause_act = NULL; /* avoid stale pointers */
65772 }
65773 DUK_ASSERT(heap->dbg_pause_act == NULL);
65774 }
65775#endif
65776
65777 /*
65778 * Unwind catchers.
65779 *
65780 * Since there are no references in the catcher structure,
65781 * unwinding is quite simple. The only thing we need to
65782 * look out for is popping a possible lexical environment
65783 * established for an active catch clause.
65784 */
65785
65786 while (act->cat != NULL) {
65788 }
65789
65790 /*
65791 * Close environment record(s) if they exist.
65792 *
65793 * Only variable environments are closed. If lex_env != var_env, it
65794 * cannot currently contain any register bound declarations.
65795 *
65796 * Only environments created for a NEWENV function are closed. If an
65797 * environment is created for e.g. an eval call, it must not be closed.
65798 */
65799
65800 func = DUK_ACT_GET_FUNC(act);
65801 if (func != NULL && !DUK_HOBJECT_HAS_NEWENV(func)) {
65802 DUK_DDD(DUK_DDDPRINT("skip closing environments, envs not owned by this activation"));
65803 goto skip_env_close;
65804 }
65805 /* func is NULL for lightfunc */
65806
65807 /* Catch sites are required to clean up their environments
65808 * in FINALLY part before propagating, so this should
65809 * always hold here.
65810 */
65811 DUK_ASSERT(act->lex_env == act->var_env);
65812
65813 /* XXX: Closing the environment record copies values from registers
65814 * into the scope object. It's side effect free as such, but may
65815 * currently run out of memory which causes an error throw. This is
65816 * an actual sandboxing problem for error unwinds, and needs to be
65817 * fixed e.g. by preallocating the scope property slots.
65818 */
65819 if (act->var_env != NULL) {
65820 DUK_DDD(DUK_DDDPRINT("closing var_env record %p -> %!O", (void *) act->var_env, (duk_heaphdr *) act->var_env));
65822 }
65823
65824skip_env_close:
65825
65826 /*
65827 * Update preventcount
65828 */
65829
65830 if (act->flags & DUK_ACT_FLAG_PREVENT_YIELD) {
65833 }
65835 /*
65836 * Reference count updates, using NORZ macros so we don't
65837 * need to handle side effects.
65838 *
65839 * duk_activation pointers like act->var_env are intentionally
65840 * left as garbage and not NULLed. Without side effects they
65841 * can't be used when the values are dangling/garbage.
65842 */
65843
65846 tmp = DUK_ACT_GET_FUNC(act);
65848 DUK_UNREF(tmp);
65849}
65850
65851/* Unwind topmost duk_activation of a thread, caller must ensure that an
65852 * activation exists. The call is side effect free, except that scope
65853 * closure may currently throw an out-of-memory error.
65854 */
65856 duk_activation *act;
65857
65860 DUK_ASSERT(thr->callstack_curr != NULL);
65861 DUK_ASSERT(thr->callstack_top > 0);
65862 act = thr->callstack_curr;
65863 thr->callstack_curr = act->parent;
65864 thr->callstack_top--;
65865
65866 /* Ideally we'd restore value stack reserve here to caller's value.
65867 * This doesn't work for current unwind call sites however, because
65868 * the current (unwound) value stack top may be above the reserve.
65869 * Thus value stack reserve is restored by the call sites.
65870 */
65871
65872 /* XXX: inline for performance builds? */
65874
65875 /* We could clear the book-keeping variables like retval_byteoff for
65876 * the topmost activation, but don't do so now as it's not necessary.
65877 */
65878}
65879
65882}
65883
65884/* Get duk_activation for given callstack level or NULL if level is invalid
65885 * or deeper than the call stack. Level -1 refers to current activation, -2
65886 * to its caller, etc. Starting from Duktape 2.2 finding the activation is
65887 * a linked list scan which gets more expensive the deeper the lookup is.
65888 */
65890 duk_activation *act;
65891
65892 if (level >= 0) {
65893 return NULL;
65894 }
65895 act = thr->callstack_curr;
65896 for (;;) {
65897 if (act == NULL) {
65898 return act;
65899 }
65900 if (level == -1) {
65901 return act;
65902 }
65903 level++;
65904 act = act->parent;
65905 }
65906 /* never here */
65907}
65908
65909#if defined(DUK_USE_FINALIZER_TORTURE)
65910DUK_INTERNAL void duk_hthread_valstack_torture_realloc(duk_hthread *thr) {
65911 duk_size_t alloc_size;
65912 duk_tval *new_ptr;
65913 duk_ptrdiff_t alloc_end_off;
65914 duk_ptrdiff_t end_off;
65915 duk_ptrdiff_t bottom_off;
65916 duk_ptrdiff_t top_off;
65917
65918 if (thr->valstack == NULL) {
65919 DUK_D(DUK_DPRINT("skip valstack torture realloc, valstack is NULL"));
65920 return;
65921 }
65922
65923 alloc_end_off = (duk_ptrdiff_t) ((duk_uint8_t *) thr->valstack_alloc_end - (duk_uint8_t *) thr->valstack);
65924 end_off = (duk_ptrdiff_t) ((duk_uint8_t *) thr->valstack_end - (duk_uint8_t *) thr->valstack);
65925 bottom_off = (duk_ptrdiff_t) ((duk_uint8_t *) thr->valstack_bottom - (duk_uint8_t *) thr->valstack);
65926 top_off = (duk_ptrdiff_t) ((duk_uint8_t *) thr->valstack_top - (duk_uint8_t *) thr->valstack);
65927 alloc_size = (duk_size_t) alloc_end_off;
65928 if (alloc_size == 0) {
65929 DUK_D(DUK_DPRINT("skip valstack torture realloc, alloc_size is zero"));
65930 return;
65931 }
65932
65933 /* Use DUK_ALLOC_RAW() to avoid side effects. */
65934 new_ptr = (duk_tval *) DUK_ALLOC_RAW(thr->heap, alloc_size);
65935 if (new_ptr != NULL) {
65936 duk_memcpy((void *) new_ptr, (const void *) thr->valstack, alloc_size);
65937 duk_memset((void *) thr->valstack, 0x55, alloc_size);
65938 DUK_FREE_CHECKED(thr, (void *) thr->valstack);
65939 thr->valstack = new_ptr;
65940 thr->valstack_alloc_end = (duk_tval *) ((duk_uint8_t *) new_ptr + alloc_end_off);
65941 thr->valstack_end = (duk_tval *) ((duk_uint8_t *) new_ptr + end_off);
65942 thr->valstack_bottom = (duk_tval *) ((duk_uint8_t *) new_ptr + bottom_off);
65943 thr->valstack_top = (duk_tval *) ((duk_uint8_t *) new_ptr + top_off);
65944 } else {
65945 DUK_D(DUK_DPRINT("failed to realloc valstack for torture, ignore"));
65946 }
65947}
65948#endif /* DUK_USE_FINALIZER_TORTURE */
65949/*
65950 * Shared helpers for arithmetic operations
65951 */
65952
65953/* #include duk_internal.h -> already included */
65954
65955/* ECMAScript modulus ('%') does not match IEEE 754 "remainder" operation
65956 * (implemented by remainder() in C99) but does seem to match ANSI C fmod().
65957 * Compare E5 Section 11.5.3 and "man fmod".
65958 */
65959DUK_INTERNAL double duk_js_arith_mod(double d1, double d2) {
65960#if defined(DUK_USE_POW_WORKAROUNDS)
65961 /* Specific fixes to common fmod() implementation issues:
65962 * - test-bug-mingw-math-issues.js
65963 */
65964 if (DUK_ISINF(d2)) {
65965 if (DUK_ISINF(d1)) {
65966 return DUK_DOUBLE_NAN;
65967 } else {
65968 return d1;
65969 }
65970 } else if (duk_double_equals(d1, 0.0)) {
65971 /* d1 +/-0 is returned as is (preserving sign) except when
65972 * d2 is zero or NaN.
65973 */
65974 if (duk_double_equals(d2, 0.0) || DUK_ISNAN(d2)) {
65975 return DUK_DOUBLE_NAN;
65976 } else {
65977 return d1;
65978 }
65979 }
65980#else
65981 /* Some ISO C assumptions. */
65990 DUK_ASSERT(duk_double_equals(DUK_FMOD(0.0, 1.0), 0.0) && DUK_SIGNBIT(DUK_FMOD(0.0, 1.0)) == 0);
65991 DUK_ASSERT(duk_double_equals(DUK_FMOD(-0.0, 1.0), 0.0) && DUK_SIGNBIT(DUK_FMOD(-0.0, 1.0)) != 0);
66000 DUK_ASSERT(DUK_ISNAN(DUK_FMOD(0.0, 0.0)));
66001 DUK_ASSERT(DUK_ISNAN(DUK_FMOD(-0.0, 0.0)));
66002 DUK_ASSERT(DUK_ISNAN(DUK_FMOD(0.0, -0.0)));
66003 DUK_ASSERT(DUK_ISNAN(DUK_FMOD(-0.0, -0.0)));
66006#endif
66007
66008 return (duk_double_t) DUK_FMOD((double) d1, (double) d2);
66009}
66010
66011/* Shared helper for Math.pow() and exponentiation operator. */
66012DUK_INTERNAL double duk_js_arith_pow(double x, double y) {
66013 /* The ANSI C pow() semantics differ from ECMAScript.
66014 *
66015 * E.g. when x==1 and y is +/- infinite, the ECMAScript required
66016 * result is NaN, while at least Linux pow() returns 1.
66017 */
66018
66019 duk_small_int_t cx, cy, sx;
66020
66021 DUK_UNREF(cx);
66022 DUK_UNREF(sx);
66024
66025 if (cy == DUK_FP_NAN) {
66026 goto ret_nan;
66027 }
66028 if (duk_double_equals(DUK_FABS(x), 1.0) && cy == DUK_FP_INFINITE) {
66029 goto ret_nan;
66030 }
66031
66032#if defined(DUK_USE_POW_WORKAROUNDS)
66033 /* Specific fixes to common pow() implementation issues:
66034 * - test-bug-netbsd-math-pow.js: NetBSD 6.0 on x86 (at least)
66035 * - test-bug-mingw-math-issues.js
66036 */
66038 if (cx == DUK_FP_ZERO && y < 0.0) {
66039 sx = (duk_small_int_t) DUK_SIGNBIT(x);
66040 if (sx == 0) {
66041 /* Math.pow(+0,y) should be Infinity when y<0. NetBSD pow()
66042 * returns -Infinity instead when y is <0 and finite. The
66043 * if-clause also catches y == -Infinity (which works even
66044 * without the fix).
66045 */
66046 return DUK_DOUBLE_INFINITY;
66047 } else {
66048 /* Math.pow(-0,y) where y<0 should be:
66049 * - -Infinity if y<0 and an odd integer
66050 * - Infinity if y<0 but not an odd integer
66051 * NetBSD pow() returns -Infinity for all finite y<0. The
66052 * if-clause also catches y == -Infinity (which works even
66053 * without the fix).
66054 */
66055
66056 /* fmod() return value has same sign as input (negative) so
66057 * the result here will be in the range ]-2,0], -1 indicates
66058 * odd. If x is -Infinity, NaN is returned and the odd check
66059 * always concludes "not odd" which results in desired outcome.
66060 */
66061 double tmp = DUK_FMOD(y, 2);
66062 if (tmp == -1.0) {
66063 return -DUK_DOUBLE_INFINITY;
66064 } else {
66065 /* Not odd, or y == -Infinity */
66066 return DUK_DOUBLE_INFINITY;
66067 }
66068 }
66069 } else if (cx == DUK_FP_NAN) {
66070 if (duk_double_equals(y, 0.0)) {
66071 /* NaN ** +/- 0 should always be 1, but is NaN on
66072 * at least some Cygwin/MinGW versions.
66073 */
66074 return 1.0;
66075 }
66076 }
66077#else
66078 /* Some ISO C assumptions. */
66080 DUK_ASSERT(DUK_ISINF(DUK_POW(0.0, -1.0)) && DUK_SIGNBIT(DUK_POW(0.0, -1.0)) == 0);
66081 DUK_ASSERT(DUK_ISINF(DUK_POW(-0.0, -2.0)) && DUK_SIGNBIT(DUK_POW(-0.0, -2.0)) == 0);
66082 DUK_ASSERT(DUK_ISINF(DUK_POW(-0.0, -3.0)) && DUK_SIGNBIT(DUK_POW(-0.0, -3.0)) != 0);
66083#endif
66084
66085 return DUK_POW(x, y);
66086
66087ret_nan:
66088 return DUK_DOUBLE_NAN;
66089}
66090/*
66091 * Call handling.
66092 *
66093 * duk_handle_call_unprotected():
66094 *
66095 * - Unprotected call to ECMAScript or Duktape/C function, from native
66096 * code or bytecode executor.
66097 *
66098 * - Also handles Ecma-to-Ecma calls which reuses a currently running
66099 * executor instance to avoid native recursion. Call setup is done
66100 * normally, but just before calling the bytecode executor a special
66101 * return code is used to indicate that a calling executor is reused.
66102 *
66103 * - Also handles tailcalls, i.e. reuse of current duk_activation.
66104 *
66105 * - Also handles setup for initial Duktape.Thread.resume().
66106 *
66107 * duk_handle_safe_call():
66108 *
66109 * - Protected C call within current activation.
66110 *
66111 * setjmp() and local variables have a nasty interaction, see execution.rst;
66112 * non-volatile locals modified after setjmp() call are not guaranteed to
66113 * keep their value and can cause compiler or compiler version specific
66114 * difficult to replicate issues.
66115 *
66116 * See 'execution.rst'.
66117 */
66118
66119/* #include duk_internal.h -> already included */
66120
66121/* XXX: heap->error_not_allowed for success path too? */
66123/*
66124 * Limit check helpers.
66126
66127/* Check native stack space if DUK_USE_NATIVE_STACK_CHECK() defined. */
66129#if defined(DUK_USE_NATIVE_STACK_CHECK)
66130 if (DUK_USE_NATIVE_STACK_CHECK() != 0) {
66132 }
66133#else
66134 DUK_UNREF(thr);
66135#endif
66136}
66137
66138/* Allow headroom for calls during error augmentation (see GH-191).
66139 * We allow space for 10 additional recursions, with one extra
66140 * for, e.g. a print() call at the deepest level, and an extra
66141 * +1 for protected call wrapping.
66142 */
66143#define DUK__AUGMENT_CALL_RELAX_COUNT (10 + 2)
66144
66145/* Stack space required by call handling entry. */
66146#define DUK__CALL_HANDLING_REQUIRE_STACK 8
66147
66149 /* When augmenting an error, the effective limit is a bit higher.
66150 * Check for it only if the fast path check fails.
66151 */
66152#if defined(DUK_USE_AUGMENT_ERROR_THROW) || defined(DUK_USE_AUGMENT_ERROR_CREATE)
66153 if (thr->heap->augmenting_error) {
66155 DUK_D(DUK_DPRINT("C recursion limit reached but augmenting error and within relaxed limit"));
66156 return;
66157 }
66158 }
66159#endif
66160
66161 DUK_D(DUK_DPRINT("call prevented because C recursion limit reached"));
66163 DUK_WO_NORETURN(return;);
66164}
66165
66169
66171
66172 /* This check is forcibly inlined because it's very cheap and almost
66173 * always passes. The slow path is forcibly noinline.
66174 */
66176 return;
66177 }
66178
66180}
66181
66183 /* When augmenting an error, the effective limit is a bit higher.
66184 * Check for it only if the fast path check fails.
66185 */
66186#if defined(DUK_USE_AUGMENT_ERROR_THROW) || defined(DUK_USE_AUGMENT_ERROR_CREATE)
66187 if (thr->heap->augmenting_error) {
66189 DUK_D(DUK_DPRINT("call stack limit reached but augmenting error and within relaxed limit"));
66190 return;
66191 }
66192 }
66193#endif
66194
66195 /* XXX: error message is a bit misleading: we reached a recursion
66196 * limit which is also essentially the same as a C callstack limit
66197 * (except perhaps with some relaxed threading assumptions).
66198 */
66199 DUK_D(DUK_DPRINT("call prevented because call stack limit reached"));
66201 DUK_WO_NORETURN(return;);
66202}
66203
66205 /* This check is forcibly inlined because it's very cheap and almost
66206 * always passes. The slow path is forcibly noinline.
66207 */
66209 return;
66210 }
66211
66213}
66214
66215/*
66216 * Interrupt counter fixup (for development only).
66217 */
66218
66219#if defined(DUK_USE_INTERRUPT_COUNTER) && defined(DUK_USE_DEBUG)
66220DUK_LOCAL void duk__interrupt_fixup(duk_hthread *thr, duk_hthread *entry_curr_thread) {
66221 /* Currently the bytecode executor and executor interrupt
66222 * instruction counts are off because we don't execute the
66223 * interrupt handler when we're about to exit from the initial
66224 * user call into Duktape.
66225 *
66226 * If we were to execute the interrupt handler here, the counts
66227 * would match. You can enable this block manually to check
66228 * that this is the case.
66229 */
66230
66231 DUK_ASSERT(thr != NULL);
66232 DUK_ASSERT(thr->heap != NULL);
66233
66234#if defined(DUK_USE_INTERRUPT_DEBUG_FIXUP)
66235 if (entry_curr_thread == NULL) {
66237 thr->heap->inst_count_interrupt += thr->interrupt_init;
66238 DUK_DD(DUK_DDPRINT("debug test: updated interrupt count on exit to "
66239 "user code, instruction counts: executor=%ld, interrupt=%ld",
66240 (long) thr->heap->inst_count_exec,
66241 (long) thr->heap->inst_count_interrupt));
66242 DUK_ASSERT(thr->heap->inst_count_exec == thr->heap->inst_count_interrupt);
66243 }
66244#else
66245 DUK_UNREF(thr);
66246 DUK_UNREF(entry_curr_thread);
66247#endif
66248}
66249#endif
66250
66251/*
66252 * Arguments object creation.
66253 *
66254 * Creating arguments objects involves many small details, see E5 Section
66255 * 10.6 for the specific requirements. Much of the arguments object exotic
66256 * behavior is implemented in duk_hobject_props.c, and is enabled by the
66257 * object flag DUK_HOBJECT_FLAG_EXOTIC_ARGUMENTS.
66258 */
66259
66261 duk_hobject *arg; /* 'arguments' */
66262 duk_hobject *formals; /* formals for 'func' (may be NULL if func is a C function) */
66263 duk_idx_t i_arg;
66264 duk_idx_t i_map;
66265 duk_idx_t i_mappednames;
66266 duk_idx_t i_formals;
66267 duk_idx_t i_argbase;
66268 duk_idx_t n_formals;
66269 duk_idx_t idx;
66270 duk_idx_t num_stack_args;
66271 duk_bool_t need_map;
66272
66273 DUK_ASSERT(thr != NULL);
66274 DUK_ASSERT(func != NULL);
66276 DUK_ASSERT(varenv != NULL);
66277
66278 /* [ ... func this arg1(@idx_args) ... argN envobj ]
66279 * [ arg1(@idx_args) ... argN envobj ] (for tailcalls)
66280 */
66281
66282 need_map = 0;
66283
66284 i_argbase = idx_args;
66285 num_stack_args = duk_get_top(thr) - i_argbase - 1;
66286 DUK_ASSERT(i_argbase >= 0);
66287 DUK_ASSERT(num_stack_args >= 0);
66288
66289 formals = (duk_hobject *) duk_hobject_get_formals(thr, (duk_hobject *) func);
66290 if (formals) {
66291 n_formals = (duk_idx_t) ((duk_harray *) formals)->length;
66292 duk_push_hobject(thr, formals);
66293 } else {
66294 /* This shouldn't happen without tampering of internal
66295 * properties: if a function accesses 'arguments', _Formals
66296 * is kept. Check for the case anyway in case internal
66297 * properties have been modified manually.
66298 */
66299 DUK_D(DUK_DPRINT("_Formals is undefined when creating arguments, use n_formals == 0"));
66300 n_formals = 0;
66301 duk_push_undefined(thr);
66302 }
66303 i_formals = duk_require_top_index(thr);
66304
66305 DUK_ASSERT(n_formals >= 0);
66306 DUK_ASSERT(formals != NULL || n_formals == 0);
66307
66308 DUK_DDD(
66309 DUK_DDDPRINT("func=%!O, formals=%!O, n_formals=%ld", (duk_heaphdr *) func, (duk_heaphdr *) formals, (long) n_formals));
66310
66311 /* [ ... formals ] */
66312
66313 /*
66314 * Create required objects:
66315 * - 'arguments' object: array-like, but not an array
66316 * - 'map' object: internal object, tied to 'arguments' (bare)
66317 * - 'mappedNames' object: temporary value used during construction (bare)
66318 */
66319
66320 arg = duk_push_object_helper(thr,
66324 DUK_ASSERT(arg != NULL);
66325 (void) duk_push_object_helper(thr,
66328 -1); /* no prototype */
66329 (void) duk_push_object_helper(thr,
66332 -1); /* no prototype */
66333 i_arg = duk_get_top(thr) - 3;
66334 i_map = i_arg + 1;
66335 i_mappednames = i_arg + 2;
66336 DUK_ASSERT(!duk_is_bare_object(thr, -3)); /* arguments */
66337 DUK_ASSERT(duk_is_bare_object(thr, -2)); /* map */
66338 DUK_ASSERT(duk_is_bare_object(thr, -1)); /* mappedNames */
66339
66340 /* [ ... formals arguments map mappedNames ] */
66341
66342 DUK_DDD(DUK_DDDPRINT("created arguments related objects: "
66343 "arguments at index %ld -> %!O "
66344 "map at index %ld -> %!O "
66345 "mappednames at index %ld -> %!O",
66346 (long) i_arg,
66347 (duk_heaphdr *) duk_get_hobject(thr, i_arg),
66348 (long) i_map,
66349 (duk_heaphdr *) duk_get_hobject(thr, i_map),
66350 (long) i_mappednames,
66351 (duk_heaphdr *) duk_get_hobject(thr, i_mappednames)));
66352
66353 /*
66354 * Init arguments properties, map, etc.
66355 */
66356
66357 duk_push_int(thr, num_stack_args);
66359
66360 /*
66361 * Init argument related properties.
66362 */
66363
66364 /* step 11 */
66365 idx = num_stack_args - 1;
66366 while (idx >= 0) {
66367 DUK_DDD(
66368 DUK_DDDPRINT("arg idx %ld, argbase=%ld, argidx=%ld", (long) idx, (long) i_argbase, (long) (i_argbase + idx)));
66369
66370 DUK_DDD(DUK_DDDPRINT("define arguments[%ld]=arg", (long) idx));
66371 duk_dup(thr, i_argbase + idx);
66372 duk_xdef_prop_index_wec(thr, i_arg, (duk_uarridx_t) idx);
66373 DUK_DDD(DUK_DDDPRINT("defined arguments[%ld]=arg", (long) idx));
66374
66375 /* step 11.c is relevant only if non-strict (checked in 11.c.ii) */
66376 if (!DUK_HOBJECT_HAS_STRICT(func) && idx < n_formals) {
66377 DUK_ASSERT(formals != NULL);
66378
66379 DUK_DDD(DUK_DDDPRINT("strict function, index within formals (%ld < %ld)", (long) idx, (long) n_formals));
66380
66381 duk_get_prop_index(thr, i_formals, (duk_uarridx_t) idx);
66382 DUK_ASSERT(duk_is_string(thr, -1));
66383
66384 duk_dup_top(thr); /* [ ... name name ] */
66385
66386 if (!duk_has_prop(thr, i_mappednames)) {
66387 /* steps 11.c.ii.1 - 11.c.ii.4, but our internal book-keeping
66388 * differs from the reference model
66389 */
66390
66391 /* [ ... name ] */
66392
66393 need_map = 1;
66394
66395 DUK_DDD(
66396 DUK_DDDPRINT("set mappednames[%s]=%ld", (const char *) duk_get_string(thr, -1), (long) idx));
66397 duk_dup_top(thr); /* name */
66398 (void) duk_push_uint_to_hstring(thr, (duk_uint_t) idx); /* index */
66399 duk_xdef_prop_wec(thr, i_mappednames); /* out of spec, must be configurable */
66400
66401 DUK_DDD(DUK_DDDPRINT("set map[%ld]=%s", (long) idx, duk_get_string(thr, -1)));
66402 duk_dup_top(thr); /* name */
66403 duk_xdef_prop_index_wec(thr, i_map, (duk_uarridx_t) idx); /* out of spec, must be configurable */
66404 } else {
66405 /* duk_has_prop() popped the second 'name' */
66406 }
66407
66408 /* [ ... name ] */
66409 duk_pop(thr); /* pop 'name' */
66410 }
66411
66412 idx--;
66413 }
66414
66415 DUK_DDD(DUK_DDDPRINT("actual arguments processed"));
66416
66417 /* step 12 */
66418 if (need_map) {
66419 DUK_DDD(DUK_DDDPRINT("adding 'map' and 'varenv' to arguments object"));
66420
66421 /* should never happen for a strict callee */
66423
66424 duk_dup(thr, i_map);
66425 duk_xdef_prop_stridx(thr, i_arg, DUK_STRIDX_INT_MAP, DUK_PROPDESC_FLAGS_NONE); /* out of spec, don't care */
66426
66427 /* The variable environment for magic variable bindings needs to be
66428 * given by the caller and recorded in the arguments object.
66429 *
66430 * See E5 Section 10.6, the creation of setters/getters.
66431 *
66432 * The variable environment also provides access to the callee, so
66433 * an explicit (internal) callee property is not needed.
66434 */
66435
66436 duk_push_hobject(thr, varenv);
66437 duk_xdef_prop_stridx(thr, i_arg, DUK_STRIDX_INT_VARENV, DUK_PROPDESC_FLAGS_NONE); /* out of spec, don't care */
66438 }
66439
66440 /* steps 13-14 */
66441 if (DUK_HOBJECT_HAS_STRICT(func)) {
66442 /* Callee/caller are throwers and are not deletable etc. They
66443 * could be implemented as virtual properties, but currently
66444 * there is no support for virtual properties which are accessors
66445 * (only plain virtual properties). This would not be difficult
66446 * to change in duk_hobject_props, but we can make the throwers
66447 * normal, concrete properties just as easily.
66448 *
66449 * Note that the specification requires that the *same* thrower
66450 * built-in object is used here! See E5 Section 10.6 main
66451 * algoritm, step 14, and Section 13.2.3 which describes the
66452 * thrower. See test case test-arguments-throwers.js.
66453 */
66454
66455 DUK_DDD(DUK_DDDPRINT("strict function, setting caller/callee to throwers"));
66456
66457 /* In ES2017 .caller is no longer set at all. */
66459 } else {
66460 DUK_DDD(DUK_DDDPRINT("non-strict function, setting callee to actual value"));
66461 duk_push_hobject(thr, func);
66463 }
66464
66465 /* set exotic behavior only after we're done */
66466 if (need_map) {
66467 /* Exotic behaviors are only enabled for arguments objects
66468 * which have a parameter map (see E5 Section 10.6 main
66469 * algorithm, step 12).
66470 *
66471 * In particular, a non-strict arguments object with no
66472 * mapped formals does *NOT* get exotic behavior, even
66473 * for e.g. "caller" property. This seems counterintuitive
66474 * but seems to be the case.
66475 */
66476
66477 /* cannot be strict (never mapped variables) */
66479
66480 DUK_DDD(DUK_DDDPRINT("enabling exotic behavior for arguments object"));
66482 } else {
66483 DUK_DDD(DUK_DDDPRINT("not enabling exotic behavior for arguments object"));
66484 }
66485
66486 DUK_DDD(DUK_DDDPRINT("final arguments related objects: "
66487 "arguments at index %ld -> %!O "
66488 "map at index %ld -> %!O "
66489 "mappednames at index %ld -> %!O",
66490 (long) i_arg,
66491 (duk_heaphdr *) duk_get_hobject(thr, i_arg),
66492 (long) i_map,
66493 (duk_heaphdr *) duk_get_hobject(thr, i_map),
66494 (long) i_mappednames,
66495 (duk_heaphdr *) duk_get_hobject(thr, i_mappednames)));
66496
66497 /* [ args(n) envobj formals arguments map mappednames ] */
66498
66499 duk_pop_2(thr);
66500 duk_remove_m2(thr);
66501
66502 /* [ args(n) envobj arguments ] */
66503}
66504
66505/* Helper for creating the arguments object and adding it to the env record
66506 * on top of the value stack.
66507 */
66509 DUK_DDD(DUK_DDDPRINT("creating arguments object for function call"));
66510
66511 DUK_ASSERT(thr != NULL);
66512 DUK_ASSERT(func != NULL);
66513 DUK_ASSERT(env != NULL);
66515
66516 /* [ ... arg1 ... argN envobj ] */
66517
66518 duk__create_arguments_object(thr, func, env, idx_args);
66519
66520 /* [ ... arg1 ... argN envobj argobj ] */
66521
66523 -2,
66525 DUK_HOBJECT_HAS_STRICT(func) ? DUK_PROPDESC_FLAGS_E : /* strict: non-deletable, non-writable */
66526 DUK_PROPDESC_FLAGS_WE); /* non-strict: non-deletable, writable */
66527 /* [ ... arg1 ... argN envobj ] */
66528}
66529
66530/*
66531 * Helpers for constructor call handling.
66532 *
66533 * There are two [[Construct]] operations in the specification:
66534 *
66535 * - E5 Section 13.2.2: for Function objects
66536 * - E5 Section 15.3.4.5.2: for "bound" Function objects
66537 *
66538 * The chain of bound functions is resolved in Section 15.3.4.5.2,
66539 * with arguments "piling up" until the [[Construct]] internal
66540 * method is called on the final, actual Function object. Note
66541 * that the "prototype" property is looked up *only* from the
66542 * final object, *before* calling the constructor.
66543 *
66544 * Since Duktape 2.2 bound functions are represented with the
66545 * duk_hboundfunc internal type, and bound function chains are
66546 * collapsed when a bound function is created. As a result, the
66547 * direct target of a duk_hboundfunc is always non-bound and the
66548 * this/argument lists have been resolved.
66549 *
66550 * When constructing new Array instances, an unnecessary object is
66551 * created and discarded now: the standard [[Construct]] creates an
66552 * object, and calls the Array constructor. The Array constructor
66553 * returns an Array instance, which is used as the result value for
66554 * the "new" operation; the object created before the Array constructor
66555 * call is discarded.
66556 *
66557 * This would be easy to fix, e.g. by knowing that the Array constructor
66558 * will always create a replacement object and skip creating the fallback
66559 * object in that case.
66560 */
66561
66562/* Update default instance prototype for constructor call. */
66564 duk_hobject *proto;
66565 duk_hobject *fallback;
66566
66567 DUK_ASSERT(duk_is_constructable(thr, idx_func));
66570 proto = duk_get_hobject(thr, -1);
66571 if (proto == NULL) {
66572 DUK_DDD(DUK_DDDPRINT("constructor has no 'prototype' property, or value not an object "
66573 "-> leave standard Object prototype as fallback prototype"));
66574 } else {
66575 DUK_DDD(DUK_DDDPRINT("constructor has 'prototype' property with object value "
66576 "-> set fallback prototype to that value: %!iO",
66577 (duk_heaphdr *) proto));
66578 /* Original fallback (default instance) is untouched when
66579 * resolving bound functions etc.
66580 */
66581 fallback = duk_known_hobject(thr, idx_func + 1);
66582 DUK_ASSERT(fallback != NULL);
66583 DUK_HOBJECT_SET_PROTOTYPE_UPDREF(thr, fallback, proto);
66584 }
66585 duk_pop(thr);
66586}
66587
66588/* Postprocess: return value special handling, error augmentation. */
66590 /* Use either fallback (default instance) or retval depending
66591 * on retval type. Needs to be called before unwind because
66592 * the default instance is read from the current (immutable)
66593 * 'this' binding.
66594 *
66595 * For Proxy 'construct' calls the return value must be an
66596 * Object (we accept object-like values like buffers and
66597 * lightfuncs too). If not, TypeError.
66598 */
66600 DUK_DDD(DUK_DDDPRINT("replacement value"));
66601 } else {
66602 if (DUK_UNLIKELY(proxy_invariant != 0U)) {
66603 /* Proxy 'construct' return value invariant violated. */
66605 DUK_WO_NORETURN(return;);
66606 }
66607 /* XXX: direct value stack access */
66608 duk_pop(thr);
66609 duk_push_this(thr);
66610 }
66611
66612#if defined(DUK_USE_AUGMENT_ERROR_CREATE)
66613 /* Augment created errors upon creation, not when they are thrown or
66614 * rethrown. __FILE__ and __LINE__ are not desirable here; the call
66615 * stack reflects the caller which is correct. Skip topmost, unwound
66616 * activation when creating a traceback. If thr->ptr_curr_pc was !=
66617 * NULL we'd need to sync the current PC so that the traceback comes
66618 * out right; however it is always synced here so just assert for it.
66619 */
66620 DUK_ASSERT(thr->ptr_curr_pc == NULL);
66622#endif
66623}
66624
66625/*
66626 * Helper for handling a bound function when a call is being made.
66627 *
66628 * Assumes that bound function chains have been "collapsed" so that either
66629 * the target is non-bound or there is one bound function that points to a
66630 * nonbound target.
66631 *
66632 * Prepends the bound arguments to the value stack (at idx_func + 2).
66633 * The 'this' binding is also updated if necessary (at idx_func + 1).
66634 * Note that for constructor calls the 'this' binding is never updated by
66635 * [[BoundThis]].
66636 */
66637
66638DUK_LOCAL void duk__handle_bound_chain_for_call(duk_hthread *thr, duk_idx_t idx_func, duk_bool_t is_constructor_call) {
66639 duk_tval *tv_func;
66640 duk_hobject *func;
66641 duk_idx_t len;
66642
66643 DUK_ASSERT(thr != NULL);
66644
66645 /* On entry, item at idx_func is a bound, non-lightweight function,
66646 * but we don't rely on that below.
66647 */
66648
66649 DUK_ASSERT(duk_get_top(thr) >= idx_func + 2);
66650
66651 tv_func = duk_require_tval(thr, idx_func);
66652 DUK_ASSERT(tv_func != NULL);
66653
66654 if (DUK_TVAL_IS_OBJECT(tv_func)) {
66655 func = DUK_TVAL_GET_OBJECT(tv_func);
66656
66657 /* XXX: separate helper function, out of fast path? */
66658 if (DUK_HOBJECT_HAS_BOUNDFUNC(func)) {
66659 duk_hboundfunc *h_bound;
66660 duk_tval *tv_args;
66661 duk_tval *tv_gap;
66662
66663 h_bound = (duk_hboundfunc *) (void *) func;
66664 tv_args = h_bound->args;
66665 len = h_bound->nargs;
66666 DUK_ASSERT(len == 0 || tv_args != NULL);
66667
66668 DUK_DDD(DUK_DDDPRINT("bound function encountered, ptr=%p: %!T",
66669 (void *) DUK_TVAL_GET_OBJECT(tv_func),
66670 tv_func));
66671
66672 /* [ ... func this arg1 ... argN ] */
66673
66674 if (is_constructor_call) {
66675 /* See: tests/ecmascript/test-spec-bound-constructor.js */
66676 DUK_DDD(DUK_DDDPRINT("constructor call: don't update this binding"));
66677 } else {
66678 /* XXX: duk_replace_tval */
66679 duk_push_tval(thr, &h_bound->this_binding);
66680 duk_replace(thr, idx_func + 1); /* idx_this = idx_func + 1 */
66681 }
66682
66683 /* [ ... func this arg1 ... argN ] */
66684
66685 duk_require_stack(thr, len);
66686
66687 tv_gap = duk_reserve_gap(thr, idx_func + 2, len);
66688 duk_copy_tvals_incref(thr, tv_gap, tv_args, (duk_size_t) len);
66689
66690 /* [ ... func this <bound args> arg1 ... argN ] */
66691
66692 duk_push_tval(thr, &h_bound->target);
66693 duk_replace(thr, idx_func); /* replace in stack */
66694
66695 DUK_DDD(DUK_DDDPRINT("bound function handled, idx_func=%ld, curr func=%!T",
66696 (long) idx_func,
66697 duk_get_tval(thr, idx_func)));
66698 }
66699 } else if (DUK_TVAL_IS_LIGHTFUNC(tv_func)) {
66700 /* Lightweight function: never bound, so terminate. */
66701 ;
66702 } else {
66703 /* Shouldn't happen, so ugly error is enough. */
66704 DUK_ERROR_INTERNAL(thr);
66705 DUK_WO_NORETURN(return;);
66706 }
66708 DUK_ASSERT(duk_get_top(thr) >= idx_func + 2);
66709
66710 DUK_DDD(DUK_DDDPRINT("final non-bound function is: %!T", duk_get_tval(thr, idx_func)));
66711
66712#if defined(DUK_USE_ASSERTIONS)
66713 tv_func = duk_require_tval(thr, idx_func);
66715 if (DUK_TVAL_IS_OBJECT(tv_func)) {
66716 func = DUK_TVAL_GET_OBJECT(tv_func);
66717 DUK_ASSERT(func != NULL);
66720 }
66721#endif
66722}
66723
66724/*
66725 * Helper for inline handling of .call(), .apply(), and .construct().
66726 */
66727
66729 duk_idx_t idx_func,
66730 duk_hobject *func,
66731 duk_small_uint_t *call_flags,
66732 duk_bool_t first) {
66733#if defined(DUK_USE_ASSERTIONS)
66734 duk_c_function natfunc;
66735#endif
66736 duk_tval *tv_args;
66737
66738 DUK_ASSERT(func != NULL);
66739 DUK_ASSERT((*call_flags & DUK_CALL_FLAG_CONSTRUCT) == 0); /* Caller. */
66740
66741#if defined(DUK_USE_ASSERTIONS)
66742 natfunc = ((duk_hnatfunc *) func)->func;
66743 DUK_ASSERT(natfunc != NULL);
66744#endif
66745
66746 /* On every round of function resolution at least target function and
66747 * 'this' binding are set. We can assume that here, and must guarantee
66748 * it on exit. Value stack reserve is extended for bound function and
66749 * .apply() unpacking so we don't need to extend it here when we need a
66750 * few slots.
66751 */
66752 DUK_ASSERT(duk_get_top(thr) >= idx_func + 2);
66753
66754 /* Handle native 'eval' specially. A direct eval check is only made
66755 * for the first resolution attempt; e.g. a bound eval call is -not-
66756 * a direct eval call.
66757 */
66758 if (DUK_UNLIKELY(((duk_hnatfunc *) func)->magic == 15)) {
66759 /* For now no special handling except for direct eval
66760 * detection.
66761 */
66763 if (first && (*call_flags & DUK_CALL_FLAG_CALLED_AS_EVAL)) {
66764 *call_flags = (*call_flags & ~DUK_CALL_FLAG_CALLED_AS_EVAL) | DUK_CALL_FLAG_DIRECT_EVAL;
66765 }
66766 DUK_ASSERT(duk_get_top(thr) >= idx_func + 2);
66767 return 1; /* stop resolving */
66768 }
66769
66770 /* Handle special functions based on the DUK_HOBJECT_FLAG_SPECIAL_CALL
66771 * flag; their magic value is used for switch-case.
66772 *
66773 * NOTE: duk_unpack_array_like() reserves value stack space
66774 * for the result values (unlike most other value stack calls).
66775 */
66776 switch (((duk_hnatfunc *) func)->magic) {
66777 case 0: { /* 0=Function.prototype.call() */
66778 /* Value stack:
66779 * idx_func + 0: Function.prototype.call() [removed]
66780 * idx_func + 1: this binding for .call (target function)
66781 * idx_func + 2: 1st argument to .call, desired 'this' binding
66782 * idx_func + 3: 2nd argument to .call, desired 1st argument for ultimate target
66783 * ...
66784 *
66785 * Remove idx_func + 0 to get:
66786 * idx_func + 0: target function
66787 * idx_func + 1: this binding
66788 * idx_func + 2: call arguments
66789 * ...
66790 */
66792 duk_remove_unsafe(thr, idx_func);
66793 tv_args = thr->valstack_bottom + idx_func + 2;
66794 if (thr->valstack_top < tv_args) {
66795 DUK_ASSERT(tv_args <= thr->valstack_end);
66796 thr->valstack_top = tv_args; /* at least target function and 'this' binding present */
66797 }
66798 break;
66799 }
66800 case 1: { /* 1=Function.prototype.apply() */
66801 /* Value stack:
66802 * idx_func + 0: Function.prototype.apply() [removed]
66803 * idx_func + 1: this binding for .apply (target function)
66804 * idx_func + 2: 1st argument to .apply, desired 'this' binding
66805 * idx_func + 3: 2nd argument to .apply, argArray
66806 * [anything after this MUST be ignored]
66807 *
66808 * Remove idx_func + 0 and unpack the argArray to get:
66809 * idx_func + 0: target function
66810 * idx_func + 1: this binding
66811 * idx_func + 2: call arguments
66812 * ...
66813 */
66815 duk_remove_unsafe(thr, idx_func);
66816 goto apply_shared;
66817 }
66818#if defined(DUK_USE_REFLECT_BUILTIN)
66819 case 2: { /* 2=Reflect.apply() */
66820 /* Value stack:
66821 * idx_func + 0: Reflect.apply() [removed]
66822 * idx_func + 1: this binding for .apply (ignored, usually Reflect) [removed]
66823 * idx_func + 2: 1st argument to .apply, target function
66824 * idx_func + 3: 2nd argument to .apply, desired 'this' binding
66825 * idx_func + 4: 3rd argument to .apply, argArray
66826 * [anything after this MUST be ignored]
66827 *
66828 * Remove idx_func + 0 and idx_func + 1, and unpack the argArray to get:
66829 * idx_func + 0: target function
66830 * idx_func + 1: this binding
66831 * idx_func + 2: call arguments
66832 * ...
66833 */
66834 DUK_ASSERT(natfunc == duk_bi_reflect_apply);
66835 duk_remove_n_unsafe(thr, idx_func, 2);
66836 goto apply_shared;
66837 }
66838 case 3: { /* 3=Reflect.construct() */
66839 /* Value stack:
66840 * idx_func + 0: Reflect.construct() [removed]
66841 * idx_func + 1: this binding for .construct (ignored, usually Reflect) [removed]
66842 * idx_func + 2: 1st argument to .construct, target function
66843 * idx_func + 3: 2nd argument to .construct, argArray
66844 * idx_func + 4: 3rd argument to .construct, newTarget
66845 * [anything after this MUST be ignored]
66846 *
66847 * Remove idx_func + 0 and idx_func + 1, unpack the argArray,
66848 * and insert default instance (prototype not yet updated), to get:
66849 * idx_func + 0: target function
66850 * idx_func + 1: this binding (default instance)
66851 * idx_func + 2: constructor call arguments
66852 * ...
66853 *
66854 * Call flags must be updated to reflect the fact that we're
66855 * now dealing with a constructor call, and e.g. the 'this'
66856 * binding cannot be overwritten if the target is bound.
66857 *
66858 * newTarget is checked but not yet passed onwards.
66859 */
66860
66861 duk_idx_t top;
66862
66864 *call_flags |= DUK_CALL_FLAG_CONSTRUCT;
66865 duk_remove_n_unsafe(thr, idx_func, 2);
66866 top = duk_get_top(thr);
66867 if (!duk_is_constructable(thr, idx_func)) {
66868 /* Target constructability must be checked before
66869 * unpacking argArray (which may cause side effects).
66870 * Just return; caller will throw the error.
66871 */
66872 duk_set_top_unsafe(thr, idx_func + 2); /* satisfy asserts */
66873 break;
66874 }
66875 duk_push_object(thr);
66876 duk_insert(thr, idx_func + 1); /* default instance */
66877
66878 /* [ ... func default_instance argArray newTarget? ] */
66879
66880 top = duk_get_top(thr);
66881 if (top < idx_func + 3) {
66882 /* argArray is a mandatory argument for Reflect.construct(). */
66884 DUK_WO_NORETURN(return 0;);
66885 }
66886 if (top > idx_func + 3) {
66887 if (!duk_strict_equals(thr, idx_func, idx_func + 3)) {
66888 /* XXX: [[Construct]] newTarget currently unsupported */
66890 DUK_WO_NORETURN(return 0;);
66891 }
66892 duk_set_top_unsafe(thr, idx_func + 3); /* remove any args beyond argArray */
66893 }
66894 DUK_ASSERT(duk_get_top(thr) == idx_func + 3);
66895 DUK_ASSERT(duk_is_valid_index(thr, idx_func + 2));
66896 (void) duk_unpack_array_like(thr,
66897 idx_func + 2); /* XXX: should also remove target to be symmetric with duk_pack()? */
66898 duk_remove(thr, idx_func + 2);
66899 DUK_ASSERT(duk_get_top(thr) >= idx_func + 2);
66900 break;
66901 }
66902#endif /* DUK_USE_REFLECT_BUILTIN */
66903 default: {
66904 DUK_ASSERT(0);
66906 }
66907 }
66908
66909 DUK_ASSERT(duk_get_top(thr) >= idx_func + 2);
66910 return 0; /* keep resolving */
66911
66912apply_shared:
66913 tv_args = thr->valstack_bottom + idx_func + 2;
66914 if (thr->valstack_top <= tv_args) {
66915 DUK_ASSERT(tv_args <= thr->valstack_end);
66916 thr->valstack_top = tv_args; /* at least target func and 'this' binding present */
66917 /* No need to check for argArray. */
66918 } else {
66919 DUK_ASSERT(duk_get_top(thr) >= idx_func + 3); /* idx_func + 2 covered above */
66920 if (thr->valstack_top > tv_args + 1) {
66921 duk_set_top_unsafe(thr, idx_func + 3); /* remove any args beyond argArray */
66922 }
66923 DUK_ASSERT(duk_is_valid_index(thr, idx_func + 2));
66924 if (!duk_is_callable(thr, idx_func)) {
66925 /* Avoid unpack side effects if the target isn't callable.
66926 * Calling code will throw the actual error.
66927 */
66928 } else {
66929 (void) duk_unpack_array_like(thr, idx_func + 2);
66930 duk_remove(thr, idx_func + 2);
66931 }
66932 }
66933 DUK_ASSERT(duk_get_top(thr) >= idx_func + 2);
66934 return 0; /* keep resolving */
66935}
66936
66937/*
66938 * Helper for Proxy handling.
66939 */
66940
66941#if defined(DUK_USE_ES6_PROXY)
66942DUK_LOCAL void duk__handle_proxy_for_call(duk_hthread *thr, duk_idx_t idx_func, duk_hproxy *h_proxy, duk_small_uint_t *call_flags) {
66943 duk_bool_t rc;
66944
66945 /* Value stack:
66946 * idx_func + 0: Proxy object
66947 * idx_func + 1: this binding for call
66948 * idx_func + 2: 1st argument for call
66949 * idx_func + 3: 2nd argument for call
66950 * ...
66951 *
66952 * If Proxy doesn't have a trap for the call ('apply' or 'construct'),
66953 * replace Proxy object with target object.
66954 *
66955 * If we're dealing with a normal call and the Proxy has an 'apply'
66956 * trap, manipulate value stack to:
66957 *
66958 * idx_func + 0: trap
66959 * idx_func + 1: Proxy's handler
66960 * idx_func + 2: Proxy's target
66961 * idx_func + 3: this binding for call (from idx_func + 1)
66962 * idx_func + 4: call arguments packed to an array
66963 *
66964 * If we're dealing with a constructor call and the Proxy has a
66965 * 'construct' trap, manipulate value stack to:
66966 *
66967 * idx_func + 0: trap
66968 * idx_func + 1: Proxy's handler
66969 * idx_func + 2: Proxy's target
66970 * idx_func + 3: call arguments packed to an array
66971 * idx_func + 4: newTarget == Proxy object here
66972 *
66973 * As we don't yet have proper newTarget support, the newTarget at
66974 * idx_func + 3 is just the original constructor being called, i.e.
66975 * the Proxy object (not the target). Note that the default instance
66976 * (original 'this' binding) is dropped and ignored.
66977 */
66978
66979 duk_push_hobject(thr, h_proxy->handler);
66981 if (rc == 0) {
66982 /* Not found, continue to target. If this is a construct
66983 * call, update default instance prototype using the Proxy,
66984 * not the target.
66985 */
66986 if (*call_flags & DUK_CALL_FLAG_CONSTRUCT) {
66987 if (!(*call_flags & DUK_CALL_FLAG_DEFAULT_INSTANCE_UPDATED)) {
66990 }
66991 }
66992 duk_pop_2(thr);
66993 duk_push_hobject(thr, h_proxy->target);
66994 duk_replace(thr, idx_func);
66995 return;
66996 }
66997
66998 /* Here we must be careful not to replace idx_func while
66999 * h_proxy is still needed, otherwise h_proxy may become
67000 * dangling. This could be improved e.g. using a
67001 * duk_pack_slice() with a freeform slice.
67002 */
67003
67004 /* Here:
67005 * idx_func + 0: Proxy object
67006 * idx_func + 1: this binding for call
67007 * idx_func + 2: 1st argument for call
67008 * idx_func + 3: 2nd argument for call
67009 * ...
67010 * idx_func + N: handler
67011 * idx_func + N + 1: trap
67012 */
67013
67014 duk_insert(thr, idx_func + 1);
67015 duk_insert(thr, idx_func + 2);
67016 duk_push_hobject(thr, h_proxy->target);
67017 duk_insert(thr, idx_func + 3);
67018 duk_pack(thr, duk_get_top(thr) - (idx_func + 5));
67019 DUK_ASSERT(!duk_is_bare_object(thr, -1));
67020
67021 /* Here:
67022 * idx_func + 0: Proxy object
67023 * idx_func + 1: trap
67024 * idx_func + 2: Proxy's handler
67025 * idx_func + 3: Proxy's target
67026 * idx_func + 4: this binding for call
67027 * idx_func + 5: arguments array
67028 */
67029 DUK_ASSERT(duk_get_top(thr) == idx_func + 6);
67030
67031 if (*call_flags & DUK_CALL_FLAG_CONSTRUCT) {
67032 *call_flags |= DUK_CALL_FLAG_CONSTRUCT_PROXY; /* Enable 'construct' trap return invariant check. */
67033 *call_flags &= ~(DUK_CALL_FLAG_CONSTRUCT); /* Resume as non-constructor call to the trap. */
67034
67035 /* 'apply' args: target, thisArg, argArray
67036 * 'construct' args: target, argArray, newTarget
67037 */
67038 duk_remove(thr, idx_func + 4);
67039 duk_push_hobject(thr, (duk_hobject *) h_proxy);
67040 }
67041
67042 /* Finalize value stack layout by removing Proxy reference. */
67043 duk_remove(thr, idx_func);
67044 h_proxy = NULL; /* invalidated */
67045 DUK_ASSERT(duk_get_top(thr) == idx_func + 5);
67046}
67047#endif /* DUK_USE_ES6_PROXY */
67048
67049/*
67050 * Helper for setting up var_env and lex_env of an activation,
67051 * assuming it does NOT have the DUK_HOBJECT_FLAG_NEWENV flag.
67052 */
67053
67055 duk_hcompfunc *f;
67056 duk_hobject *h_lex;
67057 duk_hobject *h_var;
67058
67059 DUK_ASSERT(thr != NULL);
67060 DUK_ASSERT(func != NULL);
67061 DUK_ASSERT(act != NULL);
67065 DUK_UNREF(thr);
67066
67067 f = (duk_hcompfunc *) func;
67068 h_lex = DUK_HCOMPFUNC_GET_LEXENV(thr->heap, f);
67069 h_var = DUK_HCOMPFUNC_GET_VARENV(thr->heap, f);
67070 DUK_ASSERT(h_lex != NULL); /* Always true for closures (not for templates) */
67071 DUK_ASSERT(h_var != NULL);
67072 act->lex_env = h_lex;
67073 act->var_env = h_var;
67074 DUK_HOBJECT_INCREF(thr, h_lex);
67075 DUK_HOBJECT_INCREF(thr, h_var);
67076}
67077
67078/*
67079 * Helper for updating callee 'caller' property.
67080 */
67081
67082#if defined(DUK_USE_NONSTD_FUNC_CALLER_PROPERTY)
67083DUK_LOCAL void duk__update_func_caller_prop(duk_hthread *thr, duk_hobject *func) {
67084 duk_tval *tv_caller;
67085 duk_hobject *h_tmp;
67086 duk_activation *act_callee;
67087 duk_activation *act_caller;
67088
67089 DUK_ASSERT(thr != NULL);
67090 DUK_ASSERT(func != NULL);
67091 DUK_ASSERT(!DUK_HOBJECT_HAS_BOUNDFUNC(func)); /* bound chain resolved */
67092 DUK_ASSERT(thr->callstack_top >= 1);
67093
67094 if (DUK_HOBJECT_HAS_STRICT(func)) {
67095 /* Strict functions don't get their 'caller' updated. */
67096 return;
67097 }
67098
67099 DUK_ASSERT(thr->callstack_top > 0);
67100 act_callee = thr->callstack_curr;
67101 DUK_ASSERT(act_callee != NULL);
67102 act_caller = (thr->callstack_top >= 2 ? act_callee->parent : NULL);
67103
67104 /* XXX: check .caller writability? */
67105
67106 /* Backup 'caller' property and update its value. */
67108 if (tv_caller) {
67109 /* If caller is global/eval code, 'caller' should be set to
67110 * 'null'.
67111 *
67112 * XXX: there is no exotic flag to infer this correctly now.
67113 * The NEWENV flag is used now which works as intended for
67114 * everything (global code, non-strict eval code, and functions)
67115 * except strict eval code. Bound functions are never an issue
67116 * because 'func' has been resolved to a non-bound function.
67117 */
67118
67119 if (act_caller != NULL) {
67120 /* act_caller->func may be NULL in some finalization cases,
67121 * just treat like we don't know the caller.
67122 */
67123 if (act_caller->func && !DUK_HOBJECT_HAS_NEWENV(act_caller->func)) {
67124 /* Setting to NULL causes 'caller' to be set to
67125 * 'null' as desired.
67126 */
67127 act_caller = NULL;
67128 }
67129 }
67130
67131 if (DUK_TVAL_IS_OBJECT(tv_caller)) {
67132 h_tmp = DUK_TVAL_GET_OBJECT(tv_caller);
67133 DUK_ASSERT(h_tmp != NULL);
67134 act_callee->prev_caller = h_tmp;
67135
67136 /* Previous value doesn't need refcount changes because its ownership
67137 * is transferred to prev_caller.
67138 */
67139
67140 if (act_caller != NULL) {
67141 DUK_ASSERT(act_caller->func != NULL);
67142 DUK_TVAL_SET_OBJECT(tv_caller, act_caller->func);
67143 DUK_TVAL_INCREF(thr, tv_caller);
67144 } else {
67145 DUK_TVAL_SET_NULL(tv_caller); /* no incref */
67146 }
67147 } else {
67148 /* 'caller' must only take on 'null' or function value */
67150 DUK_ASSERT(act_callee->prev_caller == NULL);
67151 if (act_caller != NULL && act_caller->func) {
67152 /* Tolerate act_caller->func == NULL which happens in
67153 * some finalization cases; treat like unknown caller.
67154 */
67155 DUK_TVAL_SET_OBJECT(tv_caller, act_caller->func);
67156 DUK_TVAL_INCREF(thr, tv_caller);
67157 } else {
67158 DUK_TVAL_SET_NULL(tv_caller); /* no incref */
67159 }
67160 }
67161 }
67162}
67163#endif /* DUK_USE_NONSTD_FUNC_CALLER_PROPERTY */
67164
67165/*
67166 * Shared helpers for resolving the final, non-bound target function of the
67167 * call and the effective 'this' binding. Resolves bound functions and
67168 * applies .call(), .apply(), and .construct() inline.
67169 *
67170 * Proxy traps are also handled inline so that if the target is a Proxy with
67171 * a 'call' or 'construct' trap, the trap handler is called with a modified
67172 * argument list.
67174 * Once the bound function / .call() / .apply() / .construct() sequence has
67175 * been resolved, the value at idx_func + 1 may need coercion described in
67176 * E5 Section 10.4.3.
67177 *
67178 * A call that begins as a non-constructor call may be converted into a
67179 * constructor call during the resolution process if Reflect.construct()
67180 * is invoked. This is handled by updating the caller's call_flags.
67181 *
67182 * For global and eval code (E5 Sections 10.4.1 and 10.4.2), we assume
67183 * that the caller has provided the correct 'this' binding explicitly
67184 * when calling, i.e.:
67185 *
67186 * - global code: this=global object
67187 * - direct eval: this=copy from eval() caller's this binding
67188 * - other eval: this=global object
67189 *
67190 * The 'this' coercion may cause a recursive function call with arbitrary
67191 * side effects, because ToObject() may be called.
67192 */
67193
67195 duk_tval *tv_this;
67196 duk_hobject *obj_global;
67197
67198 tv_this = thr->valstack_bottom + idx_this;
67199 switch (DUK_TVAL_GET_TAG(tv_this)) {
67200 case DUK_TAG_OBJECT:
67201 DUK_DDD(DUK_DDDPRINT("this binding: non-strict, object -> use directly"));
67202 break;
67203 case DUK_TAG_UNDEFINED:
67204 case DUK_TAG_NULL:
67205 DUK_DDD(DUK_DDDPRINT("this binding: non-strict, undefined/null -> use global object"));
67206 obj_global = thr->builtins[DUK_BIDX_GLOBAL];
67207 /* XXX: avoid this check somehow */
67208 if (DUK_LIKELY(obj_global != NULL)) {
67209 DUK_ASSERT(!DUK_TVAL_IS_HEAP_ALLOCATED(tv_this)); /* no need to decref previous value */
67210 DUK_TVAL_SET_OBJECT(tv_this, obj_global);
67211 DUK_HOBJECT_INCREF(thr, obj_global);
67212 } else {
67213 /* This may only happen if built-ins are being "torn down".
67214 * This behavior is out of specification scope.
67215 */
67216 DUK_D(DUK_DPRINT("this binding: wanted to use global object, but it is NULL -> using undefined instead"));
67217 DUK_ASSERT(!DUK_TVAL_IS_HEAP_ALLOCATED(tv_this)); /* no need to decref previous value */
67218 DUK_TVAL_SET_UNDEFINED(tv_this); /* nothing to incref */
67219 }
67220 break;
67221 default:
67222 /* Plain buffers and lightfuncs are object coerced. Lightfuncs
67223 * very rarely come here however, because the call target would
67224 * need to be a non-strict non-lightfunc (lightfuncs are considered
67225 * strict) with an explicit lightfunc 'this' binding.
67226 */
67227 DUK_ASSERT(!DUK_TVAL_IS_UNUSED(tv_this));
67228 DUK_DDD(DUK_DDDPRINT("this binding: non-strict, not object/undefined/null -> use ToObject(value)"));
67229 duk_to_object(thr, idx_this); /* may have side effects */
67230 break;
67231 }
67232}
67233
67235 duk_idx_t idx_func,
67236 duk_hobject **out_func,
67237 duk_small_uint_t call_flags) {
67238#if defined(DUK_USE_PREFER_SIZE)
67239 DUK_UNREF(thr);
67240 DUK_UNREF(idx_func);
67241 DUK_UNREF(out_func);
67242 DUK_UNREF(call_flags);
67243#else /* DUK_USE_PREFER_SIZE */
67244 duk_tval *tv_func;
67245 duk_hobject *func;
67246
67247 if (DUK_UNLIKELY(call_flags & DUK_CALL_FLAG_CONSTRUCT)) {
67248 return 0;
67249 }
67250
67251 tv_func = DUK_GET_TVAL_POSIDX(thr, idx_func);
67252 DUK_ASSERT(tv_func != NULL);
67253
67254 if (DUK_LIKELY(DUK_TVAL_IS_OBJECT(tv_func))) {
67255 func = DUK_TVAL_GET_OBJECT(tv_func);
67257 *out_func = func;
67258
67260 /* Strict function: no 'this' coercion. */
67261 return 1;
67262 }
67263
67264 duk__coerce_nonstrict_this_binding(thr, idx_func + 1);
67265 return 1;
67266 }
67267 } else if (DUK_TVAL_IS_LIGHTFUNC(tv_func)) {
67268 *out_func = NULL;
67269
67270 /* Lightfuncs are considered strict, so 'this' binding is
67271 * used as is. They're never bound, always constructable,
67272 * and never special functions.
67273 */
67274 return 1;
67275 }
67276#endif /* DUK_USE_PREFER_SIZE */
67277 return 0; /* let slow path deal with it */
67278}
67279
67281 duk_idx_t idx_func,
67282 duk_small_uint_t *call_flags) {
67283 duk_tval *tv_func;
67284 duk_hobject *func;
67285 duk_bool_t first;
67286
67287 DUK_ASSERT(duk_get_top(thr) >= idx_func + 2);
67288
67289 for (first = 1;; first = 0) {
67290 DUK_ASSERT(duk_get_top(thr) >= idx_func + 2);
67291
67292 tv_func = DUK_GET_TVAL_POSIDX(thr, idx_func);
67293 DUK_ASSERT(tv_func != NULL);
67294
67295 DUK_DD(DUK_DDPRINT("target func: %!iT", tv_func));
67296
67297 if (DUK_TVAL_IS_OBJECT(tv_func)) {
67298 func = DUK_TVAL_GET_OBJECT(tv_func);
67299
67300 if (*call_flags & DUK_CALL_FLAG_CONSTRUCT) {
67302 goto not_constructable;
67303 }
67304 } else {
67306 goto not_callable;
67307 }
67308 }
67309
67312 /* Common case, so test for using a single bitfield test.
67313 * Break out to handle this coercion etc.
67314 */
67315 break;
67316 }
67317
67318 /* XXX: could set specialcall for boundfuncs too, simplify check above */
67319
67320 if (DUK_HOBJECT_HAS_BOUNDFUNC(func)) {
67323
67324 /* Callable/constructable flags are the same
67325 * for the bound function and its target, so
67326 * we don't need to check them here, we can
67327 * check them from the target only.
67328 */
67329 duk__handle_bound_chain_for_call(thr, idx_func, *call_flags & DUK_CALL_FLAG_CONSTRUCT);
67330
67332 DUK_TVAL_IS_LIGHTFUNC(duk_require_tval(thr, idx_func)));
67333 } else {
67335
67336#if defined(DUK_USE_ES6_PROXY)
67338 /* If no trap, resume processing from Proxy trap.
67339 * If trap exists, helper converts call into a trap
67340 * call; this may change a constructor call into a
67341 * normal (non-constructor) trap call. We must
67342 * continue processing even when a trap is found as
67343 * the trap may be bound.
67344 */
67345 duk__handle_proxy_for_call(thr, idx_func, (duk_hproxy *) func, call_flags);
67346 } else
67347#endif
67348 {
67352 /* Constructable check already done above. */
67353
67354 if (duk__handle_specialfuncs_for_call(thr, idx_func, func, call_flags, first) != 0) {
67355 /* Encountered native eval call, normal call
67356 * context. Break out, handle this coercion etc.
67357 */
67358 break;
67359 }
67360 }
67361 }
67362 /* Retry loop. */
67363 } else if (DUK_TVAL_IS_LIGHTFUNC(tv_func)) {
67364 /* Lightfuncs are:
67365 * - Always strict, so no 'this' coercion.
67366 * - Always callable.
67367 * - Always constructable.
67368 * - Never specialfuncs.
67369 */
67370 func = NULL;
67371 goto finished;
67372 } else {
67373 goto not_callable;
67374 }
67375 }
67376
67377 DUK_ASSERT(func != NULL);
67378
67379 if (!DUK_HOBJECT_HAS_STRICT(func)) {
67380 /* Non-strict target needs 'this' coercion.
67381 * This has potential side effects invalidating
67382 * 'tv_func'.
67383 */
67384 duk__coerce_nonstrict_this_binding(thr, idx_func + 1);
67385 }
67386 if (*call_flags & DUK_CALL_FLAG_CONSTRUCT) {
67387 if (!(*call_flags & DUK_CALL_FLAG_DEFAULT_INSTANCE_UPDATED)) {
67390 }
67391 }
67392
67393finished :
67394#if defined(DUK_USE_ASSERTIONS)
67395{
67396 duk_tval *tv_tmp;
67397
67398 tv_tmp = duk_get_tval(thr, idx_func);
67399 DUK_ASSERT(tv_tmp != NULL);
67400
67402 DUK_TVAL_IS_LIGHTFUNC(tv_tmp));
67403 DUK_ASSERT(func == NULL || !DUK_HOBJECT_HAS_BOUNDFUNC(func));
67404 DUK_ASSERT(func == NULL || (DUK_HOBJECT_IS_COMPFUNC(func) || DUK_HOBJECT_IS_NATFUNC(func)));
67405 DUK_ASSERT(func == NULL || (DUK_HOBJECT_HAS_CONSTRUCTABLE(func) || (*call_flags & DUK_CALL_FLAG_CONSTRUCT) == 0));
67406}
67407#endif
67408
67409 return func;
67410
67411not_callable:
67412 DUK_ASSERT(tv_func != NULL);
67413
67414#if defined(DUK_USE_VERBOSE_ERRORS)
67415 /* GETPROPC delayed error handling: when target is not callable,
67416 * GETPROPC replaces idx_func+0 with a non-callable wrapper object
67417 * with a hidden Symbol to signify it's to be handled here. If
67418 * found, unwrap the original Error and throw it as is here. The
67419 * hidden Symbol is only checked as an own property, not inherited
67420 * (which would be dangerous).
67421 */
67422 if (DUK_TVAL_IS_OBJECT(tv_func)) {
67423 duk_tval *tv_wrap =
67425 if (tv_wrap != NULL) {
67426 DUK_DD(DUK_DDPRINT("delayed error from GETPROPC: %!T", tv_wrap));
67427 duk_push_tval(thr, tv_wrap);
67428 (void) duk_throw(thr);
67429 DUK_WO_NORETURN(return NULL;);
67430 }
67431 }
67432#endif
67433
67434#if defined(DUK_USE_VERBOSE_ERRORS)
67435#if defined(DUK_USE_PARANOID_ERRORS)
67436 DUK_ERROR_FMT1(thr, DUK_ERR_TYPE_ERROR, "%s not callable", duk_get_type_name(thr, idx_func));
67437#else
67438 DUK_ERROR_FMT1(thr, DUK_ERR_TYPE_ERROR, "%s not callable", duk_push_string_tval_readable(thr, tv_func));
67439#endif
67440#else
67442#endif
67443 DUK_WO_NORETURN(return NULL;);
67444
67445not_constructable:
67446 /* For now GETPROPC delayed error not needed for constructor calls. */
67447#if defined(DUK_USE_VERBOSE_ERRORS)
67448#if defined(DUK_USE_PARANOID_ERRORS)
67449 DUK_ERROR_FMT1(thr, DUK_ERR_TYPE_ERROR, "%s not constructable", duk_get_type_name(thr, idx_func));
67450#else
67451 DUK_ERROR_FMT1(thr, DUK_ERR_TYPE_ERROR, "%s not constructable", duk_push_string_tval_readable(thr, tv_func));
67452#endif
67453#else
67455#endif
67456 DUK_WO_NORETURN(return NULL;);
67457}
67458
67459/*
67460 * Manipulate value stack so that exactly 'num_stack_rets' return
67461 * values are at 'idx_retbase' in every case, assuming there are
67462 * 'rc' return values on top of stack.
67463 *
67464 * This is a bit tricky, because the called C function operates in
67465 * the same activation record and may have e.g. popped the stack
67466 * empty (below idx_retbase).
67467 */
67468
67470 duk_idx_t idx_retbase,
67471 duk_idx_t num_stack_rets,
67472 duk_idx_t num_actual_rets) {
67473 duk_idx_t idx_rcbase;
67474
67475 DUK_ASSERT(thr != NULL);
67476 DUK_ASSERT(idx_retbase >= 0);
67477 DUK_ASSERT(num_stack_rets >= 0);
67478 DUK_ASSERT(num_actual_rets >= 0);
67479
67480 idx_rcbase = duk_get_top(thr) - num_actual_rets; /* base of known return values */
67481 if (DUK_UNLIKELY(idx_rcbase < 0)) {
67483 DUK_WO_NORETURN(return;);
67484 }
67485
67486 DUK_DDD(DUK_DDDPRINT("adjust valstack after func call: "
67487 "num_stack_rets=%ld, num_actual_rets=%ld, stack_top=%ld, idx_retbase=%ld, idx_rcbase=%ld",
67488 (long) num_stack_rets,
67489 (long) num_actual_rets,
67490 (long) duk_get_top(thr),
67491 (long) idx_retbase,
67492 (long) idx_rcbase));
67493
67494 DUK_ASSERT(idx_rcbase >= 0); /* caller must check */
67495
67496 /* Space for num_stack_rets was reserved before the safe call.
67497 * Because value stack reserve cannot shrink except in call returns,
67498 * the reserve is still in place. Adjust valstack, carefully
67499 * ensuring we don't overstep the reserve.
67500 */
67501
67502 /* Match idx_rcbase with idx_retbase so that the return values
67503 * start at the correct index.
67504 */
67505 if (idx_rcbase > idx_retbase) {
67506 duk_idx_t count = idx_rcbase - idx_retbase;
67507
67508 DUK_DDD(DUK_DDDPRINT("elements at/after idx_retbase have enough to cover func retvals "
67509 "(idx_retbase=%ld, idx_rcbase=%ld)",
67510 (long) idx_retbase,
67511 (long) idx_rcbase));
67512
67513 /* Remove values between irc_rcbase (start of intended return
67514 * values) and idx_retbase to lower return values to idx_retbase.
67515 */
67516 DUK_ASSERT(count > 0);
67517 duk_remove_n(thr, idx_retbase, count); /* may be NORZ */
67518 } else {
67519 duk_idx_t count = idx_retbase - idx_rcbase;
67520
67521 DUK_DDD(DUK_DDDPRINT("not enough elements at/after idx_retbase to cover func retvals "
67522 "(idx_retbase=%ld, idx_rcbase=%ld)",
67523 (long) idx_retbase,
67524 (long) idx_rcbase));
67525
67526 /* Insert 'undefined' at idx_rcbase (start of intended return
67527 * values) to lift return values to idx_retbase.
67528 */
67529 DUK_ASSERT(count >= 0);
67530 DUK_ASSERT(thr->valstack_end - thr->valstack_top >= count); /* reserve cannot shrink */
67531 duk_insert_undefined_n(thr, idx_rcbase, count);
67532 }
67533
67534 /* Chop extra retvals away / extend with undefined. */
67535 duk_set_top_unsafe(thr, idx_retbase + num_stack_rets);
67536}
67537
67538/*
67539 * Activation setup for tailcalls and non-tailcalls.
67540 */
67541
67542#if defined(DUK_USE_TAILCALL)
67544 duk_small_uint_t call_flags,
67545 duk_idx_t idx_func,
67546 duk_hobject *func,
67547 duk_size_t entry_valstack_bottom_byteoff,
67548 duk_size_t entry_valstack_end_byteoff,
67549 duk_idx_t *out_nargs,
67550 duk_idx_t *out_nregs,
67551 duk_size_t *out_vs_min_bytes,
67552 duk_activation **out_act) {
67553 duk_activation *act;
67554 duk_tval *tv1, *tv2;
67555 duk_idx_t idx_args;
67556 duk_small_uint_t flags1, flags2;
67557#if defined(DUK_USE_DEBUGGER_SUPPORT)
67558 duk_activation *prev_pause_act;
67559#endif
67560
67561 DUK_UNREF(entry_valstack_end_byteoff);
67562
67563 /* Tailcall cannot be flagged to resume calls, and a
67564 * previous frame must exist.
67565 */
67566 DUK_ASSERT(thr->callstack_top >= 1);
67567
67568 act = thr->callstack_curr;
67569 DUK_ASSERT(act != NULL);
67570 *out_act = act;
67571
67572 if (func == NULL || !DUK_HOBJECT_IS_COMPFUNC(func)) {
67573 DUK_DDD(DUK_DDDPRINT("tail call prevented by target not being ecma function"));
67574 return 0;
67575 }
67576 if (act->flags & DUK_ACT_FLAG_PREVENT_YIELD) {
67577 DUK_DDD(DUK_DDDPRINT("tail call prevented by current activation having DUK_ACT_FLAG_PREVENT_YIELD"));
67578 return 0;
67579 }
67580 /* Tailcall is only allowed if current and candidate
67581 * function have identical return value handling. There
67582 * are three possible return value handling cases:
67583 * 1. Normal function call, no special return value handling.
67584 * 2. Constructor call, return value replacement object check.
67585 * 3. Proxy 'construct' trap call, return value invariant check.
67586 */
67587 flags1 = (duk_small_uint_t) ((act->flags & DUK_ACT_FLAG_CONSTRUCT) ? 1 : 0)
67588#if defined(DUK_USE_ES6_PROXY)
67590#endif
67591 ;
67592 flags2 = (duk_small_uint_t) ((call_flags & DUK_CALL_FLAG_CONSTRUCT) ? 1 : 0)
67593#if defined(DUK_USE_ES6_PROXY)
67594 | (duk_small_uint_t) ((call_flags & DUK_CALL_FLAG_CONSTRUCT_PROXY) ? 2 : 0);
67595#endif
67596 ;
67597 if (flags1 != flags2) {
67598 DUK_DDD(DUK_DDDPRINT("tail call prevented by incompatible return value handling"));
67599 return 0;
67600 }
67601 DUK_ASSERT(((act->flags & DUK_ACT_FLAG_CONSTRUCT) && (call_flags & DUK_CALL_FLAG_CONSTRUCT)) ||
67602 (!(act->flags & DUK_ACT_FLAG_CONSTRUCT) && !(call_flags & DUK_CALL_FLAG_CONSTRUCT)));
67605 if (DUK_HOBJECT_HAS_NOTAIL(func)) {
67606 /* See: test-bug-tailcall-preventyield-assert.c. */
67607 DUK_DDD(DUK_DDDPRINT("tail call prevented by function having a notail flag"));
67608 return 0;
67609 }
67610
67611 /*
67612 * Tailcall handling
67613 *
67614 * Although the callstack entry is reused, we need to explicitly unwind
67615 * the current activation (or simulate an unwind). In particular, the
67616 * current activation must be closed, otherwise something like
67617 * test-bug-reduce-judofyr.js results. Also catchers need to be unwound
67618 * because there may be non-error-catching label entries in valid tail calls.
67619 *
67620 * Special attention is needed for debugger and pause behavior when
67621 * reusing an activation.
67622 * - Disable StepOut processing for the activation unwind because
67623 * we reuse the activation, see:
67624 * https://github.com/svaarala/duktape/issues/1684.
67625 * - Disable line change pause flag permanently if act == dbg_pause_act
67626 * (if set) because it would no longer be relevant, see:
67627 * https://github.com/svaarala/duktape/issues/1726,
67628 * https://github.com/svaarala/duktape/issues/1786.
67629 * - Check for function entry (e.g. StepInto) pause flag here, because
67630 * the executor pause check won't trigger due to shared activation, see:
67631 * https://github.com/svaarala/duktape/issues/1726.
67632 */
67633
67634 DUK_DDD(DUK_DDDPRINT("is tail call, reusing activation at callstack top, at index %ld", (long) (thr->callstack_top - 1)));
67635
67641
67642 /* Unwind the topmost callstack entry before reusing it. This
67643 * also unwinds the catchers related to the topmost entry.
67644 */
67645 DUK_ASSERT(thr->callstack_top > 0);
67646 DUK_ASSERT(thr->callstack_curr != NULL);
67647#if defined(DUK_USE_DEBUGGER_SUPPORT)
67648 if (act == thr->heap->dbg_pause_act) {
67649 thr->heap->dbg_pause_flags &= ~DUK_PAUSE_FLAG_LINE_CHANGE;
67650 }
67651
67652 prev_pause_act = thr->heap->dbg_pause_act;
67653 thr->heap->dbg_pause_act = NULL;
67654 if (thr->heap->dbg_pause_flags & DUK_PAUSE_FLAG_FUNC_ENTRY) {
67655 DUK_D(DUK_DPRINT("PAUSE TRIGGERED by function entry (tailcall)"));
67656 duk_debug_set_paused(thr->heap);
67657 }
67658#endif
67660#if defined(DUK_USE_DEBUGGER_SUPPORT)
67661 thr->heap->dbg_pause_act = prev_pause_act;
67662#endif
67663 DUK_ASSERT(act == thr->callstack_curr);
67664
67665 /* XXX: We could restore the caller's value stack reserve
67666 * here, as if we did an actual unwind-and-call. Without
67667 * the restoration, value stack reserve may remain higher
67668 * than would otherwise be possible until we return to a
67669 * non-tailcall.
67670 */
67671
67672 /* Then reuse the unwound activation. */
67673 act->cat = NULL;
67674 act->var_env = NULL;
67675 act->lex_env = NULL;
67676 DUK_ASSERT(func != NULL);
67678 act->func = func; /* don't want an intermediate exposed state with func == NULL */
67679#if defined(DUK_USE_NONSTD_FUNC_CALLER_PROPERTY)
67680 act->prev_caller = NULL;
67681#endif
67682 /* don't want an intermediate exposed state with invalid pc */
67684#if defined(DUK_USE_DEBUGGER_SUPPORT)
67685 act->prev_line = 0;
67686#endif
67687 DUK_TVAL_SET_OBJECT(&act->tv_func, func); /* borrowed, no refcount */
67688 DUK_HOBJECT_INCREF(thr, func);
67689
67691 if (DUK_HOBJECT_HAS_STRICT(func)) {
67692 act->flags |= DUK_ACT_FLAG_STRICT;
67693 }
67694 if (call_flags & DUK_CALL_FLAG_CONSTRUCT) {
67696 }
67697#if defined(DUK_USE_ES6_PROXY)
67698 if (call_flags & DUK_CALL_FLAG_CONSTRUCT_PROXY) {
67700 }
67701#endif
67702
67703 DUK_ASSERT(DUK_ACT_GET_FUNC(act) == func); /* already updated */
67704 DUK_ASSERT(act->var_env == NULL);
67705 DUK_ASSERT(act->lex_env == NULL);
67706 act->bottom_byteoff = entry_valstack_bottom_byteoff; /* tail call -> reuse current "frame" */
67707#if 0
67708 /* Topmost activation retval_byteoff is considered garbage, no need to init. */
67709 act->retval_byteoff = 0;
67710#endif
67711 /* Filled in when final reserve is known, dummy value doesn't matter
67712 * even in error unwind because reserve_byteoff is only used when
67713 * returning to -this- activation.
67714 */
67715 act->reserve_byteoff = 0;
67716
67717 /*
67718 * Manipulate valstack so that args are on the current bottom and the
67719 * previous caller's 'this' binding (which is the value preceding the
67720 * current bottom) is replaced with the new 'this' binding:
67721 *
67722 * [ ... this_old | (crud) func this_new arg1 ... argN ]
67723 * --> [ ... this_new | arg1 ... argN ]
67724 *
67725 * For tail calling to work properly, the valstack bottom must not grow
67726 * here; otherwise crud would accumulate on the valstack.
67727 */
67728
67729 tv1 = thr->valstack_bottom - 1;
67730 tv2 = thr->valstack_bottom + idx_func + 1;
67731 DUK_ASSERT(tv1 >= thr->valstack && tv1 < thr->valstack_top); /* tv1 is -below- valstack_bottom */
67732 DUK_ASSERT(tv2 >= thr->valstack_bottom && tv2 < thr->valstack_top);
67733 DUK_TVAL_SET_TVAL_UPDREF(thr, tv1, tv2); /* side effects */
67734
67735 idx_args = idx_func + 2;
67736 duk_remove_n(thr, 0, idx_args); /* may be NORZ */
67737
67738 idx_func = 0;
67739 DUK_UNREF(idx_func); /* really 'not applicable' anymore, should not be referenced after this */
67740 idx_args = 0;
67741
67742 *out_nargs = ((duk_hcompfunc *) func)->nargs;
67743 *out_nregs = ((duk_hcompfunc *) func)->nregs;
67744 DUK_ASSERT(*out_nregs >= 0);
67745 DUK_ASSERT(*out_nregs >= *out_nargs);
67746 *out_vs_min_bytes =
67747 entry_valstack_bottom_byteoff + sizeof(duk_tval) * ((duk_size_t) *out_nregs + DUK_VALSTACK_INTERNAL_EXTRA);
67748
67749#if defined(DUK_USE_NONSTD_FUNC_CALLER_PROPERTY)
67750#if defined(DUK_USE_TAILCALL)
67751#error incorrect options: tail calls enabled with function caller property
67752#endif
67753 /* XXX: This doesn't actually work properly for tail calls, so
67754 * tail calls are disabled when DUK_USE_NONSTD_FUNC_CALLER_PROPERTY
67755 * is in use.
67756 */
67757 duk__update_func_caller_prop(thr, func);
67758#endif
67759
67760 /* [ ... this_new | arg1 ... argN ] */
67761
67762 return 1;
67763}
67764#endif /* DUK_USE_TAILCALL */
67765
67767 duk_small_uint_t call_flags,
67768 duk_idx_t idx_func,
67769 duk_hobject *func,
67770 duk_size_t entry_valstack_bottom_byteoff,
67771 duk_size_t entry_valstack_end_byteoff,
67772 duk_idx_t *out_nargs,
67773 duk_idx_t *out_nregs,
67774 duk_size_t *out_vs_min_bytes,
67775 duk_activation **out_act) {
67776 duk_activation *act;
67777 duk_activation *new_act;
67778
67779 DUK_UNREF(entry_valstack_end_byteoff);
67780
67781 DUK_DDD(DUK_DDDPRINT("not a tail call, pushing a new activation to callstack, to index %ld", (long) (thr->callstack_top)));
67782
67784 new_act = duk_hthread_activation_alloc(thr);
67785 DUK_ASSERT(new_act != NULL);
67786
67787 act = thr->callstack_curr;
67788 if (act != NULL) {
67789 /*
67790 * Update return value stack index of current activation (if any).
67791 *
67792 * Although it might seem this is not necessary (bytecode executor
67793 * does this for ECMAScript-to-ECMAScript calls; other calls are
67794 * handled here), this turns out to be necessary for handling yield
67795 * and resume. For them, an ECMAScript-to-native call happens, and
67796 * the ECMAScript call's retval_byteoff must be set for things to work.
67797 */
67798
67799 act->retval_byteoff = entry_valstack_bottom_byteoff + (duk_size_t) idx_func * sizeof(duk_tval);
67800 }
67801
67802 new_act->parent = act;
67803 thr->callstack_curr = new_act;
67804 thr->callstack_top++;
67805 act = new_act;
67806 *out_act = act;
67807
67808 DUK_ASSERT(thr->valstack_top > thr->valstack_bottom); /* at least effective 'this' */
67809 DUK_ASSERT(func == NULL || !DUK_HOBJECT_HAS_BOUNDFUNC(func));
67810
67811 act->cat = NULL;
67812
67813 act->flags = 0;
67814 if (call_flags & DUK_CALL_FLAG_CONSTRUCT) {
67816 }
67817#if defined(DUK_USE_ES6_PROXY)
67818 if (call_flags & DUK_CALL_FLAG_CONSTRUCT_PROXY) {
67820 }
67821#endif
67822 if (call_flags & DUK_CALL_FLAG_DIRECT_EVAL) {
67824 }
67825
67826 /* start of arguments: idx_func + 2. */
67827 act->func = func; /* NULL for lightfunc */
67828 if (DUK_LIKELY(func != NULL)) {
67829 DUK_TVAL_SET_OBJECT(&act->tv_func, func); /* borrowed, no refcount */
67830 if (DUK_HOBJECT_HAS_STRICT(func)) {
67831 act->flags |= DUK_ACT_FLAG_STRICT;
67832 }
67833 if (DUK_HOBJECT_IS_COMPFUNC(func)) {
67834 *out_nargs = ((duk_hcompfunc *) func)->nargs;
67835 *out_nregs = ((duk_hcompfunc *) func)->nregs;
67836 DUK_ASSERT(*out_nregs >= 0);
67837 DUK_ASSERT(*out_nregs >= *out_nargs);
67838 *out_vs_min_bytes =
67839 entry_valstack_bottom_byteoff +
67840 sizeof(duk_tval) * ((duk_size_t) idx_func + 2U + (duk_size_t) *out_nregs + DUK_VALSTACK_INTERNAL_EXTRA);
67841 } else {
67842 /* True because of call target lookup checks. */
67844
67845 *out_nargs = ((duk_hnatfunc *) func)->nargs;
67846 *out_nregs = *out_nargs;
67847 if (*out_nargs >= 0) {
67848 *out_vs_min_bytes =
67849 entry_valstack_bottom_byteoff +
67850 sizeof(duk_tval) * ((duk_size_t) idx_func + 2U + (duk_size_t) *out_nregs +
67852 } else {
67853 /* Vararg function. */
67854 duk_size_t valstack_top_byteoff =
67855 (duk_size_t) ((duk_uint8_t *) thr->valstack_top - ((duk_uint8_t *) thr->valstack));
67856 *out_vs_min_bytes = valstack_top_byteoff + sizeof(duk_tval) * (DUK_VALSTACK_API_ENTRY_MINIMUM +
67858 }
67859 }
67860 } else {
67861 duk_small_uint_t lf_flags;
67862 duk_tval *tv_func;
67863
67864 act->flags |= DUK_ACT_FLAG_STRICT;
67865
67866 tv_func = DUK_GET_TVAL_POSIDX(thr, idx_func);
67868 DUK_TVAL_SET_TVAL(&act->tv_func, tv_func); /* borrowed, no refcount */
67869
67870 lf_flags = DUK_TVAL_GET_LIGHTFUNC_FLAGS(tv_func);
67871 *out_nargs = DUK_LFUNC_FLAGS_GET_NARGS(lf_flags);
67872 if (*out_nargs != DUK_LFUNC_NARGS_VARARGS) {
67873 *out_vs_min_bytes = entry_valstack_bottom_byteoff +
67874 sizeof(duk_tval) * ((duk_size_t) idx_func + 2U + (duk_size_t) *out_nargs +
67876 } else {
67877 duk_size_t valstack_top_byteoff =
67878 (duk_size_t) ((duk_uint8_t *) thr->valstack_top - ((duk_uint8_t *) thr->valstack));
67879 *out_vs_min_bytes = valstack_top_byteoff +
67881 *out_nargs = -1; /* vararg */
67882 }
67883 *out_nregs = *out_nargs;
67884 }
67885
67886 act->var_env = NULL;
67887 act->lex_env = NULL;
67888#if defined(DUK_USE_NONSTD_FUNC_CALLER_PROPERTY)
67889 act->prev_caller = NULL;
67890#endif
67891 act->curr_pc = NULL;
67892#if defined(DUK_USE_DEBUGGER_SUPPORT)
67893 act->prev_line = 0;
67894#endif
67895 act->bottom_byteoff = entry_valstack_bottom_byteoff + sizeof(duk_tval) * ((duk_size_t) idx_func + 2U);
67896#if 0
67897 act->retval_byteoff = 0; /* topmost activation retval_byteoff is considered garbage, no need to init */
67898#endif
67899 /* Filled in when final reserve is known, dummy value doesn't matter
67900 * even in error unwind because reserve_byteoff is only used when
67901 * returning to -this- activation.
67902 */
67903 act->reserve_byteoff = 0; /* filled in by caller */
67904
67905 /* XXX: Is this INCREF necessary? 'func' is always a borrowed
67906 * reference reachable through the value stack? If changed, stack
67907 * unwind code also needs to be fixed to match.
67908 */
67909 DUK_HOBJECT_INCREF_ALLOWNULL(thr, func); /* act->func */
67910
67911#if defined(DUK_USE_NONSTD_FUNC_CALLER_PROPERTY)
67912 if (func) {
67913 duk__update_func_caller_prop(thr, func);
67914 }
67915#endif
67916}
67917
67918/*
67919 * Environment setup.
67920 */
67921
67923 duk_hobject *env;
67924
67925 DUK_ASSERT(func == NULL || !DUK_HOBJECT_HAS_BOUNDFUNC(func)); /* bound function has already been resolved */
67926
67927 if (DUK_LIKELY(func != NULL)) {
67929 DUK_STATS_INC(thr->heap, stats_envrec_newenv);
67931 /* Use a new environment but there's no 'arguments' object;
67932 * delayed environment initialization. This is the most
67933 * common case.
67934 */
67935 DUK_ASSERT(act->lex_env == NULL);
67936 DUK_ASSERT(act->var_env == NULL);
67937 } else {
67938 /* Use a new environment and there's an 'arguments' object.
67939 * We need to initialize it right now.
67940 */
67941
67942 /* third arg: absolute index (to entire valstack) of bottom_byteoff of new activation */
67944 DUK_ASSERT(env != NULL);
67945
67946 /* [ ... func this arg1 ... argN envobj ] */
67947
67949 duk__handle_createargs_for_call(thr, func, env, idx_args);
67950
67951 /* [ ... func this arg1 ... argN envobj ] */
67952
67953 act->lex_env = env;
67954 act->var_env = env;
67955 DUK_HOBJECT_INCREF(thr, env);
67956 DUK_HOBJECT_INCREF(thr, env); /* XXX: incref by count (2) directly */
67957 duk_pop(thr);
67958 }
67959 } else {
67960 /* Use existing env (e.g. for non-strict eval); cannot have
67961 * an own 'arguments' object (but can refer to an existing one).
67962 */
67963
67965
67966 DUK_STATS_INC(thr->heap, stats_envrec_oldenv);
67967 duk__handle_oldenv_for_call(thr, func, act);
67968
67969 DUK_ASSERT(act->lex_env != NULL);
67970 DUK_ASSERT(act->var_env != NULL);
67971 }
67972 } else {
67973 /* Lightfuncs are always native functions and have "newenv". */
67974 DUK_ASSERT(act->lex_env == NULL);
67975 DUK_ASSERT(act->var_env == NULL);
67976 DUK_STATS_INC(thr->heap, stats_envrec_newenv);
67977 }
67978}
67979
67980/*
67981 * Misc shared helpers.
67982 */
67983
67984/* Check thread state, update current thread. */
67986 DUK_ASSERT(thr != NULL);
67987
67988 if (DUK_LIKELY(thr == thr->heap->curr_thread)) {
67990 /* Should actually never happen, but check anyway. */
67991 goto thread_state_error;
67992 }
67993 } else {
67996 goto thread_state_error;
67997 }
67998 DUK_HEAP_SWITCH_THREAD(thr->heap, thr);
68000
68001 /* Multiple threads may be simultaneously in the RUNNING
68002 * state, but not in the same "resume chain".
68003 */
68004 }
68005 DUK_ASSERT(thr->heap->curr_thread == thr);
68007 return;
68008
68009thread_state_error:
68010 DUK_ERROR_FMT1(thr, DUK_ERR_TYPE_ERROR, "invalid thread state (%ld)", (long) thr->state);
68011 DUK_WO_NORETURN(return;);
68012}
68013
68015 * Main unprotected call handler, handles:
68016 *
68017 * - All combinations of native/ECMAScript caller and native/ECMAScript
68018 * target.
68019 *
68020 * - Optimized ECMAScript-to-ECMAScript call where call handling only
68021 * sets up a new duk_activation but reuses an existing bytecode executor
68022 * (the caller) without native recursion.
68023 *
68024 * - Tailcalls, where an activation is reused without increasing call
68025 * stack (duk_activation) depth.
68026 *
68027 * - Setup for an initial Duktape.Thread.resume().
68028 *
68029 * The call handler doesn't provide any protection guarantees, protected calls
68030 * must be implemented e.g. by wrapping the call in a duk_safe_call().
68031 * Call setup may fail at any stage, even when the new activation is in
68032 * place; the only guarantee is that the state is consistent for unwinding.
68033 */
68034
68036#if defined(DUK_USE_ASSERTIONS)
68037 duk_activation *entry_act;
68038 duk_size_t entry_callstack_top;
68039#endif
68040 duk_size_t entry_valstack_bottom_byteoff;
68041 duk_size_t entry_valstack_end_byteoff;
68042 duk_int_t entry_call_recursion_depth;
68043 duk_hthread *entry_curr_thread;
68044 duk_uint_fast8_t entry_thread_state;
68045 duk_instr_t **entry_ptr_curr_pc;
68046 duk_idx_t idx_args;
68047 duk_idx_t nargs; /* # argument registers target function wants (< 0 => "as is") */
68048 duk_idx_t nregs; /* # total registers target function wants on entry (< 0 => "as is") */
68049 duk_size_t vs_min_bytes; /* minimum value stack size (bytes) for handling call */
68050 duk_hobject *func; /* 'func' on stack (borrowed reference) */
68051 duk_activation *act;
68052 duk_ret_t rc;
68053 duk_small_uint_t use_tailcall;
68054
68055 DUK_ASSERT(thr != NULL);
68056 DUK_ASSERT(thr->heap != NULL);
68057 /* Asserts for heap->curr_thread omitted: it may be NULL, 'thr', or
68058 * any other thread (e.g. when heap thread is used to run finalizers).
68059 */
68061 DUK_ASSERT(duk_is_valid_index(thr, idx_func));
68062 DUK_ASSERT(idx_func >= 0);
68063
68064 DUK_STATS_INC(thr->heap, stats_call_all);
68065
68066 /* If a tail call:
68067 * - an ECMAScript activation must be on top of the callstack
68068 * - there cannot be any catch stack entries that would catch
68069 * a return
68070 */
68071#if defined(DUK_USE_ASSERTIONS)
68072 if (call_flags & DUK_CALL_FLAG_TAILCALL) {
68073 duk_activation *tmp_act;
68074 duk_catcher *tmp_cat;
68075
68076 DUK_ASSERT(thr->callstack_top >= 1);
68079
68080 /* No entry in the catch stack which would actually catch a
68081 * throw can refer to the callstack entry being reused.
68082 * There *can* be catch stack entries referring to the current
68083 * callstack entry as long as they don't catch (e.g. label sites).
68084 */
68085
68086 tmp_act = thr->callstack_curr;
68087 for (tmp_cat = tmp_act->cat; tmp_cat != NULL; tmp_cat = tmp_cat->parent) {
68088 DUK_ASSERT(DUK_CAT_GET_TYPE(tmp_cat) == DUK_CAT_TYPE_LABEL); /* a non-catching entry */
68089 }
68090 }
68091#endif /* DUK_USE_ASSERTIONS */
68092
68093 /*
68094 * Store entry state.
68095 */
68096
68097#if defined(DUK_USE_ASSERTIONS)
68098 entry_act = thr->callstack_curr;
68099 entry_callstack_top = thr->callstack_top;
68100#endif
68101 entry_valstack_bottom_byteoff = (duk_size_t) ((duk_uint8_t *) thr->valstack_bottom - (duk_uint8_t *) thr->valstack);
68102 entry_valstack_end_byteoff = (duk_size_t) ((duk_uint8_t *) thr->valstack_end - (duk_uint8_t *) thr->valstack);
68103 entry_call_recursion_depth = thr->heap->call_recursion_depth;
68104 entry_curr_thread = thr->heap->curr_thread; /* may be NULL if first call */
68105 entry_thread_state = thr->state;
68106 entry_ptr_curr_pc = thr->ptr_curr_pc; /* may be NULL */
68107
68108 /* If thr->ptr_curr_pc is set, sync curr_pc to act->pc. Then NULL
68109 * thr->ptr_curr_pc so that it's not accidentally used with an incorrect
68110 * activation when side effects occur.
68111 */
68113 DUK_ASSERT(thr->ptr_curr_pc == NULL);
68114
68115 DUK_DD(DUK_DDPRINT("duk__handle_call_raw: thr=%p, idx_func=%ld, "
68116 "call_flags=0x%08lx (constructor=%ld), "
68117 "valstack_top=%ld, idx_func=%ld, idx_args=%ld, rec_depth=%ld/%ld, "
68118 "entry_valstack_bottom_byteoff=%ld, entry_valstack_end_byteoff=%ld, "
68119 "entry_call_recursion_depth=%ld, "
68120 "entry_curr_thread=%p, entry_thread_state=%ld",
68121 (void *) thr,
68122 (long) idx_func,
68123 (unsigned long) call_flags,
68124 (long) ((call_flags & DUK_CALL_FLAG_CONSTRUCT) != 0 ? 1 : 0),
68125 (long) duk_get_top(thr),
68126 (long) idx_func,
68127 (long) (idx_func + 2),
68128 (long) thr->heap->call_recursion_depth,
68129 (long) thr->heap->call_recursion_limit,
68130 (long) entry_valstack_bottom_byteoff,
68131 (long) entry_valstack_end_byteoff,
68132 (long) entry_call_recursion_depth,
68133 (void *) entry_curr_thread,
68134 (long) entry_thread_state));
68135
68136 /*
68137 * Thread state check and book-keeping.
68138 */
68139
68141
68142 /*
68143 * Increase call recursion depth as early as possible so that if we
68144 * enter a recursive call for any reason there's a backstop to native
68145 * recursion. This can happen e.g. for almost any property read
68146 * because it may cause a getter call or a Proxy trap (GC and finalizers
68147 * are not an issue because they are not recursive). If we end up
68148 * doing an Ecma-to-Ecma call, revert the increase. (See GH-2032.)
68149 *
68150 * For similar reasons, ensure there is a known value stack spare
68151 * even before we actually prepare the value stack for the target
68152 * function. If this isn't done, early recursion may consume the
68153 * value stack space.
68154 *
68155 * XXX: Should bump yield preventcount early, for the same reason.
68156 */
68157
68159 thr->heap->call_recursion_depth++;
68161
68162 /*
68163 * Resolve final target function; handle bound functions and special
68164 * functions like .call() and .apply(). Also figure out the effective
68165 * 'this' binding, which replaces the current value at idx_func + 1.
68166 */
68167
68168 if (DUK_LIKELY(duk__resolve_target_fastpath_check(thr, idx_func, &func, call_flags) != 0U)) {
68169 DUK_DDD(DUK_DDDPRINT("fast path target resolve"));
68170 } else {
68171 DUK_DDD(DUK_DDDPRINT("slow path target resolve"));
68172 func = duk__resolve_target_func_and_this_binding(thr, idx_func, &call_flags);
68173 }
68174 DUK_ASSERT(duk_get_top(thr) - idx_func >= 2); /* at least func and this present */
68175
68176 DUK_ASSERT(func == NULL || !DUK_HOBJECT_HAS_BOUNDFUNC(func));
68177 DUK_ASSERT(func == NULL || (DUK_HOBJECT_IS_COMPFUNC(func) || DUK_HOBJECT_IS_NATFUNC(func)));
68178
68179 /* [ ... func this arg1 ... argN ] */
68180
68181 /*
68182 * Setup a preliminary activation and figure out nargs/nregs and
68183 * value stack minimum size.
68184 *
68185 * Don't touch valstack_bottom or valstack_top yet so that Duktape API
68186 * calls work normally.
68187 *
68188 * Because 'act' is not zeroed, all fields must be filled in.
68189 */
68190
68191 /* Should not be necessary, but initialize to silence warnings. */
68192 act = NULL;
68193 nargs = 0;
68194 nregs = 0;
68195 vs_min_bytes = 0;
68196
68197#if defined(DUK_USE_TAILCALL)
68198 use_tailcall = (call_flags & DUK_CALL_FLAG_TAILCALL);
68199 if (use_tailcall) {
68200 use_tailcall = duk__call_setup_act_attempt_tailcall(thr,
68201 call_flags,
68202 idx_func,
68203 func,
68204 entry_valstack_bottom_byteoff,
68205 entry_valstack_end_byteoff,
68206 &nargs,
68207 &nregs,
68208 &vs_min_bytes,
68209 &act);
68210 }
68211#else
68212 DUK_ASSERT((call_flags & DUK_CALL_FLAG_TAILCALL) == 0); /* compiler ensures this */
68213 use_tailcall = 0;
68214#endif
68215
68216 if (use_tailcall) {
68217 idx_args = 0;
68218 DUK_STATS_INC(thr->heap, stats_call_tailcall);
68219 } else {
68221 call_flags,
68222 idx_func,
68223 func,
68224 entry_valstack_bottom_byteoff,
68225 entry_valstack_end_byteoff,
68226 &nargs,
68227 &nregs,
68228 &vs_min_bytes,
68229 &act);
68230 idx_args = idx_func + 2;
68231 }
68232 /* After this point idx_func is no longer valid for tailcalls. */
68233
68234 DUK_ASSERT(act != NULL);
68235
68236 /* [ ... func this arg1 ... argN ] */
68237
68238 /*
68239 * Grow value stack to required size before env setup. This
68240 * must happen before env setup to handle some corner cases
68241 * correctly, e.g. test-bug-scope-segv-gh2448.js.
68242 */
68243
68244 duk_valstack_grow_check_throw(thr, vs_min_bytes);
68245 act->reserve_byteoff = (duk_size_t) ((duk_uint8_t *) thr->valstack_end - (duk_uint8_t *) thr->valstack);
68246
68247 /*
68248 * Environment record creation and 'arguments' object creation.
68249 * Named function expression name binding is handled by the
68250 * compiler; the compiled function's parent env will contain
68251 * the (immutable) binding already.
68252 *
68253 * This handling is now identical for C and ECMAScript functions.
68254 * C functions always have the 'NEWENV' flag set, so their
68255 * environment record initialization is delayed (which is good).
68256 *
68257 * Delayed creation (on demand) is handled in duk_js_var.c.
68258 */
68259
68260 duk__call_env_setup(thr, func, act, idx_args);
68261
68262 /* [ ... func this arg1 ... argN ] */
68263
68264 /*
68265 * Setup value stack: clamp to 'nargs', fill up to 'nregs',
68266 * ensure value stack size matches target requirements, and
68267 * switch value stack bottom. Valstack top is kept.
68268 */
68269
68270 if (use_tailcall) {
68271 DUK_ASSERT(nregs >= 0);
68272 DUK_ASSERT(nregs >= nargs);
68273 duk_set_top_and_wipe(thr, nregs, nargs);
68274 } else {
68275 if (nregs >= 0) {
68276 DUK_ASSERT(nregs >= nargs);
68277 duk_set_top_and_wipe(thr, idx_func + 2 + nregs, idx_func + 2 + nargs);
68278 } else {
68279 ;
68280 }
68281 thr->valstack_bottom = thr->valstack_bottom + idx_func + 2;
68282 }
68283 DUK_ASSERT(thr->valstack_bottom >= thr->valstack);
68285 DUK_ASSERT(thr->valstack_end >= thr->valstack_top);
68286
68287 /*
68288 * Make the actual call. For Ecma-to-Ecma calls detect that
68289 * setup is complete, then return with a status code that allows
68290 * the caller to reuse the running executor.
68291 */
68292
68293 if (func != NULL && DUK_HOBJECT_IS_COMPFUNC(func)) {
68294 /*
68295 * ECMAScript call.
68296 */
68297
68298 DUK_ASSERT(func != NULL);
68301
68302 if (call_flags & DUK_CALL_FLAG_ALLOW_ECMATOECMA) {
68303 DUK_DD(DUK_DDPRINT("avoid native call, use existing executor"));
68304 DUK_STATS_INC(thr->heap, stats_call_ecmatoecma);
68307 DUK_ASSERT(thr->ptr_curr_pc == NULL);
68308 thr->heap->call_recursion_depth--; /* No recursion increase for this case. */
68309 return 1; /* 1=reuse executor */
68310 }
68311 DUK_ASSERT(use_tailcall == 0);
68312
68313 /* duk_hthread_activation_unwind_norz() will decrease this on unwind */
68317
68318 /* [ ... func this | arg1 ... argN ] ('this' must precede new bottom) */
68319
68320 /*
68321 * Bytecode executor call.
68322 *
68323 * Execute bytecode, handling any recursive function calls and
68324 * thread resumptions. Returns when execution would return from
68325 * the entry level activation. When the executor returns, a
68326 * single return value is left on the stack top.
68327 *
68328 * The only possible longjmp() is an error (DUK_LJ_TYPE_THROW),
68329 * other types are handled internally by the executor.
68330 */
68331
68332 /* thr->ptr_curr_pc is set by bytecode executor early on entry */
68333 DUK_ASSERT(thr->ptr_curr_pc == NULL);
68334 DUK_DDD(DUK_DDDPRINT("entering bytecode execution"));
68336 DUK_DDD(DUK_DDDPRINT("returned from bytecode execution"));
68337 } else {
68338 /*
68339 * Native call.
68340 */
68341
68342 DUK_ASSERT(func == NULL || ((duk_hnatfunc *) func)->func != NULL);
68343 DUK_ASSERT(use_tailcall == 0);
68344
68345 /* [ ... func this | arg1 ... argN ] ('this' must precede new bottom) */
68346
68347 /* duk_hthread_activation_unwind_norz() will decrease this on unwind */
68351
68352 /* For native calls must be NULL so we don't sync back */
68353 DUK_ASSERT(thr->ptr_curr_pc == NULL);
68354
68355 /* XXX: native funcptr could come out of call setup. */
68356 if (func) {
68357 rc = ((duk_hnatfunc *) func)->func(thr);
68358 } else {
68359 duk_tval *tv_func;
68360 duk_c_function funcptr;
68361
68362 tv_func = &act->tv_func;
68364 funcptr = DUK_TVAL_GET_LIGHTFUNC_FUNCPTR(tv_func);
68365 rc = funcptr(thr);
68366 }
68367
68368 /* Automatic error throwing, retval check. */
68369
68370 if (rc == 0) {
68371 DUK_ASSERT(thr->valstack < thr->valstack_end);
68373 thr->valstack_top++;
68374 } else if (rc == 1) {
68375 ;
68376 } else if (rc < 0) {
68378 DUK_WO_NORETURN(return 0;);
68379 } else {
68381 DUK_WO_NORETURN(return 0;);
68382 }
68383 }
68384 DUK_ASSERT(thr->ptr_curr_pc == NULL);
68385 DUK_ASSERT(use_tailcall == 0);
68386
68387 /*
68388 * Constructor call post processing.
68389 */
68390
68391#if defined(DUK_USE_ES6_PROXY)
68394 }
68395#else
68396 if (call_flags & DUK_CALL_FLAG_CONSTRUCT) {
68398 }
68399#endif
68400
68401 /*
68402 * Unwind, restore valstack bottom and other book-keeping.
68403 */
68404
68405 DUK_ASSERT(thr->callstack_curr != NULL);
68406 DUK_ASSERT(thr->callstack_curr->parent == entry_act);
68407 DUK_ASSERT(thr->callstack_top == entry_callstack_top + 1);
68409 DUK_ASSERT(thr->callstack_curr == entry_act);
68410 DUK_ASSERT(thr->callstack_top == entry_callstack_top);
68411
68412 thr->valstack_bottom = (duk_tval *) (void *) ((duk_uint8_t *) thr->valstack + entry_valstack_bottom_byteoff);
68413 /* keep current valstack_top */
68414 DUK_ASSERT(thr->valstack_bottom >= thr->valstack);
68416 DUK_ASSERT(thr->valstack_end >= thr->valstack_top);
68417 DUK_ASSERT(thr->valstack_top - thr->valstack_bottom >= idx_func + 1);
68418
68419 /* Return value handling. */
68420
68421 /* [ ... func this (crud) retval ] */
68422
68423 {
68424 duk_tval *tv_ret;
68425 duk_tval *tv_funret;
68426
68427 tv_ret = thr->valstack_bottom + idx_func;
68428 tv_funret = thr->valstack_top - 1;
68429#if defined(DUK_USE_FASTINT)
68430 /* Explicit check for fastint downgrade. */
68432#endif
68433 DUK_TVAL_SET_TVAL_UPDREF(thr, tv_ret, tv_funret); /* side effects */
68434 }
68435
68436 duk_set_top_unsafe(thr, idx_func + 1);
68437
68438 /* [ ... retval ] */
68439
68440 /* Restore caller's value stack reserve (cannot fail). */
68441 DUK_ASSERT((duk_uint8_t *) thr->valstack + entry_valstack_end_byteoff >= (duk_uint8_t *) thr->valstack_top);
68442 DUK_ASSERT((duk_uint8_t *) thr->valstack + entry_valstack_end_byteoff <= (duk_uint8_t *) thr->valstack_alloc_end);
68443 thr->valstack_end = (duk_tval *) (void *) ((duk_uint8_t *) thr->valstack + entry_valstack_end_byteoff);
68444
68445 /* XXX: Trial value stack shrink would be OK here, but we'd need
68446 * to prevent side effects of the potential realloc.
68447 */
68448
68449 /* Restore entry thread executor curr_pc stack frame pointer. */
68450 thr->ptr_curr_pc = entry_ptr_curr_pc;
68451
68452 DUK_HEAP_SWITCH_THREAD(thr->heap, entry_curr_thread); /* may be NULL */
68453 thr->state = (duk_uint8_t) entry_thread_state;
68454
68455 /* Disabled assert: triggered with some torture tests. */
68456#if 0
68457 DUK_ASSERT((thr->state == DUK_HTHREAD_STATE_INACTIVE && thr->heap->curr_thread == NULL) || /* first call */
68458 (thr->state == DUK_HTHREAD_STATE_INACTIVE && thr->heap->curr_thread != NULL) || /* other call */
68459 (thr->state == DUK_HTHREAD_STATE_RUNNING && thr->heap->curr_thread == thr)); /* current thread */
68460#endif
68461
68462 thr->heap->call_recursion_depth = entry_call_recursion_depth;
68463
68464 /* If the debugger is active we need to force an interrupt so that
68465 * debugger breakpoints are rechecked. This is important for function
68466 * calls caused by side effects (e.g. when doing a DUK_OP_GETPROP), see
68467 * GH-303. Only needed for success path, error path always causes a
68468 * breakpoint recheck in the executor. It would be enough to set this
68469 * only when returning to an ECMAScript activation, but setting the flag
68470 * on every return should have no ill effect.
68471 */
68472#if defined(DUK_USE_DEBUGGER_SUPPORT)
68473 if (duk_debug_is_attached(thr->heap)) {
68474 DUK_DD(DUK_DDPRINT("returning with debugger enabled, force interrupt"));
68476 thr->interrupt_init -= thr->interrupt_counter;
68477 thr->interrupt_counter = 0;
68478 thr->heap->dbg_force_restart = 1;
68479 }
68480#endif
68481
68482#if defined(DUK_USE_INTERRUPT_COUNTER) && defined(DUK_USE_DEBUG)
68483 duk__interrupt_fixup(thr, entry_curr_thread);
68484#endif
68485
68486 /* Restored by success path. */
68487 DUK_ASSERT(thr->heap->call_recursion_depth == entry_call_recursion_depth);
68488 DUK_ASSERT(thr->ptr_curr_pc == entry_ptr_curr_pc);
68490
68492
68493 return 0; /* 0=call handled inline */
68494}
68495
68497 duk_idx_t idx_func;
68498 DUK_ASSERT(duk_get_top(thr) >= nargs + 2);
68499 idx_func = duk_get_top(thr) - (nargs + 2);
68500 DUK_ASSERT(idx_func >= 0);
68501 return duk_handle_call_unprotected(thr, idx_func, call_flags);
68502}
68503
68505 DUK_ASSERT(duk_is_valid_index(thr, idx_func));
68506 DUK_ASSERT(idx_func >= 0);
68507 return duk__handle_call_raw(thr, idx_func, call_flags);
68508}
68509
68510/*
68511 * duk_handle_safe_call(): make a "C protected call" within the
68512 * current activation.
68513 *
68514 * The allowed thread states for making a call are the same as for
68515 * duk_handle_call_protected().
68516 *
68517 * Even though this call is protected, errors are thrown for insane arguments
68518 * and may result in a fatal error unless there's another protected call which
68519 * catches such errors.
68520 *
68521 * The error handling path should be error free, even for out-of-memory
68522 * errors, to ensure safe sandboxing. (As of Duktape 2.2.0 this is not
68523 * yet the case for environment closing which may run out of memory, see
68524 * XXX notes below.)
68525 */
68526
68529 void *udata,
68530#if defined(DUK_USE_ASSERTIONS)
68531 duk_size_t entry_valstack_bottom_byteoff,
68532 duk_size_t entry_callstack_top,
68533#endif
68534 duk_hthread *entry_curr_thread,
68535 duk_uint_fast8_t entry_thread_state,
68536 duk_idx_t idx_retbase,
68537 duk_idx_t num_stack_rets) {
68538 duk_ret_t rc;
68539
68540 DUK_ASSERT(thr != NULL);
68542
68543 /*
68544 * Thread state check and book-keeping.
68545 */
68546
68548
68549 /*
68550 * Recursion limit check.
68551 */
68552
68554 thr->heap->call_recursion_depth++;
68555
68556 /*
68557 * Make the C call.
68558 */
68559
68560 rc = func(thr, udata);
68561
68562 DUK_DDD(DUK_DDDPRINT("safe_call, func rc=%ld", (long) rc));
68563
68564 /*
68565 * Valstack manipulation for results.
68566 */
68568 /* we're running inside the caller's activation, so no change in call/catch stack or valstack bottom */
68569 DUK_ASSERT(thr->callstack_top == entry_callstack_top);
68570 DUK_ASSERT(thr->valstack_bottom >= thr->valstack);
68571 DUK_ASSERT((duk_size_t) ((duk_uint8_t *) thr->valstack_bottom - (duk_uint8_t *) thr->valstack) ==
68572 entry_valstack_bottom_byteoff);
68574 DUK_ASSERT(thr->valstack_end >= thr->valstack_top);
68575
68576 if (DUK_UNLIKELY(rc < 0)) {
68578 DUK_WO_NORETURN(return;);
68579 }
68580 DUK_ASSERT(rc >= 0);
68581
68582 duk__safe_call_adjust_valstack(thr, idx_retbase, num_stack_rets, rc); /* throws for insane rc */
68583
68584 DUK_HEAP_SWITCH_THREAD(thr->heap, entry_curr_thread); /* may be NULL */
68585 thr->state = (duk_uint8_t) entry_thread_state;
68586}
68587
68589 duk_activation *entry_act,
68590#if defined(DUK_USE_ASSERTIONS)
68591 duk_size_t entry_callstack_top,
68592#endif
68593 duk_hthread *entry_curr_thread,
68594 duk_uint_fast8_t entry_thread_state,
68595 duk_idx_t idx_retbase,
68596 duk_idx_t num_stack_rets,
68597 duk_size_t entry_valstack_bottom_byteoff,
68598 duk_jmpbuf *old_jmpbuf_ptr) {
68599 DUK_ASSERT(thr != NULL);
68601
68602 /*
68603 * Error during call. The error value is at heap->lj.value1.
68604 *
68605 * The very first thing we do is restore the previous setjmp catcher.
68606 * This means that any error in error handling will propagate outwards
68607 * instead of causing a setjmp() re-entry above.
68608 */
68609
68610 DUK_DDD(DUK_DDDPRINT("error caught during protected duk_handle_safe_call()"));
68611
68612 /* Other longjmp types are handled by executor before propagating
68613 * the error here.
68614 */
68617
68618 /* Either pointer may be NULL (at entry), so don't assert. */
68619 thr->heap->lj.jmpbuf_ptr = old_jmpbuf_ptr;
68620
68621 /* XXX: callstack unwind may now throw an error when closing
68622 * scopes; this is a sandboxing issue, described in:
68623 * https://github.com/svaarala/duktape/issues/476
68624 */
68625 /* XXX: "unwind to" primitive? */
68626
68627 DUK_ASSERT(thr->callstack_top >= entry_callstack_top);
68628 while (thr->callstack_curr != entry_act) {
68629 DUK_ASSERT(thr->callstack_curr != NULL);
68631 }
68632 DUK_ASSERT(thr->callstack_top == entry_callstack_top);
68633
68634 /* Switch active thread before any side effects to avoid a
68635 * dangling curr_thread pointer.
68636 */
68637 DUK_HEAP_SWITCH_THREAD(thr->heap, entry_curr_thread); /* may be NULL */
68638 thr->state = (duk_uint8_t) entry_thread_state;
68639
68640 DUK_ASSERT(thr->heap->curr_thread == entry_curr_thread);
68641 DUK_ASSERT(thr->state == entry_thread_state);
68642
68643 /* Restore valstack bottom. */
68644 thr->valstack_bottom = (duk_tval *) (void *) ((duk_uint8_t *) thr->valstack + entry_valstack_bottom_byteoff);
68645
68646 /* [ ... | (crud) ] */
68647
68648 /* XXX: ensure space in valstack (now relies on internal reserve)? */
68649 duk_push_tval(thr, &thr->heap->lj.value1);
68650
68651 /* [ ... | (crud) errobj ] */
68652
68653 DUK_ASSERT(duk_get_top(thr) >= 1); /* at least errobj must be on stack */
68654
68655 duk__safe_call_adjust_valstack(thr, idx_retbase, num_stack_rets, 1); /* 1 = num actual 'return values' */
68656
68657 /* [ ... | ] or [ ... | errobj (M * undefined)] where M = num_stack_rets - 1 */
68658
68659 /* Reset longjmp state. */
68661 thr->heap->lj.iserror = 0;
68664
68665 /* Error handling complete, remove side effect protections. Caller
68666 * will process pending finalizers.
68667 */
68668#if defined(DUK_USE_ASSERTIONS)
68669 DUK_ASSERT(thr->heap->error_not_allowed == 1);
68670 thr->heap->error_not_allowed = 0;
68671#endif
68672 DUK_ASSERT(thr->heap->pf_prevent_count > 0);
68673 thr->heap->pf_prevent_count--;
68674 DUK_DD(DUK_DDPRINT("safe call error handled, pf_prevent_count updated to %ld", (long) thr->heap->pf_prevent_count));
68675
68676 /* thr->ptr_curr_pc is restored by
68677 * duk__handle_safe_call_shared_unwind() which is also used for
68678 * success path.
68679 */
68680}
68681
68683 duk_idx_t idx_retbase,
68684 duk_idx_t num_stack_rets,
68685#if defined(DUK_USE_ASSERTIONS)
68686 duk_size_t entry_callstack_top,
68687#endif
68688 duk_int_t entry_call_recursion_depth,
68689 duk_hthread *entry_curr_thread,
68690 duk_instr_t **entry_ptr_curr_pc) {
68691 DUK_ASSERT(thr != NULL);
68693 DUK_UNREF(idx_retbase);
68694 DUK_UNREF(num_stack_rets);
68695 DUK_UNREF(entry_curr_thread);
68696
68697 DUK_ASSERT(thr->callstack_top == entry_callstack_top);
68699 /* Restore entry thread executor curr_pc stack frame pointer.
68700 * XXX: would be enough to do in error path only, should nest
68701 * cleanly in success path.
68702 */
68703 thr->ptr_curr_pc = entry_ptr_curr_pc;
68704
68705 thr->heap->call_recursion_depth = entry_call_recursion_depth;
68706
68707 /* stack discipline consistency check */
68708 DUK_ASSERT(duk_get_top(thr) == idx_retbase + num_stack_rets);
68709
68710 /* A debugger forced interrupt check is not needed here, as
68711 * problematic safe calls are not caused by side effects.
68712 */
68713
68714#if defined(DUK_USE_INTERRUPT_COUNTER) && defined(DUK_USE_DEBUG)
68715 duk__interrupt_fixup(thr, entry_curr_thread);
68716#endif
68717}
68718
68721 void *udata,
68722 duk_idx_t num_stack_args,
68723 duk_idx_t num_stack_rets) {
68724 duk_activation *entry_act;
68725 duk_size_t entry_valstack_bottom_byteoff;
68726#if defined(DUK_USE_ASSERTIONS)
68727 duk_size_t entry_valstack_end_byteoff;
68728 duk_size_t entry_callstack_top;
68729 duk_size_t entry_callstack_preventcount;
68730#endif
68731 duk_int_t entry_call_recursion_depth;
68732 duk_hthread *entry_curr_thread;
68733 duk_uint_fast8_t entry_thread_state;
68734 duk_instr_t **entry_ptr_curr_pc;
68735 duk_jmpbuf *old_jmpbuf_ptr = NULL;
68736 duk_jmpbuf our_jmpbuf;
68737 duk_idx_t idx_retbase;
68738 duk_int_t retval;
68739
68740 DUK_ASSERT(thr != NULL);
68741 DUK_ASSERT(duk_get_top(thr) >= num_stack_args); /* Caller ensures. */
68742
68743 DUK_STATS_INC(thr->heap, stats_safecall_all);
68744
68745 /* Value stack reserve handling: safe call assumes caller has reserved
68746 * space for nrets (assuming optimal unwind processing). Value stack
68747 * reserve is not stored/restored as for normal calls because a safe
68748 * call conceptually happens in the same activation.
68749 */
68750
68751 /* Careful with indices like '-x'; if 'x' is zero, it refers to bottom */
68752 entry_act = thr->callstack_curr;
68753 entry_valstack_bottom_byteoff = (duk_size_t) ((duk_uint8_t *) thr->valstack_bottom - (duk_uint8_t *) thr->valstack);
68754#if defined(DUK_USE_ASSERTIONS)
68755 entry_valstack_end_byteoff = (duk_size_t) ((duk_uint8_t *) thr->valstack_end - (duk_uint8_t *) thr->valstack);
68756 entry_callstack_top = thr->callstack_top;
68757 entry_callstack_preventcount = thr->callstack_preventcount;
68758#endif
68759 entry_call_recursion_depth = thr->heap->call_recursion_depth;
68760 entry_curr_thread = thr->heap->curr_thread; /* may be NULL if first call */
68761 entry_thread_state = thr->state;
68762 entry_ptr_curr_pc = thr->ptr_curr_pc; /* may be NULL */
68763 idx_retbase = duk_get_top(thr) - num_stack_args; /* not a valid stack index if num_stack_args == 0 */
68764 DUK_ASSERT(idx_retbase >= 0);
68765
68766 DUK_ASSERT((duk_idx_t) (thr->valstack_top - thr->valstack_bottom) >= num_stack_args); /* Caller ensures. */
68767 DUK_ASSERT((duk_idx_t) (thr->valstack_end - (thr->valstack_bottom + idx_retbase)) >= num_stack_rets); /* Caller ensures. */
68768
68769 /* Cannot portably debug print a function pointer, hence 'func' not printed! */
68770 DUK_DD(DUK_DDPRINT("duk_handle_safe_call: thr=%p, num_stack_args=%ld, num_stack_rets=%ld, "
68771 "valstack_top=%ld, idx_retbase=%ld, rec_depth=%ld/%ld, "
68772 "entry_act=%p, entry_valstack_bottom_byteoff=%ld, entry_call_recursion_depth=%ld, "
68773 "entry_curr_thread=%p, entry_thread_state=%ld",
68774 (void *) thr,
68775 (long) num_stack_args,
68776 (long) num_stack_rets,
68777 (long) duk_get_top(thr),
68778 (long) idx_retbase,
68779 (long) thr->heap->call_recursion_depth,
68780 (long) thr->heap->call_recursion_limit,
68781 (void *) entry_act,
68782 (long) entry_valstack_bottom_byteoff,
68783 (long) entry_call_recursion_depth,
68784 (void *) entry_curr_thread,
68785 (long) entry_thread_state));
68786
68787 /* Setjmp catchpoint setup. */
68788 old_jmpbuf_ptr = thr->heap->lj.jmpbuf_ptr;
68789 thr->heap->lj.jmpbuf_ptr = &our_jmpbuf;
68790
68791 /* Prevent yields for the duration of the safe call. This only
68792 * matters if the executor makes safe calls to functions that
68793 * yield, this doesn't currently happen.
68794 */
68795 thr->callstack_preventcount++;
68796
68797#if defined(DUK_USE_CPP_EXCEPTIONS)
68798 try {
68799#else
68800 DUK_ASSERT(thr->heap->lj.jmpbuf_ptr == &our_jmpbuf);
68801 if (DUK_SETJMP(our_jmpbuf.jb) == 0) {
68802 /* Success path. */
68803#endif
68804 DUK_DDD(DUK_DDDPRINT("safe_call setjmp catchpoint setup complete"));
68805
68807 func,
68808 udata,
68809#if defined(DUK_USE_ASSERTIONS)
68810 entry_valstack_bottom_byteoff,
68811 entry_callstack_top,
68812#endif
68813 entry_curr_thread,
68814 entry_thread_state,
68815 idx_retbase,
68816 num_stack_rets);
68817
68818 DUK_STATS_INC(thr->heap, stats_safecall_nothrow);
68819
68820 /* Either pointer may be NULL (at entry), so don't assert */
68821 thr->heap->lj.jmpbuf_ptr = old_jmpbuf_ptr;
68822
68823 /* If calls happen inside the safe call, these are restored by
68824 * whatever calls are made. Reserve cannot decrease.
68825 */
68826 DUK_ASSERT(thr->callstack_curr == entry_act);
68827 DUK_ASSERT((duk_size_t) ((duk_uint8_t *) thr->valstack_end - (duk_uint8_t *) thr->valstack) >=
68828 entry_valstack_end_byteoff);
68829
68830 retval = DUK_EXEC_SUCCESS;
68831#if defined(DUK_USE_CPP_EXCEPTIONS)
68832 } catch (duk_internal_exception &exc) {
68833 DUK_UNREF(exc);
68834#else
68835 } else {
68836 /* Error path. */
68837#endif
68838 DUK_ASSERT((duk_size_t) ((duk_uint8_t *) thr->valstack_end - (duk_uint8_t *) thr->valstack) >=
68839 entry_valstack_end_byteoff);
68840
68841 DUK_STATS_INC(thr->heap, stats_safecall_throw);
68842
68844 entry_act,
68845#if defined(DUK_USE_ASSERTIONS)
68846 entry_callstack_top,
68847#endif
68848 entry_curr_thread,
68849 entry_thread_state,
68850 idx_retbase,
68851 num_stack_rets,
68852 entry_valstack_bottom_byteoff,
68853 old_jmpbuf_ptr);
68854
68855 retval = DUK_EXEC_ERROR;
68856 }
68857#if defined(DUK_USE_CPP_EXCEPTIONS)
68858 catch (duk_fatal_exception &exc) {
68859 DUK_D(DUK_DPRINT("rethrow duk_fatal_exception"));
68860 DUK_UNREF(exc);
68861 throw;
68862 } catch (std::exception &exc) {
68863 const char *what = exc.what();
68864 DUK_ASSERT((duk_size_t) ((duk_uint8_t *) thr->valstack_end - (duk_uint8_t *) thr->valstack) >=
68865 entry_valstack_end_byteoff);
68866 DUK_STATS_INC(thr->heap, stats_safecall_throw);
68867 if (!what) {
68868 what = "unknown";
68869 }
68870 DUK_D(DUK_DPRINT("unexpected c++ std::exception (perhaps thrown by user code)"));
68871 try {
68872 DUK_ERROR_FMT1(thr,
68874 "caught invalid c++ std::exception '%s' (perhaps thrown by user code)",
68875 what);
68876 DUK_WO_NORETURN(return 0;);
68877 } catch (duk_internal_exception exc) {
68878 DUK_D(DUK_DPRINT("caught api error thrown from unexpected c++ std::exception"));
68879 DUK_UNREF(exc);
68881 entry_act,
68882#if defined(DUK_USE_ASSERTIONS)
68883 entry_callstack_top,
68884#endif
68885 entry_curr_thread,
68886 entry_thread_state,
68887 idx_retbase,
68888 num_stack_rets,
68889 entry_valstack_bottom_byteoff,
68890 old_jmpbuf_ptr);
68891 retval = DUK_EXEC_ERROR;
68892 }
68893 } catch (...) {
68894 DUK_D(DUK_DPRINT("unexpected c++ exception (perhaps thrown by user code)"));
68895 DUK_ASSERT((duk_size_t) ((duk_uint8_t *) thr->valstack_end - (duk_uint8_t *) thr->valstack) >=
68896 entry_valstack_end_byteoff);
68897 DUK_STATS_INC(thr->heap, stats_safecall_throw);
68898 try {
68899 DUK_ERROR_TYPE(thr, "caught invalid c++ exception (perhaps thrown by user code)");
68900 DUK_WO_NORETURN(return 0;);
68901 } catch (duk_internal_exception exc) {
68902 DUK_D(DUK_DPRINT("caught api error thrown from unexpected c++ exception"));
68903 DUK_UNREF(exc);
68905 entry_act,
68906#if defined(DUK_USE_ASSERTIONS)
68907 entry_callstack_top,
68908#endif
68909 entry_curr_thread,
68910 entry_thread_state,
68911 idx_retbase,
68912 num_stack_rets,
68913 entry_valstack_bottom_byteoff,
68914 old_jmpbuf_ptr);
68915 retval = DUK_EXEC_ERROR;
68916 }
68917 }
68918#endif
68919
68920 DUK_ASSERT(thr->heap->lj.jmpbuf_ptr == old_jmpbuf_ptr); /* success/error path both do this */
68921
68922 DUK_ASSERT_LJSTATE_UNSET(thr->heap);
68923
68924 DUK_ASSERT((duk_size_t) ((duk_uint8_t *) thr->valstack_end - (duk_uint8_t *) thr->valstack) >= entry_valstack_end_byteoff);
68926 idx_retbase,
68927 num_stack_rets,
68928#if defined(DUK_USE_ASSERTIONS)
68929 entry_callstack_top,
68930#endif
68931 entry_call_recursion_depth,
68932 entry_curr_thread,
68933 entry_ptr_curr_pc);
68934
68935 /* Restore preventcount. */
68936 thr->callstack_preventcount--;
68937 DUK_ASSERT(thr->callstack_preventcount == entry_callstack_preventcount);
68938
68939 /* Final asserts. */
68940 DUK_ASSERT(thr->callstack_curr == entry_act);
68941 DUK_ASSERT((duk_size_t) ((duk_uint8_t *) thr->valstack_bottom - (duk_uint8_t *) thr->valstack) ==
68942 entry_valstack_bottom_byteoff);
68943 DUK_ASSERT((duk_size_t) ((duk_uint8_t *) thr->valstack_end - (duk_uint8_t *) thr->valstack) >= entry_valstack_end_byteoff);
68944 DUK_ASSERT(thr->callstack_top == entry_callstack_top);
68945 DUK_ASSERT(thr->heap->call_recursion_depth == entry_call_recursion_depth);
68946 DUK_ASSERT(thr->heap->curr_thread == entry_curr_thread);
68947 DUK_ASSERT(thr->state == entry_thread_state);
68948 DUK_ASSERT(thr->ptr_curr_pc == entry_ptr_curr_pc);
68949 DUK_ASSERT(duk_get_top(thr) == idx_retbase + num_stack_rets);
68950 DUK_ASSERT_LJSTATE_UNSET(thr->heap);
68951
68952 /* Pending side effects. */
68954
68955 return retval;
68956}
68957
68958/*
68959 * Property-based call (foo.noSuch()) error setup: replace target function
68960 * on stack top with a hidden Symbol tagged non-callable wrapper object
68961 * holding the error. The error gets thrown in call handling at the
68962 * proper spot to follow ECMAScript semantics.
68963 */
68964
68965#if defined(DUK_USE_VERBOSE_ERRORS)
68967 const char *str_targ, *str_key, *str_base;
68968 duk_idx_t entry_top;
68969
68970 entry_top = duk_get_top(thr);
68971
68972 /* [ <nargs> target ] */
68973
68974 /* Must stabilize pointers first. tv_targ is already on stack top. */
68975 duk_push_tval(thr, tv_base);
68976 duk_push_tval(thr, tv_key);
68977
68978 DUK_GC_TORTURE(thr->heap);
68979
68981
68982 /* [ <nargs> target base key {} ] */
68983
68984 /* We only push a wrapped error, replacing the call target (at
68985 * idx_func) with the error to ensure side effects come out
68986 * correctly:
68987 * - Property read
68988 * - Call argument evaluation
68989 * - Callability check and error thrown
68990 *
68991 * A hidden Symbol on the wrapper object pushed above is used by
68992 * call handling to figure out the error is to be thrown as is.
68993 * It is CRITICAL that the hidden Symbol can never occur on a
68994 * user visible object that may get thrown.
68995 */
68996
68997#if defined(DUK_USE_PARANOID_ERRORS)
68998 str_targ = duk_get_type_name(thr, -4);
68999 str_key = duk_get_type_name(thr, -2);
69000 str_base = duk_get_type_name(thr, -3);
69003 "%s not callable (property %s of %s)",
69004 str_targ,
69005 str_key,
69006 str_base);
69007 duk_xdef_prop_stridx(thr, -2, DUK_STRIDX_INT_TARGET, DUK_PROPDESC_FLAGS_NONE); /* Marker property, reuse _Target. */
69008 /* [ <nargs> target base key { _Target: error } ] */
69009 duk_replace(thr, entry_top - 1);
69010#else
69011 str_targ = duk_push_string_readable(thr, -4);
69012 str_key = duk_push_string_readable(thr, -3);
69013 str_base = duk_push_string_readable(thr, -5);
69016 "%s not callable (property %s of %s)",
69017 str_targ,
69018 str_key,
69019 str_base);
69020 /* [ <nargs> target base key {} str_targ str_key str_base error ] */
69021 duk_xdef_prop_stridx(thr, -5, DUK_STRIDX_INT_TARGET, DUK_PROPDESC_FLAGS_NONE); /* Marker property, reuse _Target. */
69022 /* [ <nargs> target base key { _Target: error } str_targ str_key str_base ] */
69023 duk_swap(thr, -4, entry_top - 1);
69024 /* [ <nargs> { _Target: error } base key target str_targ str_key str_base ] */
69025#endif
69026
69027 /* [ <nregs> { _Target: error } <variable> */
69028 duk_set_top(thr, entry_top);
69029
69030 /* [ <nregs> { _Target: error } */
69031 DUK_ASSERT(!duk_is_callable(thr, -1)); /* Critical so that call handling will throw the error. */
69032}
69033#endif /* DUK_USE_VERBOSE_ERRORS */
69034
69035/* automatic undefs */
69036#undef DUK__AUGMENT_CALL_RELAX_COUNT
69037#undef DUK__CALL_HANDLING_REQUIRE_STACK
69038/*
69039 * ECMAScript compiler.
69040 *
69041 * Parses an input string and generates a function template result.
69042 * Compilation may happen in multiple contexts (global code, eval
69043 * code, function code).
69044 *
69045 * The parser uses a traditional top-down recursive parsing for the
69046 * statement level, and an operator precedence based top-down approach
69047 * for the expression level. The attempt is to minimize the C stack
69048 * depth. Bytecode is generated directly without an intermediate
69049 * representation (tree), at the cost of needing two (and sometimes
69050 * three) passes over each function.
69051 *
69052 * The top-down recursive parser functions are named "duk__parse_XXX".
69054 * Recursion limits are in key functions to prevent arbitrary C recursion:
69055 * function body parsing, statement parsing, and expression parsing.
69057 * See doc/compiler.rst for discussion on the design.
69058 *
69059 * A few typing notes:
69061 * - duk_regconst_t: signed, highest bit set (< 0) means constant,
69062 * some call sites use -1 for "none" (equivalent to constant 0x7fffffff)
69063 * - PC values: duk_int_t, negative values used as markers
69066/* #include duk_internal.h -> already included */
69068/* If highest bit of a register number is set, it refers to a constant instead.
69069 * When interpreted as a signed value, this means const values are always
69070 * negative (when interpreted as two's complement). For example DUK__ISREG_TEMP()
69071 * uses this approach to avoid an explicit DUK__ISREG() check (the condition is
69072 * logically "'x' is a register AND 'x' >= temp_first").
69073 */
69074#define DUK__CONST_MARKER DUK_REGCONST_CONST_MARKER
69075#define DUK__REMOVECONST(x) ((x) & ~DUK__CONST_MARKER)
69076#define DUK__ISREG(x) ((x) >= 0)
69077#define DUK__ISCONST(x) ((x) < 0)
69078#define DUK__ISREG_TEMP(comp_ctx, x) \
69079 ((duk_int32_t) (x) >= \
69080 (duk_int32_t) ((comp_ctx)->curr_func.temp_first)) /* Check for x >= temp_first && x >= 0 by comparing as signed. */
69081#define DUK__ISREG_NOTTEMP(comp_ctx, x) \
69082 ((duk_uint32_t) (x) < \
69083 (duk_uint32_t) ((comp_ctx)->curr_func.temp_first)) /* Check for x >= 0 && x < temp_first by interpreting as unsigned. */
69084#define DUK__GETTEMP(comp_ctx) ((comp_ctx)->curr_func.temp_next)
69085#define DUK__SETTEMP(comp_ctx, x) ((comp_ctx)->curr_func.temp_next = (x)) /* dangerous: must only lower (temp_max not updated) */
69086#define DUK__SETTEMP_CHECKMAX(comp_ctx, x) duk__settemp_checkmax((comp_ctx), (x))
69087#define DUK__ALLOCTEMP(comp_ctx) duk__alloctemp((comp_ctx))
69088#define DUK__ALLOCTEMPS(comp_ctx, count) duk__alloctemps((comp_ctx), (count))
69089
69090/* Init value set size for array and object literals. */
69091#define DUK__MAX_ARRAY_INIT_VALUES 20
69092#define DUK__MAX_OBJECT_INIT_PAIRS 10
69093
69094/* XXX: hack, remove when const lookup is not O(n) */
69095#define DUK__GETCONST_MAX_CONSTS_CHECK 256
69097/* These limits are based on bytecode limits. Max temps is limited
69098 * by duk_hcompfunc nargs/nregs fields being 16 bits.
69099 */
69100#define DUK__MAX_CONSTS DUK_BC_BC_MAX
69101#define DUK__MAX_FUNCS DUK_BC_BC_MAX
69102#define DUK__MAX_TEMPS 0xffffL
69103
69104/* Initial bytecode size allocation. */
69105#if defined(DUK_USE_PREFER_SIZE)
69106#define DUK__BC_INITIAL_INSTS 16
69107#else
69108#define DUK__BC_INITIAL_INSTS 256
69109#endif
69110
69111#define DUK__RECURSION_INCREASE(comp_ctx, thr) \
69112 do { \
69113 DUK_DDD(DUK_DDDPRINT("RECURSION INCREASE: %s:%ld", (const char *) DUK_FILE_MACRO, (long) DUK_LINE_MACRO)); \
69114 duk__comp_recursion_increase((comp_ctx)); \
69115 } while (0)
69117#define DUK__RECURSION_DECREASE(comp_ctx, thr) \
69118 do { \
69119 DUK_DDD(DUK_DDDPRINT("RECURSION DECREASE: %s:%ld", (const char *) DUK_FILE_MACRO, (long) DUK_LINE_MACRO)); \
69120 duk__comp_recursion_decrease((comp_ctx)); \
69121 } while (0)
69122
69123/* Value stack slot limits: these are quite approximate right now, and
69124 * because they overlap in control flow, some could be eliminated.
69125 */
69126#define DUK__COMPILE_ENTRY_SLOTS 8
69127#define DUK__FUNCTION_INIT_REQUIRE_SLOTS 16
69128#define DUK__FUNCTION_BODY_REQUIRE_SLOTS 16
69129#define DUK__PARSE_STATEMENTS_SLOTS 16
69130#define DUK__PARSE_EXPR_SLOTS 16
69131
69132/* Temporary structure used to pass a stack allocated region through
69133 * duk_safe_call().
69134 */
69135typedef struct {
69136 duk_small_uint_t flags;
69137 duk_compiler_ctx comp_ctx_alloc;
69138 duk_lexer_point lex_pt_alloc;
69140
69141/*
69142 * Prototypes
69143 */
69144
69145/* lexing */
69149
69150/* function helpers */
69156
69157/* code emission */
69163 duk_small_uint_t op_flags,
69166 duk_regconst_t c);
69169#if 0 /* unused */
69170DUK_LOCAL_DECL void duk__emit_a(duk_compiler_ctx *comp_ctx, duk_small_uint_t op_flags, duk_regconst_t a);
69171DUK_LOCAL_DECL void duk__emit_b(duk_compiler_ctx *comp_ctx, duk_small_uint_t op_flags, duk_regconst_t b);
69172#endif
69176DUK_LOCAL_DECL void duk__emit_load_int32(duk_compiler_ctx *comp_ctx, duk_regconst_t reg, duk_int32_t val);
69178DUK_LOCAL_DECL void duk__emit_jump(duk_compiler_ctx *comp_ctx, duk_int_t target_pc);
69181DUK_LOCAL_DECL void duk__patch_jump(duk_compiler_ctx *comp_ctx, duk_int_t jump_pc, duk_int_t target_pc);
69184 duk_int_t ldconst_pc,
69185 duk_int_t trycatch_pc,
69186 duk_regconst_t reg_catch,
69187 duk_regconst_t const_varname,
69188 duk_small_uint_t flags);
69192
69193/* ivalue/ispec helpers */
69206 duk_ispec *x,
69207 duk_regconst_t forced_reg,
69208 duk_small_uint_t flags);
69215 duk_ivalue *x,
69216 duk_regconst_t forced_reg,
69217 duk_small_uint_t flags);
69219#if 0 /* unused */
69220DUK_LOCAL_DECL duk_regconst_t duk__ivalue_totemp(duk_compiler_ctx *comp_ctx, duk_ivalue *x);
69221#endif
69225
69226/* identifier handling */
69229
69230/* label handling */
69231DUK_LOCAL_DECL void duk__add_label(duk_compiler_ctx *comp_ctx, duk_hstring *h_label, duk_int_t pc_label, duk_int_t label_id);
69234 duk_hstring *h_label,
69235 duk_bool_t is_break,
69236 duk_int_t *out_label_id,
69237 duk_int_t *out_label_catch_depth,
69238 duk_int_t *out_label_pc,
69239 duk_bool_t *out_is_closest);
69241
69242/* top-down expression parser */
69247
69248/* exprtop is the top level variant which resets nud/led counts */
69251
69252/* convenience helpers */
69253#if 0 /* unused */
69254DUK_LOCAL_DECL duk_regconst_t duk__expr_toreg(duk_compiler_ctx *comp_ctx, duk_ivalue *res, duk_small_uint_t rbp_flags);
69255#endif
69256#if 0 /* unused */
69257DUK_LOCAL_DECL duk_regconst_t duk__expr_totemp(duk_compiler_ctx *comp_ctx, duk_ivalue *res, duk_small_uint_t rbp_flags);
69258#endif
69260 duk_ivalue *res,
69261 duk_small_uint_t rbp_flags,
69262 duk_regconst_t forced_reg);
69264#if 0 /* unused */
69265DUK_LOCAL_DECL duk_regconst_t duk__expr_totempconst(duk_compiler_ctx *comp_ctx, duk_ivalue *res, duk_small_uint_t rbp_flags);
69266#endif
69270#if 0 /* unused */
69271DUK_LOCAL_DECL duk_regconst_t duk__exprtop_totemp(duk_compiler_ctx *comp_ctx, duk_ivalue *res, duk_small_uint_t rbp_flags);
69272#endif
69274 duk_ivalue *res,
69275 duk_small_uint_t rbp_flags,
69276 duk_regconst_t forced_reg);
69278#if 0 /* unused */
69279DUK_LOCAL_DECL void duk__exprtop_toplain_ignore(duk_compiler_ctx *comp_ctx, duk_ivalue *res, duk_small_uint_t rbp_flags);
69280#endif
69281
69282/* expression parsing helpers */
69286
69287/* statement parsing */
69289 duk_ivalue *res,
69290 duk_small_uint_t expr_flags,
69291 duk_regconst_t *out_reg_varbind,
69292 duk_regconst_t *out_rc_varname);
69294DUK_LOCAL_DECL void duk__parse_for_stmt(duk_compiler_ctx *comp_ctx, duk_ivalue *res, duk_int_t pc_label_site);
69297DUK_LOCAL_DECL void duk__parse_do_stmt(duk_compiler_ctx *comp_ctx, duk_ivalue *res, duk_int_t pc_label_site);
69298DUK_LOCAL_DECL void duk__parse_while_stmt(duk_compiler_ctx *comp_ctx, duk_ivalue *res, duk_int_t pc_label_site);
69304DUK_LOCAL_DECL void duk__parse_stmt(duk_compiler_ctx *comp_ctx, duk_ivalue *res, duk_bool_t allow_source_elem);
69307 duk_bool_t allow_source_elem,
69308 duk_bool_t expect_eof,
69309 duk_bool_t regexp_after);
69310
69312 duk_bool_t expect_eof,
69313 duk_bool_t implicit_return_value,
69314 duk_bool_t regexp_after,
69315 duk_small_int_t expect_token);
69319
69320#define DUK__FUNC_FLAG_DECL (1 << 0) /* Parsing a function declaration. */
69321#define DUK__FUNC_FLAG_GETSET (1 << 1) /* Parsing an object literal getter/setter. */
69322#define DUK__FUNC_FLAG_METDEF (1 << 2) /* Parsing an object literal method definition shorthand. */
69323#define DUK__FUNC_FLAG_PUSHNAME_PASS1 (1 << 3) /* Push function name when creating template (first pass only). */
69324#define DUK__FUNC_FLAG_USE_PREVTOKEN (1 << 4) /* Use prev_token to start function parsing (workaround for object literal). */
69327 * Parser control values for tokens. The token table is ordered by the
69328 * DUK_TOK_XXX defines.
69330 * The binding powers are for lbp() use (i.e. for use in led() context).
69331 * Binding powers are positive for typing convenience, and bits at the
69332 * top should be reserved for flags. Binding power step must be higher
69333 * than 1 so that binding power "lbp - 1" can be used for right associative
69334 * operators. Currently a step of 2 is used (which frees one more bit for
69335 * flags).
69338/* XXX: actually single step levels would work just fine, clean up */
69340/* binding power "levels" (see doc/compiler.rst) */
69341#define DUK__BP_INVALID 0 /* always terminates led() */
69342#define DUK__BP_EOF 2
69343#define DUK__BP_CLOSING 4 /* token closes expression, e.g. ')', ']' */
69344#define DUK__BP_FOR_EXPR DUK__BP_CLOSING /* bp to use when parsing a top level Expression */
69345#define DUK__BP_COMMA 6
69346#define DUK__BP_ASSIGNMENT 8
69347#define DUK__BP_CONDITIONAL 10
69348#define DUK__BP_LOR 12
69349#define DUK__BP_LAND 14
69350#define DUK__BP_BOR 16
69351#define DUK__BP_BXOR 18
69352#define DUK__BP_BAND 20
69353#define DUK__BP_EQUALITY 22
69354#define DUK__BP_RELATIONAL 24
69355#define DUK__BP_SHIFT 26
69356#define DUK__BP_ADDITIVE 28
69357#define DUK__BP_MULTIPLICATIVE 30
69358#define DUK__BP_EXPONENTIATION 32
69359#define DUK__BP_POSTFIX 34
69360#define DUK__BP_CALL 36
69361#define DUK__BP_MEMBER 38
69362
69363#define DUK__TOKEN_LBP_BP_MASK 0x1f
69364#define DUK__TOKEN_LBP_FLAG_NO_REGEXP (1 << 5) /* regexp literal must not follow this token */
69365#define DUK__TOKEN_LBP_FLAG_TERMINATES (1 << 6) /* terminates expression; e.g. post-increment/-decrement */
69366#define DUK__TOKEN_LBP_FLAG_UNUSED (1 << 7) /* unused */
69367
69368#define DUK__TOKEN_LBP_GET_BP(x) ((duk_small_uint_t) (((x) &DUK__TOKEN_LBP_BP_MASK) * 2))
69369
69370#define DUK__MK_LBP(bp) ((bp) >> 1) /* bp is assumed to be even */
69371#define DUK__MK_LBP_FLAGS(bp, flags) (((bp) >> 1) | (flags))
69372
69373DUK_LOCAL const duk_uint8_t duk__token_lbp[] = {
69374 DUK__MK_LBP(DUK__BP_EOF), /* DUK_TOK_EOF */
69376 DUK__MK_LBP(DUK__BP_INVALID), /* DUK_TOK_BREAK */
69377 DUK__MK_LBP(DUK__BP_INVALID), /* DUK_TOK_CASE */
69378 DUK__MK_LBP(DUK__BP_INVALID), /* DUK_TOK_CATCH */
69379 DUK__MK_LBP(DUK__BP_INVALID), /* DUK_TOK_CONTINUE */
69380 DUK__MK_LBP(DUK__BP_INVALID), /* DUK_TOK_DEBUGGER */
69381 DUK__MK_LBP(DUK__BP_INVALID), /* DUK_TOK_DEFAULT */
69382 DUK__MK_LBP(DUK__BP_INVALID), /* DUK_TOK_DELETE */
69383 DUK__MK_LBP(DUK__BP_INVALID), /* DUK_TOK_DO */
69384 DUK__MK_LBP(DUK__BP_INVALID), /* DUK_TOK_ELSE */
69385 DUK__MK_LBP(DUK__BP_INVALID), /* DUK_TOK_FINALLY */
69386 DUK__MK_LBP(DUK__BP_INVALID), /* DUK_TOK_FOR */
69387 DUK__MK_LBP(DUK__BP_INVALID), /* DUK_TOK_FUNCTION */
69388 DUK__MK_LBP(DUK__BP_INVALID), /* DUK_TOK_IF */
69389 DUK__MK_LBP(DUK__BP_RELATIONAL), /* DUK_TOK_IN */
69390 DUK__MK_LBP(DUK__BP_RELATIONAL), /* DUK_TOK_INSTANCEOF */
69391 DUK__MK_LBP(DUK__BP_INVALID), /* DUK_TOK_NEW */
69392 DUK__MK_LBP(DUK__BP_INVALID), /* DUK_TOK_RETURN */
69393 DUK__MK_LBP(DUK__BP_INVALID), /* DUK_TOK_SWITCH */
69395 DUK__MK_LBP(DUK__BP_INVALID), /* DUK_TOK_THROW */
69396 DUK__MK_LBP(DUK__BP_INVALID), /* DUK_TOK_TRY */
69397 DUK__MK_LBP(DUK__BP_INVALID), /* DUK_TOK_TYPEOF */
69398 DUK__MK_LBP(DUK__BP_INVALID), /* DUK_TOK_VAR */
69399 DUK__MK_LBP(DUK__BP_INVALID), /* DUK_TOK_CONST */
69400 DUK__MK_LBP(DUK__BP_INVALID), /* DUK_TOK_VOID */
69401 DUK__MK_LBP(DUK__BP_INVALID), /* DUK_TOK_WHILE */
69402 DUK__MK_LBP(DUK__BP_INVALID), /* DUK_TOK_WITH */
69403 DUK__MK_LBP(DUK__BP_INVALID), /* DUK_TOK_CLASS */
69404 DUK__MK_LBP(DUK__BP_INVALID), /* DUK_TOK_ENUM */
69405 DUK__MK_LBP(DUK__BP_INVALID), /* DUK_TOK_EXPORT */
69406 DUK__MK_LBP(DUK__BP_INVALID), /* DUK_TOK_EXTENDS */
69407 DUK__MK_LBP(DUK__BP_INVALID), /* DUK_TOK_IMPORT */
69408 DUK__MK_LBP(DUK__BP_INVALID), /* DUK_TOK_SUPER */
69412 DUK__MK_LBP(DUK__BP_INVALID), /* DUK_TOK_GET */
69413 DUK__MK_LBP(DUK__BP_INVALID), /* DUK_TOK_SET */
69414 DUK__MK_LBP(DUK__BP_INVALID), /* DUK_TOK_IMPLEMENTS */
69415 DUK__MK_LBP(DUK__BP_INVALID), /* DUK_TOK_INTERFACE */
69416 DUK__MK_LBP(DUK__BP_INVALID), /* DUK_TOK_LET */
69417 DUK__MK_LBP(DUK__BP_INVALID), /* DUK_TOK_PACKAGE */
69418 DUK__MK_LBP(DUK__BP_INVALID), /* DUK_TOK_PRIVATE */
69419 DUK__MK_LBP(DUK__BP_INVALID), /* DUK_TOK_PROTECTED */
69420 DUK__MK_LBP(DUK__BP_INVALID), /* DUK_TOK_PUBLIC */
69421 DUK__MK_LBP(DUK__BP_INVALID), /* DUK_TOK_STATIC */
69422 DUK__MK_LBP(DUK__BP_INVALID), /* DUK_TOK_YIELD */
69423 DUK__MK_LBP(DUK__BP_INVALID), /* DUK_TOK_LCURLY */
69425 DUK__MK_LBP(DUK__BP_MEMBER), /* DUK_TOK_LBRACKET */
69427 DUK__MK_LBP(DUK__BP_CALL), /* DUK_TOK_LPAREN */
69429 DUK__MK_LBP(DUK__BP_MEMBER), /* DUK_TOK_PERIOD */
69430 DUK__MK_LBP(DUK__BP_INVALID), /* DUK_TOK_SEMICOLON */
69431 DUK__MK_LBP(DUK__BP_COMMA), /* DUK_TOK_COMMA */
69432 DUK__MK_LBP(DUK__BP_RELATIONAL), /* DUK_TOK_LT */
69433 DUK__MK_LBP(DUK__BP_RELATIONAL), /* DUK_TOK_GT */
69434 DUK__MK_LBP(DUK__BP_RELATIONAL), /* DUK_TOK_LE */
69435 DUK__MK_LBP(DUK__BP_RELATIONAL), /* DUK_TOK_GE */
69436 DUK__MK_LBP(DUK__BP_EQUALITY), /* DUK_TOK_EQ */
69437 DUK__MK_LBP(DUK__BP_EQUALITY), /* DUK_TOK_NEQ */
69438 DUK__MK_LBP(DUK__BP_EQUALITY), /* DUK_TOK_SEQ */
69439 DUK__MK_LBP(DUK__BP_EQUALITY), /* DUK_TOK_SNEQ */
69440 DUK__MK_LBP(DUK__BP_ADDITIVE), /* DUK_TOK_ADD */
69441 DUK__MK_LBP(DUK__BP_ADDITIVE), /* DUK_TOK_SUB */
69442 DUK__MK_LBP(DUK__BP_MULTIPLICATIVE), /* DUK_TOK_MUL */
69443 DUK__MK_LBP(DUK__BP_MULTIPLICATIVE), /* DUK_TOK_DIV */
69444 DUK__MK_LBP(DUK__BP_MULTIPLICATIVE), /* DUK_TOK_MOD */
69445 DUK__MK_LBP(DUK__BP_EXPONENTIATION), /* DUK_TOK_EXP */
69448 DUK__MK_LBP(DUK__BP_SHIFT), /* DUK_TOK_ALSHIFT */
69449 DUK__MK_LBP(DUK__BP_SHIFT), /* DUK_TOK_ARSHIFT */
69450 DUK__MK_LBP(DUK__BP_SHIFT), /* DUK_TOK_RSHIFT */
69451 DUK__MK_LBP(DUK__BP_BAND), /* DUK_TOK_BAND */
69452 DUK__MK_LBP(DUK__BP_BOR), /* DUK_TOK_BOR */
69453 DUK__MK_LBP(DUK__BP_BXOR), /* DUK_TOK_BXOR */
69454 DUK__MK_LBP(DUK__BP_INVALID), /* DUK_TOK_LNOT */
69455 DUK__MK_LBP(DUK__BP_INVALID), /* DUK_TOK_BNOT */
69456 DUK__MK_LBP(DUK__BP_LAND), /* DUK_TOK_LAND */
69457 DUK__MK_LBP(DUK__BP_LOR), /* DUK_TOK_LOR */
69458 DUK__MK_LBP(DUK__BP_CONDITIONAL), /* DUK_TOK_QUESTION */
69459 DUK__MK_LBP(DUK__BP_INVALID), /* DUK_TOK_COLON */
69460 DUK__MK_LBP(DUK__BP_ASSIGNMENT), /* DUK_TOK_EQUALSIGN */
69461 DUK__MK_LBP(DUK__BP_ASSIGNMENT), /* DUK_TOK_ADD_EQ */
69462 DUK__MK_LBP(DUK__BP_ASSIGNMENT), /* DUK_TOK_SUB_EQ */
69463 DUK__MK_LBP(DUK__BP_ASSIGNMENT), /* DUK_TOK_MUL_EQ */
69464 DUK__MK_LBP(DUK__BP_ASSIGNMENT), /* DUK_TOK_DIV_EQ */
69465 DUK__MK_LBP(DUK__BP_ASSIGNMENT), /* DUK_TOK_MOD_EQ */
69466 DUK__MK_LBP(DUK__BP_ASSIGNMENT), /* DUK_TOK_EXP_EQ */
69467 DUK__MK_LBP(DUK__BP_ASSIGNMENT), /* DUK_TOK_ALSHIFT_EQ */
69468 DUK__MK_LBP(DUK__BP_ASSIGNMENT), /* DUK_TOK_ARSHIFT_EQ */
69469 DUK__MK_LBP(DUK__BP_ASSIGNMENT), /* DUK_TOK_RSHIFT_EQ */
69470 DUK__MK_LBP(DUK__BP_ASSIGNMENT), /* DUK_TOK_BAND_EQ */
69471 DUK__MK_LBP(DUK__BP_ASSIGNMENT), /* DUK_TOK_BOR_EQ */
69472 DUK__MK_LBP(DUK__BP_ASSIGNMENT), /* DUK_TOK_BXOR_EQ */
69476};
69478/*
69479 * Misc helpers
69480 */
69481
69483 DUK_ASSERT(comp_ctx != NULL);
69484 DUK_ASSERT(comp_ctx->recursion_depth >= 0);
69485 if (comp_ctx->recursion_depth >= comp_ctx->recursion_limit) {
69487 DUK_WO_NORETURN(return;);
69488 }
69489 comp_ctx->recursion_depth++;
69490}
69491
69493 DUK_ASSERT(comp_ctx != NULL);
69494 DUK_ASSERT(comp_ctx->recursion_depth > 0);
69495 comp_ctx->recursion_depth--;
69497
69499 DUK_UNREF(comp_ctx);
69500 DUK_ASSERT(h != NULL);
69502}
69503
69505 DUK_ASSERT(h != NULL);
69506 return (comp_ctx->curr_func.is_strict && DUK_HSTRING_HAS_EVAL_OR_ARGUMENTS(h));
69507}
69508
69509/*
69510 * Parser duk__advance() token eating functions
69511 */
69512
69513/* XXX: valstack handling is awkward. Add a valstack helper which
69514 * avoids dup():ing; valstack_copy(src, dst)?
69515 */
69516
69518 duk_hthread *thr = comp_ctx->thr;
69519 duk_bool_t regexp;
69520
69521 DUK_ASSERT_DISABLE(comp_ctx->curr_token.t >= 0); /* unsigned */
69522 DUK_ASSERT(comp_ctx->curr_token.t <= DUK_TOK_MAXVAL); /* MAXVAL is inclusive */
69523
69524 /*
69525 * Use current token to decide whether a RegExp can follow.
69526 *
69527 * We can use either 't' or 't_nores'; the latter would not
69528 * recognize keywords. Some keywords can be followed by a
69529 * RegExp (e.g. "return"), so using 't' is better. This is
69530 * not trivial, see doc/compiler.rst.
69531 */
69532
69533 regexp = 1;
69535 regexp = 0;
69536 }
69537 if (comp_ctx->curr_func.reject_regexp_in_adv) {
69538 comp_ctx->curr_func.reject_regexp_in_adv = 0;
69539 regexp = 0;
69540 }
69541 if (comp_ctx->curr_func.allow_regexp_in_adv) {
69542 comp_ctx->curr_func.allow_regexp_in_adv = 0;
69543 regexp = 1;
69544 }
69545
69546 if (expect >= 0 && comp_ctx->curr_token.t != (duk_small_uint_t) expect) {
69547 DUK_D(DUK_DPRINT("parse error: expect=%ld, got=%ld", (long) expect, (long) comp_ctx->curr_token.t));
69549 DUK_WO_NORETURN(return;);
69550 }
69551
69552 /* make current token the previous; need to fiddle with valstack "backing store" */
69553 duk_memcpy(&comp_ctx->prev_token, &comp_ctx->curr_token, sizeof(duk_token));
69554 duk_copy(thr, comp_ctx->tok11_idx, comp_ctx->tok21_idx);
69555 duk_copy(thr, comp_ctx->tok12_idx, comp_ctx->tok22_idx);
69557 /* parse new token */
69558 duk_lexer_parse_js_input_element(&comp_ctx->lex, &comp_ctx->curr_token, comp_ctx->curr_func.is_strict, regexp);
69559
69560 DUK_DDD(DUK_DDDPRINT("advance: curr: tok=%ld/%ld,%ld,term=%ld,%!T,%!T "
69561 "prev: tok=%ld/%ld,%ld,term=%ld,%!T,%!T",
69562 (long) comp_ctx->curr_token.t,
69563 (long) comp_ctx->curr_token.t_nores,
69564 (long) comp_ctx->curr_token.start_line,
69565 (long) comp_ctx->curr_token.lineterm,
69566 (duk_tval *) duk_get_tval(thr, comp_ctx->tok11_idx),
69567 (duk_tval *) duk_get_tval(thr, comp_ctx->tok12_idx),
69568 (long) comp_ctx->prev_token.t,
69569 (long) comp_ctx->prev_token.t_nores,
69570 (long) comp_ctx->prev_token.start_line,
69571 (long) comp_ctx->prev_token.lineterm,
69572 (duk_tval *) duk_get_tval(thr, comp_ctx->tok21_idx),
69573 (duk_tval *) duk_get_tval(thr, comp_ctx->tok22_idx)));
69574}
69575
69576/* advance, expecting current token to be a specific token; parse next token in regexp context */
69578 duk__advance_helper(comp_ctx, expect);
69579}
69580
69581/* advance, whatever the current token is; parse next token in regexp context */
69582DUK_LOCAL void duk__advance(duk_compiler_ctx *comp_ctx) {
69583 duk__advance_helper(comp_ctx, -1);
69584}
69585
69586/*
69587 * Helpers for duk_compiler_func.
69588 */
69589
69590/* init function state: inits valstack allocations */
69592 duk_compiler_func *func = &comp_ctx->curr_func;
69593 duk_hthread *thr = comp_ctx->thr;
69594 duk_idx_t entry_top;
69595
69596 entry_top = duk_get_top(thr);
69597
69598 duk_memzero(func, sizeof(*func)); /* intentional overlap with earlier memzero */
69599#if defined(DUK_USE_EXPLICIT_NULL_INIT)
69600 func->h_name = NULL;
69601 func->h_consts = NULL;
69602 func->h_funcs = NULL;
69603 func->h_decls = NULL;
69604 func->h_labelnames = NULL;
69605 func->h_labelinfos = NULL;
69606 func->h_argnames = NULL;
69607 func->h_varmap = NULL;
69608#endif
69609
69611
69613 /* code_idx = entry_top + 0 */
69614
69616 func->consts_idx = entry_top + 1;
69617 func->h_consts = DUK_GET_HOBJECT_POSIDX(thr, entry_top + 1);
69618 DUK_ASSERT(func->h_consts != NULL);
69619
69621 func->funcs_idx = entry_top + 2;
69622 func->h_funcs = DUK_GET_HOBJECT_POSIDX(thr, entry_top + 2);
69623 DUK_ASSERT(func->h_funcs != NULL);
69624 DUK_ASSERT(func->fnum_next == 0);
69625
69627 func->decls_idx = entry_top + 3;
69628 func->h_decls = DUK_GET_HOBJECT_POSIDX(thr, entry_top + 3);
69629 DUK_ASSERT(func->h_decls != NULL);
69630
69632 func->labelnames_idx = entry_top + 4;
69633 func->h_labelnames = DUK_GET_HOBJECT_POSIDX(thr, entry_top + 4);
69634 DUK_ASSERT(func->h_labelnames != NULL);
69635
69637 func->labelinfos_idx = entry_top + 5;
69638 func->h_labelinfos = (duk_hbuffer_dynamic *) duk_known_hbuffer(thr, entry_top + 5);
69639 DUK_ASSERT(func->h_labelinfos != NULL);
69641
69643 func->argnames_idx = entry_top + 6;
69644 func->h_argnames = DUK_GET_HOBJECT_POSIDX(thr, entry_top + 6);
69645 DUK_ASSERT(func->h_argnames != NULL);
69646
69648 func->varmap_idx = entry_top + 7;
69649 func->h_varmap = DUK_GET_HOBJECT_POSIDX(thr, entry_top + 7);
69650 DUK_ASSERT(func->h_varmap != NULL);
69651}
69652
69653/* reset function state (prepare for pass 2) */
69655 duk_compiler_func *func = &comp_ctx->curr_func;
69656 duk_hthread *thr = comp_ctx->thr;
69657
69658 /* reset bytecode buffer but keep current size; pass 2 will
69659 * require same amount or more.
69661 DUK_BW_RESET_SIZE(thr, &func->bw_code);
69662
69663 duk_set_length(thr, func->consts_idx, 0);
69664 /* keep func->h_funcs; inner functions are not reparsed to avoid O(depth^2) parsing */
69665 func->fnum_next = 0;
69666 /* duk_set_length(thr, func->funcs_idx, 0); */
69667 duk_set_length(thr, func->labelnames_idx, 0);
69668 duk_hbuffer_reset(thr, func->h_labelinfos);
69669 /* keep func->h_argnames; it is fixed for all passes */
69670
69671 /* truncated in case pass 3 needed */
69673 duk_replace(thr, func->varmap_idx);
69674 func->h_varmap = DUK_GET_HOBJECT_POSIDX(thr, func->varmap_idx);
69675 DUK_ASSERT(func->h_varmap != NULL);
69676}
69677
69678/* cleanup varmap from any null entries, compact it, etc; returns number
69679 * of final entries after cleanup.
69680 */
69682 duk_hthread *thr = comp_ctx->thr;
69683 duk_hobject *h_varmap;
69684 duk_hstring *h_key;
69685 duk_tval *tv;
69686 duk_uint32_t i, e_next;
69687 duk_int_t ret;
69688
69689 /* [ ... varmap ] */
69690
69691 h_varmap = DUK_GET_HOBJECT_NEGIDX(thr, -1);
69692 DUK_ASSERT(h_varmap != NULL);
69693
69694 ret = 0;
69695 e_next = DUK_HOBJECT_GET_ENEXT(h_varmap);
69696 for (i = 0; i < e_next; i++) {
69697 h_key = DUK_HOBJECT_E_GET_KEY(thr->heap, h_varmap, i);
69698 if (!h_key) {
69699 continue;
69700 }
69701
69702 DUK_ASSERT(!DUK_HOBJECT_E_SLOT_IS_ACCESSOR(thr->heap, h_varmap, i));
69703
69704 /* The entries can either be register numbers or 'null' values.
69705 * Thus, no need to DECREF them and get side effects. DECREF'ing
69706 * the keys (strings) can cause memory to be freed but no side
69707 * effects as strings don't have finalizers. This is why we can
69708 * rely on the object properties not changing from underneath us.
69709 */
69711 tv = DUK_HOBJECT_E_GET_VALUE_TVAL_PTR(thr->heap, h_varmap, i);
69712 if (!DUK_TVAL_IS_NUMBER(tv)) {
69714 DUK_HOBJECT_E_SET_KEY(thr->heap, h_varmap, i, NULL);
69715 DUK_HSTRING_DECREF(thr, h_key);
69716 /* when key is NULL, value is garbage so no need to set */
69717 } else {
69718 ret++;
69719 }
69720 }
69721
69722 duk_compact_m1(thr);
69723
69724 return ret;
69725}
69726
69727/* Convert duk_compiler_func into a function template, leaving the result
69728 * on top of stack.
69729 */
69730/* XXX: awkward and bloated asm -- use faster internal accesses */
69732 duk_compiler_func *func = &comp_ctx->curr_func;
69733 duk_hthread *thr = comp_ctx->thr;
69734 duk_hcompfunc *h_res;
69735 duk_hbuffer_fixed *h_data;
69736 duk_size_t consts_count;
69737 duk_size_t funcs_count;
69738 duk_size_t code_count;
69739 duk_size_t code_size;
69740 duk_size_t data_size;
69741 duk_size_t i;
69742 duk_tval *p_const;
69743 duk_hobject **p_func;
69744 duk_instr_t *p_instr;
69745 duk_compiler_instr *q_instr;
69746 duk_tval *tv;
69747 duk_bool_t keep_varmap;
69748 duk_bool_t keep_formals;
69749#if !defined(DUK_USE_DEBUGGER_SUPPORT)
69750 duk_size_t formals_length;
69751#endif
69752
69753 DUK_DDD(DUK_DDDPRINT("converting duk_compiler_func to function/template"));
69754
69755 /*
69756 * Push result object and init its flags
69757 */
69758
69759 /* Valstack should suffice here, required on function valstack init */
69760
69761 h_res = duk_push_hcompfunc(thr);
69762 DUK_ASSERT(h_res != NULL);
69764 DUK_HOBJECT_SET_PROTOTYPE_UPDREF(thr, (duk_hobject *) h_res, NULL); /* Function templates are "bare objects". */
69765
69766 if (func->is_function) {
69767 DUK_DDD(DUK_DDDPRINT("function -> set NEWENV"));
69769
69770 if (!func->is_arguments_shadowed) {
69771 /* arguments object would be accessible; note that shadowing
69772 * bindings are arguments or function declarations, neither
69773 * of which are deletable, so this is safe.
69774 */
69775
69776 if (func->id_access_arguments || func->may_direct_eval) {
69777 DUK_DDD(DUK_DDDPRINT("function may access 'arguments' object directly or "
69778 "indirectly -> set CREATEARGS"));
69780 }
69781 }
69782 } else if (func->is_eval && func->is_strict) {
69783 DUK_DDD(DUK_DDDPRINT("strict eval code -> set NEWENV"));
69785 } else {
69786 /* non-strict eval: env is caller's env or global env (direct vs. indirect call)
69787 * global code: env is is global env
69788 */
69789 DUK_DDD(DUK_DDDPRINT("non-strict eval code or global code -> no NEWENV"));
69791 }
69792
69793#if defined(DUK_USE_FUNC_NAME_PROPERTY)
69794 if (func->is_function && func->is_namebinding && func->h_name != NULL) {
69795 /* Object literal set/get functions have a name (property
69796 * name) but must not have a lexical name binding, see
69797 * test-bug-getset-func-name.js.
69798 */
69799 DUK_DDD(DUK_DDDPRINT("function expression with a name -> set NAMEBINDING"));
69801 }
69802#endif
69803
69804 if (func->is_strict) {
69805 DUK_DDD(DUK_DDDPRINT("function is strict -> set STRICT"));
69807 }
69808
69809 if (func->is_notail) {
69810 DUK_DDD(DUK_DDDPRINT("function is notail -> set NOTAIL"));
69812 }
69813
69814 if (func->is_constructable) {
69815 DUK_DDD(DUK_DDDPRINT("function is constructable -> set CONSTRUCTABLE"));
69817 }
69818
69819 /*
69820 * Build function fixed size 'data' buffer, which contains bytecode,
69821 * constants, and inner function references.
69822 *
69823 * During the building phase 'data' is reachable but incomplete.
69824 * Only incref's occur during building (no refzero or GC happens),
69825 * so the building process is atomic.
69826 */
69827
69828 consts_count = duk_hobject_get_length(thr, func->h_consts);
69829 funcs_count = duk_hobject_get_length(thr, func->h_funcs) / 3;
69830 code_count = DUK_BW_GET_SIZE(thr, &func->bw_code) / sizeof(duk_compiler_instr);
69831 code_size = code_count * sizeof(duk_instr_t);
69832
69833 data_size = consts_count * sizeof(duk_tval) + funcs_count * sizeof(duk_hobject *) + code_size;
69834
69835 DUK_DDD(DUK_DDDPRINT("consts_count=%ld, funcs_count=%ld, code_size=%ld -> "
69836 "data_size=%ld*%ld + %ld*%ld + %ld = %ld",
69837 (long) consts_count,
69838 (long) funcs_count,
69839 (long) code_size,
69840 (long) consts_count,
69841 (long) sizeof(duk_tval),
69842 (long) funcs_count,
69843 (long) sizeof(duk_hobject *),
69844 (long) code_size,
69845 (long) data_size));
69846
69847 duk_push_fixed_buffer_nozero(thr, data_size);
69848 h_data = (duk_hbuffer_fixed *) (void *) duk_known_hbuffer(thr, -1);
69849
69850 DUK_HCOMPFUNC_SET_DATA(thr->heap, h_res, (duk_hbuffer *) h_data);
69851 DUK_HEAPHDR_INCREF(thr, h_data);
69852
69853 p_const = (duk_tval *) (void *) DUK_HBUFFER_FIXED_GET_DATA_PTR(thr->heap, h_data);
69854 for (i = 0; i < consts_count; i++) {
69855 DUK_ASSERT(i <= DUK_UARRIDX_MAX); /* const limits */
69857 DUK_ASSERT(tv != NULL);
69858 DUK_TVAL_SET_TVAL(p_const, tv);
69859 p_const++;
69860 DUK_TVAL_INCREF(thr, tv); /* may be a string constant */
69861
69862 DUK_DDD(DUK_DDDPRINT("constant: %!T", (duk_tval *) tv));
69863 }
69864
69865 p_func = (duk_hobject **) p_const;
69866 DUK_HCOMPFUNC_SET_FUNCS(thr->heap, h_res, p_func);
69867 for (i = 0; i < funcs_count; i++) {
69868 duk_hobject *h;
69869 DUK_ASSERT(i * 3 <= DUK_UARRIDX_MAX); /* func limits */
69871 DUK_ASSERT(tv != NULL);
69873 h = DUK_TVAL_GET_OBJECT(tv);
69874 DUK_ASSERT(h != NULL);
69876 *p_func++ = h;
69877 DUK_HOBJECT_INCREF(thr, h);
69878
69879 DUK_DDD(DUK_DDDPRINT("inner function: %p -> %!iO", (void *) h, (duk_heaphdr *) h));
69880 }
69881
69882 p_instr = (duk_instr_t *) p_func;
69883 DUK_HCOMPFUNC_SET_BYTECODE(thr->heap, h_res, p_instr);
69884
69885 /* copy bytecode instructions one at a time */
69886 q_instr = (duk_compiler_instr *) (void *) DUK_BW_GET_BASEPTR(thr, &func->bw_code);
69887 for (i = 0; i < code_count; i++) {
69888 p_instr[i] = q_instr[i].ins;
69889 }
69890 /* Note: 'q_instr' is still used below */
69891
69892 DUK_ASSERT((duk_uint8_t *) (p_instr + code_count) == DUK_HBUFFER_FIXED_GET_DATA_PTR(thr->heap, h_data) + data_size);
69893
69894 duk_pop(thr); /* 'data' (and everything in it) is reachable through h_res now */
69895
69896 /*
69897 * Init non-property result fields
69898 *
69899 * 'nregs' controls how large a register frame is allocated.
69900 *
69901 * 'nargs' controls how many formal arguments are written to registers:
69902 * r0, ... r(nargs-1). The remaining registers are initialized to
69903 * undefined.
69904 */
69905
69906 DUK_ASSERT(func->temp_max >= 0);
69907 h_res->nregs = (duk_uint16_t) func->temp_max;
69908 h_res->nargs = (duk_uint16_t) duk_hobject_get_length(thr, func->h_argnames);
69909 DUK_ASSERT(h_res->nregs >= h_res->nargs); /* pass2 allocation handles this */
69910#if defined(DUK_USE_DEBUGGER_SUPPORT)
69911 h_res->start_line = (duk_uint32_t) func->min_line;
69912 h_res->end_line = (duk_uint32_t) func->max_line;
69913#endif
69914
69915 /*
69916 * Init object properties
69917 *
69918 * Properties should be added in decreasing order of access frequency.
69919 * (Not very critical for function templates.)
69920 */
69921
69922 DUK_DDD(DUK_DDDPRINT("init function properties"));
69923
69924 /* [ ... res ] */
69925
69926 /* _Varmap: omitted if function is guaranteed not to do a slow path
69927 * identifier access that might be caught by locally declared variables.
69928 * The varmap can also be omitted if it turns out empty of actual
69929 * register mappings after a cleanup. When debugging is enabled, we
69930 * always need the varmap to be able to lookup variables at any point.
69931 */
69932
69933#if defined(DUK_USE_DEBUGGER_SUPPORT)
69934 DUK_DD(DUK_DDPRINT("keeping _Varmap because debugger support is enabled"));
69935 keep_varmap = 1;
69936#else
69937 if (func->id_access_slow_own || /* directly uses slow accesses that may match own variables */
69938 func->id_access_arguments || /* accesses 'arguments' directly */
69939 func->may_direct_eval || /* may indirectly slow access through a direct eval */
69940 funcs_count >
69941 0) { /* has inner functions which may slow access (XXX: this can be optimized by looking at the inner functions) */
69942 DUK_DD(DUK_DDPRINT("keeping _Varmap because of direct eval, slow path access that may match local variables, or "
69943 "presence of inner functions"));
69944 keep_varmap = 1;
69945 } else {
69946 DUK_DD(DUK_DDPRINT("dropping _Varmap"));
69947 keep_varmap = 0;
69948 }
69949#endif
69950
69951 if (keep_varmap) {
69952 duk_int_t num_used;
69953 duk_dup(thr, func->varmap_idx);
69954 num_used = duk__cleanup_varmap(comp_ctx);
69955 DUK_DDD(DUK_DDDPRINT("cleaned up varmap: %!T (num_used=%ld)", (duk_tval *) duk_get_tval(thr, -1), (long) num_used));
69956
69957 if (num_used > 0) {
69959 } else {
69960 DUK_DD(DUK_DDPRINT("varmap is empty after cleanup -> no need to add"));
69961 duk_pop(thr);
69962 }
69963 }
69964
69965 /* _Formals: omitted if function is guaranteed not to need a (non-strict)
69966 * arguments object, and _Formals.length matches nargs exactly.
69967 *
69968 * Non-arrow functions can't see an outer function's 'argument' binding
69969 * (because they have their own), but arrow functions can. When arrow
69970 * functions are added, this condition would need to be added:
69971 * inner_arrow_funcs_count > 0 inner arrow functions may access 'arguments'
69972 */
69973#if defined(DUK_USE_DEBUGGER_SUPPORT)
69974 DUK_DD(DUK_DDPRINT("keeping _Formals because debugger support is enabled"));
69975 keep_formals = 1;
69976#else
69977 formals_length = duk_get_length(thr, func->argnames_idx);
69978 if (formals_length != (duk_size_t) h_res->nargs) {
69979 /* Nargs not enough for closure .length: keep _Formals regardless
69980 * of its length. Shouldn't happen in practice at the moment.
69981 */
69982 DUK_DD(DUK_DDPRINT("keeping _Formals because _Formals.length != nargs"));
69983 keep_formals = 1;
69984 } else if ((func->id_access_arguments || func->may_direct_eval) && (formals_length > 0)) {
69985 /* Direct eval (may access 'arguments') or accesses 'arguments'
69986 * explicitly: keep _Formals unless it is zero length.
69987 */
69989 "keeping _Formals because of direct eval or explicit access to 'arguments', and _Formals.length != 0"));
69990 keep_formals = 1;
69991 } else {
69992 DUK_DD(DUK_DDPRINT("omitting _Formals, nargs matches _Formals.length, so no properties added"));
69993 keep_formals = 0;
69994 }
69995#endif
69996
69997 if (keep_formals) {
69998 duk_dup(thr, func->argnames_idx);
70000 }
70001
70002 /* name */
70003#if defined(DUK_USE_FUNC_NAME_PROPERTY)
70004 if (func->h_name) {
70005 duk_push_hstring(thr, func->h_name);
70006 DUK_DD(DUK_DDPRINT("setting function template .name to %!T", duk_get_tval(thr, -1)));
70008 }
70009#endif /* DUK_USE_FUNC_NAME_PROPERTY */
70010
70011 /* _Source */
70012#if defined(DUK_USE_NONSTD_FUNC_SOURCE_PROPERTY)
70013 if (0) {
70014 /* XXX: Currently function source code is not stored, as it is not
70015 * required by the standard. Source code should not be stored by
70016 * default (user should enable it explicitly), and the source should
70017 * probably be compressed with a trivial text compressor; average
70018 * compression of 20-30% is quite easy to achieve even with a trivial
70019 * compressor (RLE + backwards lookup).
70020 *
70021 * Debugging needs source code to be useful: sometimes input code is
70022 * not found in files as it may be generated and then eval()'d, given
70023 * by dynamic C code, etc.
70024 *
70025 * Other issues:
70026 *
70027 * - Need tokenizer indices for start and end to substring
70028 * - Always normalize function declaration part?
70029 * - If we keep _Formals, only need to store body
70030 */
70031
70032 /*
70033 * For global or eval code this is straightforward. For functions
70034 * created with the Function constructor we only get the source for
70035 * the body and must manufacture the "function ..." part.
70036 *
70037 * For instance, for constructed functions (v8):
70038 *
70039 * > a = new Function("foo", "bar", "print(foo)");
70040 * [Function]
70041 * > a.toString()
70042 * 'function anonymous(foo,bar) {\nprint(foo)\n}'
70043 *
70044 * Similarly for e.g. getters (v8):
70045 *
70046 * > x = { get a(foo,bar) { print(foo); } }
70047 * { a: [Getter] }
70048 * > Object.getOwnPropertyDescriptor(x, 'a').get.toString()
70049 * 'function a(foo,bar) { print(foo); }'
70050 */
70051
70052#if 0
70053 duk_push_literal(thr, "XXX");
70055#endif
70056 }
70057#endif /* DUK_USE_NONSTD_FUNC_SOURCE_PROPERTY */
70058
70059 /* _Pc2line */
70060#if defined(DUK_USE_PC2LINE)
70061 if (1) {
70062 /*
70063 * Size-optimized pc->line mapping.
70064 */
70065
70067 duk_hobject_pc2line_pack(thr, q_instr, (duk_uint_fast32_t) code_count); /* -> pushes fixed buffer */
70069
70070 /* XXX: if assertions enabled, walk through all valid PCs
70071 * and check line mapping.
70072 */
70073 }
70074#endif /* DUK_USE_PC2LINE */
70075
70076 /* fileName */
70077#if defined(DUK_USE_FUNC_FILENAME_PROPERTY)
70078 if (comp_ctx->h_filename) {
70079 /*
70080 * Source filename (or equivalent), for identifying thrown errors.
70081 */
70082
70083 duk_push_hstring(thr, comp_ctx->h_filename);
70085 }
70086#endif
70087
70088 DUK_DD(DUK_DDPRINT("converted function: %!ixT", (duk_tval *) duk_get_tval(thr, -1)));
70089
70090 /*
70091 * Compact the function template.
70092 */
70093
70094 duk_compact_m1(thr);
70095
70096 /*
70097 * Debug dumping
70098 */
70099
70100#if defined(DUK_USE_DEBUG_LEVEL) && (DUK_USE_DEBUG_LEVEL >= 2)
70101 {
70102 duk_hcompfunc *h;
70103 duk_instr_t *p, *p_start, *p_end;
70104
70105 h = (duk_hcompfunc *) duk_get_hobject(thr, -1);
70106 p_start = (duk_instr_t *) DUK_HCOMPFUNC_GET_CODE_BASE(thr->heap, h);
70107 p_end = (duk_instr_t *) DUK_HCOMPFUNC_GET_CODE_END(thr->heap, h);
70108
70109 p = p_start;
70110 while (p < p_end) {
70111 DUK_DDD(DUK_DDDPRINT("BC %04ld: %!I ; 0x%08lx op=%ld (%!X) a=%ld b=%ld c=%ld",
70112 (long) (p - p_start),
70113 (duk_instr_t) (*p),
70114 (unsigned long) (*p),
70115 (long) DUK_DEC_OP(*p),
70116 (long) DUK_DEC_OP(*p),
70117 (long) DUK_DEC_A(*p),
70118 (long) DUK_DEC_B(*p),
70119 (long) DUK_DEC_C(*p)));
70120 p++;
70121 }
70122 }
70123#endif
70124}
70125
70126/*
70127 * Code emission helpers
70128 *
70129 * Some emission helpers understand the range of target and source reg/const
70130 * values and automatically emit shuffling code if necessary. This is the
70131 * case when the slot in question (A, B, C) is used in the standard way and
70132 * for opcodes the emission helpers explicitly understand (like DUK_OP_MPUTOBJ).
70133 *
70134 * The standard way is that:
70135 * - slot A is a target register
70136 * - slot B is a source register/constant
70137 * - slot C is a source register/constant
70138 *
70139 * If a slot is used in a non-standard way the caller must indicate this
70140 * somehow. If a slot is used as a target instead of a source (or vice
70141 * versa), this can be indicated with a flag to trigger proper shuffling
70142 * (e.g. DUK__EMIT_FLAG_B_IS_TARGET). If the value in the slot is not
70143 * register/const related at all, the caller must ensure that the raw value
70144 * fits into the corresponding slot so as to not trigger shuffling. The
70145 * caller must set a "no shuffle" flag to ensure compilation fails if
70146 * shuffling were to be triggered because of an internal error.
70147 *
70148 * For slots B and C the raw slot size is 9 bits but one bit is reserved for
70149 * the reg/const indicator. To use the full 9-bit range for a raw value,
70150 * shuffling must be disabled with the DUK__EMIT_FLAG_NO_SHUFFLE_{B,C} flag.
70151 * Shuffling is only done for A, B, and C slots, not the larger BC or ABC slots.
70152 *
70153 * There is call handling specific understanding in the A-B-C emitter to
70154 * convert call setup and call instructions into indirect ones if necessary.
70156
70157/* Code emission flags, passed in the 'opcode' field. Opcode + flags
70158 * fit into 16 bits for now, so use duk_small_uint_t.
70159 */
70160#define DUK__EMIT_FLAG_NO_SHUFFLE_A (1 << 8)
70161#define DUK__EMIT_FLAG_NO_SHUFFLE_B (1 << 9)
70162#define DUK__EMIT_FLAG_NO_SHUFFLE_C (1 << 10)
70163#define DUK__EMIT_FLAG_A_IS_SOURCE (1 << 11) /* slot A is a source (default: target) */
70164#define DUK__EMIT_FLAG_B_IS_TARGET (1 << 12) /* slot B is a target (default: source) */
70165#define DUK__EMIT_FLAG_C_IS_TARGET (1 << 13) /* slot C is a target (default: source) */
70166#define DUK__EMIT_FLAG_BC_REGCONST (1 << 14) /* slots B and C are reg/const */
70167#define DUK__EMIT_FLAG_RESERVE_JUMPSLOT (1 << 15) /* reserve a jumpslot after instr before target spilling, used for NEXTENUM */
70168
70169/* XXX: macro smaller than call? */
70171 duk_compiler_func *func;
70172 func = &comp_ctx->curr_func;
70173 return (duk_int_t) (DUK_BW_GET_SIZE(comp_ctx->thr, &func->bw_code) / sizeof(duk_compiler_instr));
70174}
70175
70177 DUK_ASSERT(pc >= 0);
70178 DUK_ASSERT((duk_size_t) pc <
70179 (duk_size_t) (DUK_BW_GET_SIZE(comp_ctx->thr, &comp_ctx->curr_func.bw_code) / sizeof(duk_compiler_instr)));
70180 return ((duk_compiler_instr *) (void *) DUK_BW_GET_BASEPTR(comp_ctx->thr, &comp_ctx->curr_func.bw_code)) + pc;
70181}
70182
70183/* emit instruction; could return PC but that's not needed in the majority
70184 * of cases.
70185 */
70186DUK_LOCAL void duk__emit(duk_compiler_ctx *comp_ctx, duk_instr_t ins) {
70187#if defined(DUK_USE_PC2LINE)
70189#endif
70190 duk_compiler_instr *instr;
70191
70192 DUK_DDD(DUK_DDDPRINT("duk__emit: 0x%08lx curr_token.start_line=%ld prev_token.start_line=%ld pc=%ld --> %!I",
70193 (unsigned long) ins,
70194 (long) comp_ctx->curr_token.start_line,
70195 (long) comp_ctx->prev_token.start_line,
70196 (long) duk__get_current_pc(comp_ctx),
70197 (duk_instr_t) ins));
70198
70199 instr = (duk_compiler_instr *) (void *) DUK_BW_ENSURE_GETPTR(comp_ctx->thr,
70200 &comp_ctx->curr_func.bw_code,
70201 sizeof(duk_compiler_instr));
70202 DUK_BW_ADD_PTR(comp_ctx->thr, &comp_ctx->curr_func.bw_code, sizeof(duk_compiler_instr));
70203
70204#if defined(DUK_USE_PC2LINE)
70205 /* The line number tracking is a bit inconsistent right now, which
70206 * affects debugger accuracy. Mostly call sites emit opcodes when
70207 * they have parsed a token (say a terminating semicolon) and called
70208 * duk__advance(). In this case the line number of the previous
70209 * token is the most accurate one (except in prologue where
70210 * prev_token.start_line is 0). This is probably not 100% correct
70211 * right now.
70212 */
70213 /* approximation, close enough */
70214 line = comp_ctx->prev_token.start_line;
70215 if (line == 0) {
70216 line = comp_ctx->curr_token.start_line;
70217 }
70218#endif
70219
70220 instr->ins = ins;
70221#if defined(DUK_USE_PC2LINE)
70222 instr->line = (duk_uint32_t) line;
70223#endif
70224#if defined(DUK_USE_DEBUGGER_SUPPORT)
70225 if (line < comp_ctx->curr_func.min_line) {
70226 comp_ctx->curr_func.min_line = line;
70227 }
70228 if (line > comp_ctx->curr_func.max_line) {
70229 comp_ctx->curr_func.max_line = line;
70230 }
70231#endif
70232
70233 /* Limit checks for bytecode byte size and line number. */
70235 goto fail_bc_limit;
70236 }
70237#if defined(DUK_USE_PC2LINE) && defined(DUK_USE_ESBC_LIMITS)
70238#if defined(DUK_USE_BUFLEN16)
70239 /* Buffer length is bounded to 0xffff automatically, avoid compile warning. */
70241 goto fail_bc_limit;
70242 }
70243#else
70245 goto fail_bc_limit;
70246 }
70247#endif
70248#endif
70249
70250 return;
70251
70252fail_bc_limit:
70254 DUK_WO_NORETURN(return;);
70255}
70256
70257/* Update function min/max line from current token. Needed to improve
70258 * function line range information for debugging, so that e.g. opening
70259 * curly brace is covered by line range even when no opcodes are emitted
70260 * for the line containing the brace.
70261 */
70263#if defined(DUK_USE_DEBUGGER_SUPPORT)
70266 line = comp_ctx->curr_token.start_line;
70267 if (line == 0) {
70268 return;
70269 }
70270 if (line < comp_ctx->curr_func.min_line) {
70271 comp_ctx->curr_func.min_line = line;
70272 }
70273 if (line > comp_ctx->curr_func.max_line) {
70274 comp_ctx->curr_func.max_line = line;
70275 }
70276#else
70277 DUK_UNREF(comp_ctx);
70278#endif
70279}
70280
70282 duk__emit(comp_ctx, DUK_ENC_OP_ABC(op, 0));
70283}
70284
70285/* Important main primitive. */
70287 duk_small_uint_t op_flags,
70290 duk_regconst_t c) {
70291 duk_instr_t ins = 0;
70292 duk_int_t a_out = -1;
70293 duk_int_t b_out = -1;
70294 duk_int_t c_out = -1;
70295 duk_int_t tmp;
70296 duk_small_uint_t op = op_flags & 0xffU;
70297
70298 DUK_DDD(DUK_DDDPRINT("emit: op_flags=%04lx, a=%ld, b=%ld, c=%ld", (unsigned long) op_flags, (long) a, (long) b, (long) c));
70299
70300 /* We could rely on max temp/const checks: if they don't exceed BC
70301 * limit, nothing here can either (just asserts would be enough).
70302 * Currently we check for the limits, which provides additional
70303 * protection against creating invalid bytecode due to compiler
70304 * bugs.
70305 */
70306
70307 DUK_ASSERT_DISABLE((op_flags & 0xff) >= DUK_BC_OP_MIN); /* unsigned */
70308 DUK_ASSERT((op_flags & 0xff) <= DUK_BC_OP_MAX);
70310 DUK_ASSERT(b != -1); /* Not 'none'. */
70311 DUK_ASSERT(c != -1); /* Not 'none'. */
70312
70313 /* Input shuffling happens before the actual operation, while output
70314 * shuffling happens afterwards. Output shuffling decisions are still
70315 * made at the same time to reduce branch clutter; output shuffle decisions
70316 * are recorded into X_out variables.
70317 */
70318
70319 /* Slot A: currently no support for reg/const. */
70320
70321#if defined(DUK_USE_SHUFFLE_TORTURE)
70322 if (a <= DUK_BC_A_MAX && (op_flags & DUK__EMIT_FLAG_NO_SHUFFLE_A)) {
70323#else
70324 if (a <= DUK_BC_A_MAX) {
70325#endif
70326 ;
70327 } else if (op_flags & DUK__EMIT_FLAG_NO_SHUFFLE_A) {
70328 DUK_D(DUK_DPRINT("out of regs: 'a' (reg) needs shuffling but shuffle prohibited, a: %ld", (long) a));
70329 goto error_outofregs;
70330 } else if (a <= DUK_BC_BC_MAX) {
70331 comp_ctx->curr_func.needs_shuffle = 1;
70332 tmp = comp_ctx->curr_func.shuffle1;
70333 if (op_flags & DUK__EMIT_FLAG_A_IS_SOURCE) {
70334 duk__emit(comp_ctx, DUK_ENC_OP_A_BC(DUK_OP_LDREG, tmp, a));
70335 } else {
70336 /* Output shuffle needed after main operation */
70337 a_out = a;
70338
70339 /* The DUK_OP_CSVAR output shuffle assumes shuffle registers are
70340 * consecutive.
70341 */
70342 DUK_ASSERT((comp_ctx->curr_func.shuffle1 == 0 && comp_ctx->curr_func.shuffle2 == 0) ||
70343 (comp_ctx->curr_func.shuffle2 == comp_ctx->curr_func.shuffle1 + 1));
70344 if (op == DUK_OP_CSVAR) {
70345 /* For CSVAR the limit is one smaller because output shuffle
70346 * must be able to express 'a + 1' in BC.
70347 */
70348 if (a + 1 > DUK_BC_BC_MAX) {
70349 goto error_outofregs;
70350 }
70351 }
70352 }
70353 a = tmp;
70354 } else {
70355 DUK_D(DUK_DPRINT("out of regs: 'a' (reg) needs shuffling but does not fit into BC, a: %ld", (long) a));
70356 goto error_outofregs;
70357 }
70358
70359 /* Slot B: reg/const support, mapped to bit 0 of opcode. */
70360
70361 if ((b & DUK__CONST_MARKER) != 0) {
70362 DUK_ASSERT((op_flags & DUK__EMIT_FLAG_NO_SHUFFLE_B) == 0);
70363 DUK_ASSERT((op_flags & DUK__EMIT_FLAG_B_IS_TARGET) == 0);
70364 b = b & ~DUK__CONST_MARKER;
70365#if defined(DUK_USE_SHUFFLE_TORTURE)
70366 if (0) {
70367#else
70368 if (b <= 0xff) {
70369#endif
70370 if (op_flags & DUK__EMIT_FLAG_BC_REGCONST) {
70371 /* Opcode follows B/C reg/const convention. */
70372 DUK_ASSERT((op & 0x01) == 0);
70373 ins |= DUK_ENC_OP_A_B_C(0x01, 0, 0, 0); /* const flag for B */
70374 } else {
70375 DUK_D(DUK_DPRINT("B is const, opcode is not B/C reg/const: %x", op_flags));
70376 }
70377 } else if (b <= DUK_BC_BC_MAX) {
70378 comp_ctx->curr_func.needs_shuffle = 1;
70379 tmp = comp_ctx->curr_func.shuffle2;
70380 duk__emit(comp_ctx, DUK_ENC_OP_A_BC(DUK_OP_LDCONST, tmp, b));
70381 b = tmp;
70382 } else {
70383 DUK_D(DUK_DPRINT("out of regs: 'b' (const) needs shuffling but does not fit into BC, b: %ld", (long) b));
70384 goto error_outofregs;
70385 }
70386 } else {
70387#if defined(DUK_USE_SHUFFLE_TORTURE)
70388 if (b <= 0xff && (op_flags & DUK__EMIT_FLAG_NO_SHUFFLE_B)) {
70389#else
70390 if (b <= 0xff) {
70391#endif
70392 ;
70393 } else if (op_flags & DUK__EMIT_FLAG_NO_SHUFFLE_B) {
70394 if (b > DUK_BC_B_MAX) {
70395 /* Note: 0xff != DUK_BC_B_MAX */
70396 DUK_D(
70397 DUK_DPRINT("out of regs: 'b' (reg) needs shuffling but shuffle prohibited, b: %ld", (long) b));
70398 goto error_outofregs;
70399 }
70400 } else if (b <= DUK_BC_BC_MAX) {
70401 comp_ctx->curr_func.needs_shuffle = 1;
70402 tmp = comp_ctx->curr_func.shuffle2;
70403 if (op_flags & DUK__EMIT_FLAG_B_IS_TARGET) {
70404 /* Output shuffle needed after main operation */
70405 b_out = b;
70406 }
70407 if (!(op_flags & DUK__EMIT_FLAG_B_IS_TARGET)) {
70408 if (op == DUK_OP_MPUTOBJ || op == DUK_OP_MPUTARR) {
70409 /* Special handling for MPUTOBJ/MPUTARR shuffling.
70410 * For each, slot B identifies the first register of a range
70411 * of registers, so normal shuffling won't work. Instead,
70412 * an indirect version of the opcode is used.
70413 */
70414 DUK_ASSERT((op_flags & DUK__EMIT_FLAG_B_IS_TARGET) == 0);
70415 duk__emit_load_int32_noshuffle(comp_ctx, tmp, b);
70418 op_flags++; /* indirect opcode follows direct */
70419 } else {
70420 duk__emit(comp_ctx, DUK_ENC_OP_A_BC(DUK_OP_LDREG, tmp, b));
70421 }
70422 }
70423 b = tmp;
70424 } else {
70425 DUK_D(DUK_DPRINT("out of regs: 'b' (reg) needs shuffling but does not fit into BC, b: %ld", (long) b));
70426 goto error_outofregs;
70427 }
70428 }
70429
70430 /* Slot C: reg/const support, mapped to bit 1 of opcode. */
70431
70432 if ((c & DUK__CONST_MARKER) != 0) {
70433 DUK_ASSERT((op_flags & DUK__EMIT_FLAG_NO_SHUFFLE_C) == 0);
70434 DUK_ASSERT((op_flags & DUK__EMIT_FLAG_C_IS_TARGET) == 0);
70435 c = c & ~DUK__CONST_MARKER;
70436#if defined(DUK_USE_SHUFFLE_TORTURE)
70437 if (0) {
70438#else
70439 if (c <= 0xff) {
70440#endif
70441 if (op_flags & DUK__EMIT_FLAG_BC_REGCONST) {
70442 /* Opcode follows B/C reg/const convention. */
70443 DUK_ASSERT((op & 0x02) == 0);
70444 ins |= DUK_ENC_OP_A_B_C(0x02, 0, 0, 0); /* const flag for C */
70445 } else {
70446 DUK_D(DUK_DPRINT("C is const, opcode is not B/C reg/const: %x", op_flags));
70447 }
70448 } else if (c <= DUK_BC_BC_MAX) {
70449 comp_ctx->curr_func.needs_shuffle = 1;
70450 tmp = comp_ctx->curr_func.shuffle3;
70451 duk__emit(comp_ctx, DUK_ENC_OP_A_BC(DUK_OP_LDCONST, tmp, c));
70452 c = tmp;
70453 } else {
70454 DUK_D(DUK_DPRINT("out of regs: 'c' (const) needs shuffling but does not fit into BC, c: %ld", (long) c));
70455 goto error_outofregs;
70456 }
70457 } else {
70458#if defined(DUK_USE_SHUFFLE_TORTURE)
70459 if (c <= 0xff && (op_flags & DUK__EMIT_FLAG_NO_SHUFFLE_C)) {
70460#else
70461 if (c <= 0xff) {
70462#endif
70463 ;
70464 } else if (op_flags & DUK__EMIT_FLAG_NO_SHUFFLE_C) {
70465 if (c > DUK_BC_C_MAX) {
70466 /* Note: 0xff != DUK_BC_C_MAX */
70467 DUK_D(
70468 DUK_DPRINT("out of regs: 'c' (reg) needs shuffling but shuffle prohibited, c: %ld", (long) c));
70469 goto error_outofregs;
70470 }
70471 } else if (c <= DUK_BC_BC_MAX) {
70472 comp_ctx->curr_func.needs_shuffle = 1;
70473 tmp = comp_ctx->curr_func.shuffle3;
70474 if (op_flags & DUK__EMIT_FLAG_C_IS_TARGET) {
70475 /* Output shuffle needed after main operation */
70476 c_out = c;
70477 } else {
70478 duk__emit(comp_ctx, DUK_ENC_OP_A_BC(DUK_OP_LDREG, tmp, c));
70479 }
70480 c = tmp;
70481 } else {
70482 DUK_D(DUK_DPRINT("out of regs: 'c' (reg) needs shuffling but does not fit into BC, c: %ld", (long) c));
70483 goto error_outofregs;
70484 }
70485 }
70486
70487 /* Main operation */
70488
70495
70496 ins |= DUK_ENC_OP_A_B_C(op_flags & 0xff, a, b, c);
70497 duk__emit(comp_ctx, ins);
70498
70499 /* NEXTENUM needs a jump slot right after the main instruction.
70500 * When the JUMP is taken, output spilling is not needed so this
70501 * workaround is possible. The jump slot PC is exceptionally
70502 * plumbed through comp_ctx to minimize call sites.
70503 */
70504 if (op_flags & DUK__EMIT_FLAG_RESERVE_JUMPSLOT) {
70505 comp_ctx->emit_jumpslot_pc = duk__get_current_pc(comp_ctx);
70506 duk__emit_abc(comp_ctx, DUK_OP_JUMP, 0);
70507 }
70508
70509 /* Output shuffling: only one output register is realistically possible.
70510 *
70511 * (Zero would normally be an OK marker value: if the target register
70512 * was zero, it would never be shuffled. But with DUK_USE_SHUFFLE_TORTURE
70513 * this is no longer true, so use -1 as a marker instead.)
70514 */
70515
70516 if (a_out >= 0) {
70517 DUK_ASSERT(b_out < 0);
70518 DUK_ASSERT(c_out < 0);
70519 duk__emit(comp_ctx, DUK_ENC_OP_A_BC(DUK_OP_STREG, a, a_out));
70520
70521 if (op == DUK_OP_CSVAR) {
70522 /* Special handling for CSVAR shuffling. The variable lookup
70523 * results in a <value, this binding> pair in successive
70524 * registers so use two shuffle registers and two output
70525 * loads. (In practice this is dead code because temp/const
70526 * limit is reached first.)
70527 */
70528 duk__emit(comp_ctx, DUK_ENC_OP_A_BC(DUK_OP_STREG, a + 1, a_out + 1));
70529 }
70530 } else if (b_out >= 0) {
70531 DUK_ASSERT(a_out < 0);
70532 DUK_ASSERT(c_out < 0);
70533 duk__emit(comp_ctx, DUK_ENC_OP_A_BC(DUK_OP_STREG, b, b_out));
70534 } else if (c_out >= 0) {
70535 DUK_ASSERT(b_out < 0);
70536 DUK_ASSERT(c_out < 0);
70537 duk__emit(comp_ctx, DUK_ENC_OP_A_BC(DUK_OP_STREG, c, c_out));
70538 }
70539
70540 return;
70541
70542error_outofregs:
70544 DUK_WO_NORETURN(return;);
70545}
70546
70547/* For many of the helpers below it'd be technically correct to add
70548 * "no shuffle" flags for parameters passed in as zero. For example,
70549 * duk__emit_a_b() should call duk__emit_a_b_c() with C set to 0, and
70550 * DUK__EMIT_FLAG_NO_SHUFFLE_C added to op_flags. However, since the
70551 * C value is 0, it'll never get shuffled so adding the flag is just
70552 * unnecessary additional code. This is unfortunately not true for
70553 * "shuffle torture" mode which needs special handling.
70554 */
70555
70557#if defined(DUK_USE_SHUFFLE_TORTURE)
70558 op_flags |= DUK__EMIT_FLAG_NO_SHUFFLE_C;
70559#endif
70560 duk__emit_a_b_c(comp_ctx, op_flags, a, b, 0);
70561}
70562
70564#if defined(DUK_USE_SHUFFLE_TORTURE)
70565 op_flags |= DUK__EMIT_FLAG_NO_SHUFFLE_A;
70566#endif
70567 duk__emit_a_b_c(comp_ctx, op_flags, 0, b, c);
70568}
70569
70570#if 0 /* unused */
70571DUK_LOCAL void duk__emit_a(duk_compiler_ctx *comp_ctx, int op_flags, int a) {
70572#if defined(DUK_USE_SHUFFLE_TORTURE)
70574#endif
70575 duk__emit_a_b_c(comp_ctx, op_flags, a, 0, 0);
70576}
70577#endif
70578
70579#if 0 /* unused */
70580DUK_LOCAL void duk__emit_b(duk_compiler_ctx *comp_ctx, duk_small_uint_t op_flags, duk_regconst_t b) {
70581#if defined(DUK_USE_SHUFFLE_TORTURE)
70583#endif
70584 duk__emit_a_b_c(comp_ctx, op_flags, 0, b, 0);
70585}
70586#endif
70587
70589 duk_instr_t ins;
70590 duk_int_t tmp;
70591
70592 /* allow caller to give a const number with the DUK__CONST_MARKER */
70593 DUK_ASSERT(bc != -1); /* Not 'none'. */
70594 bc = bc & (~DUK__CONST_MARKER);
70595
70596 DUK_ASSERT_DISABLE((op_flags & 0xff) >= DUK_BC_OP_MIN); /* unsigned */
70597 DUK_ASSERT((op_flags & 0xff) <= DUK_BC_OP_MAX);
70600 DUK_ASSERT((bc & DUK__CONST_MARKER) == 0);
70601
70602 if (bc <= DUK_BC_BC_MAX) {
70603 ;
70604 } else {
70605 /* No BC shuffling now. */
70606 goto error_outofregs;
70607 }
70608
70609#if defined(DUK_USE_SHUFFLE_TORTURE)
70610 if (a <= DUK_BC_A_MAX && (op_flags & DUK__EMIT_FLAG_NO_SHUFFLE_A)) {
70611#else
70612 if (a <= DUK_BC_A_MAX) {
70613#endif
70614 ins = DUK_ENC_OP_A_BC(op_flags & 0xff, a, bc);
70615 duk__emit(comp_ctx, ins);
70616 } else if (op_flags & DUK__EMIT_FLAG_NO_SHUFFLE_A) {
70617 goto error_outofregs;
70618 } else if ((op_flags & 0xf0U) == DUK_OP_CALL0) {
70619 comp_ctx->curr_func.needs_shuffle = 1;
70620 tmp = comp_ctx->curr_func.shuffle1;
70621 duk__emit_load_int32_noshuffle(comp_ctx, tmp, a);
70622 op_flags |= DUK_BC_CALL_FLAG_INDIRECT;
70623 ins = DUK_ENC_OP_A_BC(op_flags & 0xff, tmp, bc);
70624 duk__emit(comp_ctx, ins);
70625 } else if (a <= DUK_BC_BC_MAX) {
70626 comp_ctx->curr_func.needs_shuffle = 1;
70627 tmp = comp_ctx->curr_func.shuffle1;
70628 ins = DUK_ENC_OP_A_BC(op_flags & 0xff, tmp, bc);
70629 if (op_flags & DUK__EMIT_FLAG_A_IS_SOURCE) {
70630 duk__emit(comp_ctx, DUK_ENC_OP_A_BC(DUK_OP_LDREG, tmp, a));
70631 duk__emit(comp_ctx, ins);
70632 } else {
70633 duk__emit(comp_ctx, ins);
70634 duk__emit(comp_ctx, DUK_ENC_OP_A_BC(DUK_OP_STREG, tmp, a));
70635 }
70636 } else {
70637 goto error_outofregs;
70638 }
70639 return;
70640
70641error_outofregs:
70643 DUK_WO_NORETURN(return;);
70644}
70645
70647#if defined(DUK_USE_SHUFFLE_TORTURE)
70649#endif
70650 duk__emit_a_bc(comp_ctx, op, 0, bc);
70651}
70652
70654 duk_instr_t ins;
70655
70656 DUK_ASSERT_DISABLE(op >= DUK_BC_OP_MIN); /* unsigned */
70658 DUK_ASSERT_DISABLE(abc >= DUK_BC_ABC_MIN); /* unsigned */
70659 DUK_ASSERT(abc <= DUK_BC_ABC_MAX);
70660 DUK_ASSERT((abc & DUK__CONST_MARKER) == 0);
70661 DUK_ASSERT(abc != -1); /* Not 'none'. */
70662
70663 if (abc <= DUK_BC_ABC_MAX) {
70665 } else {
70666 goto error_outofregs;
70667 }
70668 ins = DUK_ENC_OP_ABC(op, abc);
70669 DUK_DDD(DUK_DDDPRINT("duk__emit_abc: 0x%08lx line=%ld pc=%ld op=%ld (%!X) abc=%ld (%!I)",
70670 (unsigned long) ins,
70671 (long) comp_ctx->curr_token.start_line,
70672 (long) duk__get_current_pc(comp_ctx),
70673 (long) op,
70674 (long) op,
70675 (long) abc,
70676 (duk_instr_t) ins));
70677 duk__emit(comp_ctx, ins);
70678 return;
70679
70680error_outofregs:
70682 DUK_WO_NORETURN(return;);
70683}
70684
70686 duk_regconst_t reg,
70687 duk_int32_t val,
70688 duk_small_uint_t op_flags) {
70689 /* XXX: Shuffling support could be implemented here so that LDINT+LDINTX
70690 * would only shuffle once (instead of twice). The current code works
70691 * though, and has a smaller compiler footprint.
70692 */
70693
70694 if ((val >= (duk_int32_t) DUK_BC_BC_MIN - (duk_int32_t) DUK_BC_LDINT_BIAS) &&
70695 (val <= (duk_int32_t) DUK_BC_BC_MAX - (duk_int32_t) DUK_BC_LDINT_BIAS)) {
70696 DUK_DDD(DUK_DDDPRINT("emit LDINT to reg %ld for %ld", (long) reg, (long) val));
70697 duk__emit_a_bc(comp_ctx, DUK_OP_LDINT | op_flags, reg, (duk_regconst_t) (val + (duk_int32_t) DUK_BC_LDINT_BIAS));
70698 } else {
70699 duk_int32_t hi = val >> DUK_BC_LDINTX_SHIFT;
70700 duk_int32_t lo = val & ((((duk_int32_t) 1) << DUK_BC_LDINTX_SHIFT) - 1);
70701 DUK_ASSERT(lo >= 0);
70702 DUK_DDD(DUK_DDDPRINT("emit LDINT+LDINTX to reg %ld for %ld -> hi %ld, lo %ld",
70703 (long) reg,
70704 (long) val,
70705 (long) hi,
70706 (long) lo));
70707 duk__emit_a_bc(comp_ctx, DUK_OP_LDINT | op_flags, reg, (duk_regconst_t) (hi + (duk_int32_t) DUK_BC_LDINT_BIAS));
70708 duk__emit_a_bc(comp_ctx, DUK_OP_LDINTX | op_flags, reg, (duk_regconst_t) lo);
70709 }
70710}
70711
70712DUK_LOCAL void duk__emit_load_int32(duk_compiler_ctx *comp_ctx, duk_regconst_t reg, duk_int32_t val) {
70713 duk__emit_load_int32_raw(comp_ctx, reg, val, 0 /*op_flags*/);
70714}
70715
70716#if defined(DUK_USE_SHUFFLE_TORTURE)
70717/* Used by duk__emit*() calls so that we don't shuffle the loadints that
70718 * are needed to handle indirect opcodes.
70719 */
70720DUK_LOCAL void duk__emit_load_int32_noshuffle(duk_compiler_ctx *comp_ctx, duk_regconst_t reg, duk_int32_t val) {
70721 duk__emit_load_int32_raw(comp_ctx, reg, val, DUK__EMIT_FLAG_NO_SHUFFLE_A /*op_flags*/);
70722}
70723#else
70724DUK_LOCAL void duk__emit_load_int32_noshuffle(duk_compiler_ctx *comp_ctx, duk_regconst_t reg, duk_int32_t val) {
70725 /* When torture not enabled, can just use the same helper because
70726 * 'reg' won't get spilled.
70727 */
70728 DUK_ASSERT(reg <= DUK_BC_A_MAX);
70729 duk__emit_load_int32(comp_ctx, reg, val);
70730}
70731#endif
70732
70733DUK_LOCAL void duk__emit_jump(duk_compiler_ctx *comp_ctx, duk_int_t target_pc) {
70734 duk_int_t curr_pc;
70735 duk_int_t offset;
70736
70737 curr_pc = (duk_int_t) (DUK_BW_GET_SIZE(comp_ctx->thr, &comp_ctx->curr_func.bw_code) / sizeof(duk_compiler_instr));
70738 offset = (duk_int_t) target_pc - (duk_int_t) curr_pc - 1;
70742}
70743
70745 duk_int_t ret;
70746
70747 ret = duk__get_current_pc(comp_ctx); /* useful for patching jumps later */
70748 duk__emit_op_only(comp_ctx, DUK_OP_JUMP);
70749 return ret;
70750}
70751
70752/* Insert an empty jump in the middle of code emitted earlier. This is
70753 * currently needed for compiling for-in.
70754 */
70756#if defined(DUK_USE_PC2LINE)
70758#endif
70759 duk_compiler_instr *instr;
70760 duk_size_t offset;
70761
70762 DUK_ASSERT(jump_pc >= 0);
70763 offset = (duk_size_t) jump_pc * sizeof(duk_compiler_instr);
70764 instr = (duk_compiler_instr *) (void *)
70765 DUK_BW_INSERT_ENSURE_AREA(comp_ctx->thr, &comp_ctx->curr_func.bw_code, offset, sizeof(duk_compiler_instr));
70766
70767#if defined(DUK_USE_PC2LINE)
70768 line = comp_ctx->curr_token.start_line; /* approximation, close enough */
70769#endif
70770 instr->ins = DUK_ENC_OP_ABC(DUK_OP_JUMP, 0);
70771#if defined(DUK_USE_PC2LINE)
70772 instr->line = (duk_uint32_t) line;
70773#endif
70774
70775 DUK_BW_ADD_PTR(comp_ctx->thr, &comp_ctx->curr_func.bw_code, sizeof(duk_compiler_instr));
70777 goto fail_bc_limit;
70778 }
70779 return;
70780
70781fail_bc_limit:
70783 DUK_WO_NORETURN(return;);
70784}
70785
70786/* Does not assume that jump_pc contains a DUK_OP_JUMP previously; this is intentional
70787 * to allow e.g. an INVALID opcode be overwritten with a JUMP (label management uses this).
70788 */
70789DUK_LOCAL void duk__patch_jump(duk_compiler_ctx *comp_ctx, duk_int_t jump_pc, duk_int_t target_pc) {
70790 duk_compiler_instr *instr;
70791 duk_int_t offset;
70792
70793 /* allow negative PCs, behave as a no-op */
70794 if (jump_pc < 0) {
70795 DUK_DDD(
70796 DUK_DDDPRINT("duk__patch_jump(): nop call, jump_pc=%ld (<0), target_pc=%ld", (long) jump_pc, (long) target_pc));
70797 return;
70799 DUK_ASSERT(jump_pc >= 0);
70800
70801 /* XXX: range assert */
70802 instr = duk__get_instr_ptr(comp_ctx, jump_pc);
70803 DUK_ASSERT(instr != NULL);
70804
70805 /* XXX: range assert */
70806 offset = target_pc - jump_pc - 1;
70807
70808 instr->ins = DUK_ENC_OP_ABC(DUK_OP_JUMP, offset + DUK_BC_JUMP_BIAS);
70809 DUK_DDD(DUK_DDDPRINT("duk__patch_jump(): jump_pc=%ld, target_pc=%ld, offset=%ld",
70810 (long) jump_pc,
70811 (long) target_pc,
70812 (long) offset));
70813}
70814
70816 duk__patch_jump(comp_ctx, jump_pc, duk__get_current_pc(comp_ctx));
70817}
70818
70820 duk_int_t ldconst_pc,
70821 duk_int_t trycatch_pc,
70822 duk_regconst_t reg_catch,
70823 duk_regconst_t const_varname,
70824 duk_small_uint_t flags) {
70825 duk_compiler_instr *instr;
70826
70827 DUK_ASSERT(DUK__ISREG(reg_catch));
70828
70829 instr = duk__get_instr_ptr(comp_ctx, ldconst_pc);
70831 DUK_ASSERT(instr != NULL);
70832 if (const_varname & DUK__CONST_MARKER) {
70833 /* Have a catch variable. */
70834 const_varname = const_varname & (~DUK__CONST_MARKER);
70835 if (reg_catch > DUK_BC_BC_MAX || const_varname > DUK_BC_BC_MAX) {
70836 /* Catch attempts to use out-of-range reg/const. Without this
70837 * check Duktape 0.12.0 could generate invalid code which caused
70838 * an assert failure on execution. This error is triggered e.g.
70839 * for functions with a lot of constants and a try-catch statement.
70840 * Shuffling or opcode semantics change is needed to fix the issue.
70841 * See: test-bug-trycatch-many-constants.js.
70842 */
70843 DUK_D(DUK_DPRINT("failed to patch trycatch: flags=%ld, reg_catch=%ld, const_varname=%ld (0x%08lx)",
70844 (long) flags,
70845 (long) reg_catch,
70846 (long) const_varname,
70847 (long) const_varname));
70849 DUK_WO_NORETURN(return;);
70850 }
70851 instr->ins |= DUK_ENC_OP_A_BC(0, 0, const_varname);
70852 } else {
70853 /* No catch variable, e.g. a try-finally; replace LDCONST with
70854 * NOP to avoid a bogus LDCONST.
70855 */
70856 instr->ins = DUK_ENC_OP(DUK_OP_NOP);
70857 }
70858
70859 instr = duk__get_instr_ptr(comp_ctx, trycatch_pc);
70860 DUK_ASSERT(instr != NULL);
70862 DUK_ASSERT(flags <= DUK_BC_A_MAX);
70863 instr->ins = DUK_ENC_OP_A_BC(DUK_OP_TRYCATCH, flags, reg_catch);
70864}
70865
70868
70869 op = DUK__ISREG(regconst) ? DUK_OP_IFFALSE_R : DUK_OP_IFFALSE_C;
70870 duk__emit_bc(comp_ctx, op, regconst); /* helper will remove const flag */
70871}
70872
70875
70876 op = DUK__ISREG(regconst) ? DUK_OP_IFTRUE_R : DUK_OP_IFTRUE_C;
70877 duk__emit_bc(comp_ctx, op, regconst); /* helper will remove const flag */
70878}
70879
70882}
70883
70884/*
70885 * Peephole optimizer for finished bytecode.
70886 *
70887 * Does not remove opcodes; currently only straightens out unconditional
70888 * jump chains which are generated by several control structures.
70889 */
70890
70893 duk_small_uint_t iter;
70894 duk_int_t i, n;
70895 duk_int_t count_opt;
70896
70897 bc = (duk_compiler_instr *) (void *) DUK_BW_GET_BASEPTR(comp_ctx->thr, &comp_ctx->curr_func.bw_code);
70898#if defined(DUK_USE_BUFLEN16)
70899 /* No need to assert, buffer size maximum is 0xffff. */
70900#else
70901 DUK_ASSERT((duk_size_t) DUK_BW_GET_SIZE(comp_ctx->thr, &comp_ctx->curr_func.bw_code) / sizeof(duk_compiler_instr) <=
70902 (duk_size_t) DUK_INT_MAX); /* bytecode limits */
70903#endif
70904 n = (duk_int_t) (DUK_BW_GET_SIZE(comp_ctx->thr, &comp_ctx->curr_func.bw_code) / sizeof(duk_compiler_instr));
70905
70906 for (iter = 0; iter < DUK_COMPILER_PEEPHOLE_MAXITER; iter++) {
70907 count_opt = 0;
70908
70909 for (i = 0; i < n; i++) {
70910 duk_instr_t ins;
70911 duk_int_t target_pc1;
70912 duk_int_t target_pc2;
70913
70914 ins = bc[i].ins;
70915 if (DUK_DEC_OP(ins) != DUK_OP_JUMP) {
70916 continue;
70917 }
70918
70919 target_pc1 = i + 1 + (duk_int_t) DUK_DEC_ABC(ins) - (duk_int_t) DUK_BC_JUMP_BIAS;
70920 DUK_DDD(DUK_DDDPRINT("consider jump at pc %ld; target_pc=%ld", (long) i, (long) target_pc1));
70921 DUK_ASSERT(target_pc1 >= 0);
70922 DUK_ASSERT(target_pc1 < n);
70923
70924 /* Note: if target_pc1 == i, we'll optimize a jump to itself.
70925 * This does not need to be checked for explicitly; the case
70926 * is rare and max iter breaks us out.
70927 */
70928
70929 ins = bc[target_pc1].ins;
70930 if (DUK_DEC_OP(ins) != DUK_OP_JUMP) {
70931 continue;
70932 }
70933
70934 target_pc2 = target_pc1 + 1 + (duk_int_t) DUK_DEC_ABC(ins) - (duk_int_t) DUK_BC_JUMP_BIAS;
70935
70936 DUK_DDD(DUK_DDDPRINT("optimizing jump at pc %ld; old target is %ld -> new target is %ld",
70937 (long) i,
70938 (long) target_pc1,
70939 (long) target_pc2));
70940
70941 bc[i].ins = DUK_ENC_OP_ABC(DUK_OP_JUMP, target_pc2 - (i + 1) + DUK_BC_JUMP_BIAS);
70942
70943 count_opt++;
70946 DUK_DD(DUK_DDPRINT("optimized %ld jumps on peephole round %ld", (long) count_opt, (long) (iter + 1)));
70947
70948 if (count_opt == 0) {
70949 break;
70950 }
70951 }
70952}
70953
70954/*
70955 * Intermediate value helpers
70956 */
70957
70958/* Flags for intermediate value coercions. A flag for using a forced reg
70959 * is not needed, the forced_reg argument suffices and generates better
70960 * code (it is checked as it is used).
70961 */
70962/* XXX: DUK__IVAL_FLAG_REQUIRE_SHORT is passed but not currently implemented
70963 * by ispec/ivalue operations.
70964 */
70965#define DUK__IVAL_FLAG_ALLOW_CONST (1 << 0) /* allow a constant to be returned */
70966#define DUK__IVAL_FLAG_REQUIRE_TEMP (1 << 1) /* require a (mutable) temporary as a result (or a const if allowed) */
70967#define DUK__IVAL_FLAG_REQUIRE_SHORT (1 << 2) /* require a short (8-bit) reg/const which fits into bytecode B/C slot */
70968
70969/* XXX: some code might benefit from DUK__SETTEMP_IFTEMP(thr,x) */
70970
70971#if 0 /* enable manually for dumping */
70972#define DUK__DUMP_ISPEC(compctx, ispec) \
70973 do { \
70974 duk__dump_ispec((compctx), (ispec)); \
70975 } while (0)
70976#define DUK__DUMP_IVALUE(compctx, ivalue) \
70977 do { \
70978 duk__dump_ivalue((compctx), (ivalue)); \
70979 } while (0)
70980
70981DUK_LOCAL void duk__dump_ispec(duk_compiler_ctx *comp_ctx, duk_ispec *x) {
70982 DUK_D(DUK_DPRINT("ispec dump: t=%ld regconst=0x%08lx, valstack_idx=%ld, value=%!T",
70983 (long) x->t, (unsigned long) x->regconst, (long) x->valstack_idx,
70985}
70986DUK_LOCAL void duk__dump_ivalue(duk_compiler_ctx *comp_ctx, duk_ivalue *x) {
70987 DUK_D(DUK_DPRINT("ivalue dump: t=%ld op=%ld "
70988 "x1={t=%ld regconst=0x%08lx valstack_idx=%ld value=%!T} "
70989 "x2={t=%ld regconst=0x%08lx valstack_idx=%ld value=%!T}",
70990 (long) x->t, (long) x->op,
70991 (long) x->x1.t, (unsigned long) x->x1.regconst, (long) x->x1.valstack_idx,
70992 duk_get_tval(comp_ctx->thr, x->x1.valstack_idx),
70993 (long) x->x2.t, (unsigned long) x->x2.regconst, (long) x->x2.valstack_idx,
70994 duk_get_tval(comp_ctx->thr, x->x2.valstack_idx)));
70995}
70996#else
70997#define DUK__DUMP_ISPEC(comp_ctx, x) \
70998 do { \
70999 } while (0)
71000#define DUK__DUMP_IVALUE(comp_ctx, x) \
71001 do { \
71002 } while (0)
71003#endif
71004
71006 x->t = DUK_IVAL_PLAIN;
71007 x->x1.t = DUK_ISPEC_REGCONST;
71008 x->x1.regconst = regconst;
71009}
71010
71012 x->t = DUK_IVAL_PLAIN;
71013 x->x1.t = DUK_ISPEC_VALUE;
71015}
71016
71018 x->t = DUK_IVAL_VAR;
71019 x->x1.t = DUK_ISPEC_VALUE;
71020 duk_replace(comp_ctx->thr, x->x1.valstack_idx);
71021}
71022
71024 DUK_ASSERT(h != NULL);
71025 duk_push_hstring(comp_ctx->thr, h);
71026 duk__ivalue_var_fromstack(comp_ctx, x);
71027}
71028
71029DUK_LOCAL void duk__copy_ispec(duk_compiler_ctx *comp_ctx, duk_ispec *src, duk_ispec *dst) {
71030 dst->t = src->t;
71031 dst->regconst = src->regconst;
71032 duk_copy(comp_ctx->thr, src->valstack_idx, dst->valstack_idx);
71033}
71034
71036 dst->t = src->t;
71037 dst->op = src->op;
71038 dst->x1.t = src->x1.t;
71039 dst->x1.regconst = src->x1.regconst;
71040 dst->x2.t = src->x2.t;
71041 dst->x2.regconst = src->x2.regconst;
71042 duk_copy(comp_ctx->thr, src->x1.valstack_idx, dst->x1.valstack_idx);
71043 duk_copy(comp_ctx->thr, src->x2.valstack_idx, dst->x2.valstack_idx);
71045
71047 duk_regconst_t res;
71049 res = comp_ctx->curr_func.temp_next;
71050 comp_ctx->curr_func.temp_next += num;
71051
71052 if (comp_ctx->curr_func.temp_next > DUK__MAX_TEMPS) { /* == DUK__MAX_TEMPS is OK */
71054 DUK_WO_NORETURN(return 0;);
71055 }
71057 /* maintain highest 'used' temporary, needed to figure out nregs of function */
71058 if (comp_ctx->curr_func.temp_next > comp_ctx->curr_func.temp_max) {
71059 comp_ctx->curr_func.temp_max = comp_ctx->curr_func.temp_next;
71060 }
71061
71062 return res;
71063}
71064
71066 return duk__alloctemps(comp_ctx, 1);
71067}
71068
71070 comp_ctx->curr_func.temp_next = temp_next;
71071 if (temp_next > comp_ctx->curr_func.temp_max) {
71072 comp_ctx->curr_func.temp_max = temp_next;
71073 }
71074}
71075
71076/* get const for value at valstack top */
71078 duk_hthread *thr = comp_ctx->thr;
71079 duk_compiler_func *f = &comp_ctx->curr_func;
71080 duk_tval *tv1;
71081 duk_int_t i, n, n_check;
71082
71083 n = (duk_int_t) duk_get_length(thr, f->consts_idx);
71084
71085 tv1 = DUK_GET_TVAL_NEGIDX(thr, -1);
71086 DUK_ASSERT(tv1 != NULL);
71087
71088#if defined(DUK_USE_FASTINT)
71089 /* Explicit check for fastint downgrade. */
71091#endif
71092
71093 /* Sanity workaround for handling functions with a large number of
71094 * constants at least somewhat reasonably. Otherwise checking whether
71095 * we already have the constant would grow very slow (as it is O(N^2)).
71096 */
71098 for (i = 0; i < n_check; i++) {
71101 /* Strict equality is NOT enough, because we cannot use the same
71102 * constant for e.g. +0 and -0.
71103 */
71104 if (duk_js_samevalue(tv1, tv2)) {
71105 DUK_DDD(DUK_DDDPRINT("reused existing constant for %!T -> const index %ld", (duk_tval *) tv1, (long) i));
71106 duk_pop(thr);
71108 }
71109 }
71110
71111 if (n > DUK__MAX_CONSTS) {
71113 DUK_WO_NORETURN(return 0;);
71114 }
71115
71116 DUK_DDD(DUK_DDDPRINT("allocating new constant for %!T -> const index %ld", (duk_tval *) tv1, (long) n));
71117 (void) duk_put_prop_index(thr, f->consts_idx, (duk_uarridx_t) n); /* invalidates tv1, tv2 */
71119}
71120
71122#if defined(DUK_USE_REFERENCE_COUNTING)
71123 duk_compiler_func *f = &comp_ctx->curr_func;
71124 duk_bool_t ret;
71125
71126 DUK_ASSERT((rc & DUK__CONST_MARKER) == 0); /* caller removes const marker */
71127 (void) duk_get_prop_index(comp_ctx->thr, f->consts_idx, (duk_uarridx_t) rc);
71128 ret = !duk_is_number(comp_ctx->thr, -1); /* now only number/string, so conservative check */
71129 duk_pop(comp_ctx->thr);
71130 return ret;
71131#else
71132 DUK_UNREF(comp_ctx);
71133 DUK_UNREF(rc);
71134 DUK_ASSERT((rc & DUK__CONST_MARKER) == 0); /* caller removes const marker */
71135 return 0;
71136#endif
71137}
71138
71139/* Get the value represented by an duk_ispec to a register or constant.
71140 * The caller can control the result by indicating whether or not:
71141 *
71142 * (1) a constant is allowed (sometimes the caller needs the result to
71143 * be in a register)
71144 *
71145 * (2) a temporary register is required (usually when caller requires
71146 * the register to be safely mutable; normally either a bound
71147 * register or a temporary register are both OK)
71148 *
71149 * (3) a forced register target needs to be used
71150 *
71151 * Bytecode may be emitted to generate the necessary value. The return
71152 * value is either a register or a constant.
71153 */
71154
71157 duk_ispec *x,
71158 duk_regconst_t forced_reg,
71159 duk_small_uint_t flags) {
71160 duk_hthread *thr = comp_ctx->thr;
71161
71162 DUK_DDD(DUK_DDDPRINT("duk__ispec_toregconst_raw(): x={%ld:%ld:%!T}, "
71163 "forced_reg=%ld, flags 0x%08lx: allow_const=%ld require_temp=%ld require_short=%ld",
71164 (long) x->t,
71165 (long) x->regconst,
71166 (duk_tval *) duk_get_tval(thr, x->valstack_idx),
71167 (long) forced_reg,
71168 (unsigned long) flags,
71169 (long) ((flags & DUK__IVAL_FLAG_ALLOW_CONST) ? 1 : 0),
71170 (long) ((flags & DUK__IVAL_FLAG_REQUIRE_TEMP) ? 1 : 0),
71171 (long) ((flags & DUK__IVAL_FLAG_REQUIRE_SHORT) ? 1 : 0)));
71172
71173 switch (x->t) {
71174 case DUK_ISPEC_VALUE: {
71175 duk_tval *tv;
71176
71177 tv = DUK_GET_TVAL_POSIDX(thr, x->valstack_idx);
71178 DUK_ASSERT(tv != NULL);
71179
71180 switch (DUK_TVAL_GET_TAG(tv)) {
71181 case DUK_TAG_UNDEFINED: {
71182 /* Note: although there is no 'undefined' literal, undefined
71183 * values can occur during compilation as a result of e.g.
71184 * the 'void' operator.
71185 */
71186 duk_regconst_t dest = (forced_reg >= 0 ? forced_reg : DUK__ALLOCTEMP(comp_ctx));
71187 duk__emit_bc(comp_ctx, DUK_OP_LDUNDEF, dest);
71188 return dest;
71189 }
71190 case DUK_TAG_NULL: {
71191 duk_regconst_t dest = (forced_reg >= 0 ? forced_reg : DUK__ALLOCTEMP(comp_ctx));
71192 duk__emit_bc(comp_ctx, DUK_OP_LDNULL, dest);
71193 return dest;
71194 }
71195 case DUK_TAG_BOOLEAN: {
71196 duk_regconst_t dest = (forced_reg >= 0 ? forced_reg : DUK__ALLOCTEMP(comp_ctx));
71198 return dest;
71199 }
71200 case DUK_TAG_POINTER: {
71202 break;
71203 }
71204 case DUK_TAG_STRING: {
71205 duk_hstring *h;
71206 duk_regconst_t dest;
71207 duk_regconst_t constidx;
71208
71209 h = DUK_TVAL_GET_STRING(tv);
71210 DUK_UNREF(h);
71211 DUK_ASSERT(h != NULL);
71212
71213#if 0 /* XXX: to be implemented? */
71214 /* Use special opcodes to load short strings */
71215 if (DUK_HSTRING_GET_BYTELEN(h) <= 2) {
71216 /* Encode into a single opcode (18 bits can encode 1-2 bytes + length indicator) */
71217 } else if (DUK_HSTRING_GET_BYTELEN(h) <= 6) {
71218 /* Encode into a double constant (53 bits can encode 6*8 = 48 bits + 3-bit length */
71219 }
71220#endif
71221 duk_dup(thr, x->valstack_idx);
71222 constidx = duk__getconst(comp_ctx);
71223
71224 if (flags & DUK__IVAL_FLAG_ALLOW_CONST) {
71225 return constidx;
71226 }
71227
71228 dest = (forced_reg >= 0 ? forced_reg : DUK__ALLOCTEMP(comp_ctx));
71229 duk__emit_a_bc(comp_ctx, DUK_OP_LDCONST, dest, constidx);
71230 return dest;
71231 }
71232 case DUK_TAG_OBJECT: {
71234 break;
71235 }
71236 case DUK_TAG_BUFFER: {
71238 break;
71239 }
71240 case DUK_TAG_LIGHTFUNC: {
71242 break;
71243 }
71244#if defined(DUK_USE_FASTINT)
71245 case DUK_TAG_FASTINT:
71246#endif
71247 default: {
71248 /* number */
71249 duk_regconst_t dest;
71250 duk_regconst_t constidx;
71251 duk_double_t dval;
71252 duk_int32_t ival;
71253
71256 dval = DUK_TVAL_GET_NUMBER(tv);
71257
71258 if (!(flags & DUK__IVAL_FLAG_ALLOW_CONST)) {
71259 /* A number can be loaded either through a constant, using
71260 * LDINT, or using LDINT+LDINTX. LDINT is always a size win,
71261 * LDINT+LDINTX is not if the constant is used multiple times.
71262 * Currently always prefer LDINT+LDINTX over a double constant.
71263 */
71264
71265 if (duk_is_whole_get_int32_nonegzero(dval, &ival)) {
71266 dest = (forced_reg >= 0 ? forced_reg : DUK__ALLOCTEMP(comp_ctx));
71267 duk__emit_load_int32(comp_ctx, dest, ival);
71268 return dest;
71269 }
71270 }
71271
71272 duk_dup(thr, x->valstack_idx);
71273 constidx = duk__getconst(comp_ctx);
71274
71275 if (flags & DUK__IVAL_FLAG_ALLOW_CONST) {
71276 return constidx;
71277 } else {
71278 dest = (forced_reg >= 0 ? forced_reg : DUK__ALLOCTEMP(comp_ctx));
71279 duk__emit_a_bc(comp_ctx, DUK_OP_LDCONST, dest, constidx);
71280 return dest;
71281 }
71282 }
71283 } /* end switch */
71284 goto fail_internal; /* never here */
71285 }
71286 case DUK_ISPEC_REGCONST: {
71287 if (forced_reg >= 0) {
71288 if (DUK__ISCONST(x->regconst)) {
71289 duk__emit_a_bc(comp_ctx, DUK_OP_LDCONST, forced_reg, x->regconst);
71290 } else if (x->regconst != forced_reg) {
71291 duk__emit_a_bc(comp_ctx, DUK_OP_LDREG, forced_reg, x->regconst);
71292 } else {
71293 ; /* already in correct reg */
71294 }
71295 return forced_reg;
71296 }
71297
71298 DUK_ASSERT(forced_reg < 0);
71299 if (DUK__ISCONST(x->regconst)) {
71300 if (!(flags & DUK__IVAL_FLAG_ALLOW_CONST)) {
71301 duk_regconst_t dest = DUK__ALLOCTEMP(comp_ctx);
71302 duk__emit_a_bc(comp_ctx, DUK_OP_LDCONST, dest, x->regconst);
71303 return dest;
71304 }
71305 return x->regconst;
71306 }
71307
71308 DUK_ASSERT(forced_reg < 0 && !DUK__ISCONST(x->regconst));
71309 if ((flags & DUK__IVAL_FLAG_REQUIRE_TEMP) && !DUK__ISREG_TEMP(comp_ctx, x->regconst)) {
71310 duk_regconst_t dest = DUK__ALLOCTEMP(comp_ctx);
71311 duk__emit_a_bc(comp_ctx, DUK_OP_LDREG, dest, x->regconst);
71312 return dest;
71313 }
71314 return x->regconst;
71316 default: {
71317 break; /* never here */
71318 }
71319 }
71320
71321fail_internal:
71322 DUK_ERROR_INTERNAL(thr);
71323 DUK_WO_NORETURN(return 0;);
71324}
71325
71327 DUK_ASSERT(forced_reg >= 0);
71328 (void) duk__ispec_toregconst_raw(comp_ctx, x, forced_reg, 0 /*flags*/);
71329}
71330
71331/* Coerce an duk_ivalue to a 'plain' value by generating the necessary
71332 * arithmetic operations, property access, or variable access bytecode.
71333 * The duk_ivalue argument ('x') is converted into a plain value as a
71334 * side effect.
71335 */
71337 duk_hthread *thr = comp_ctx->thr;
71338
71339 DUK_DDD(DUK_DDDPRINT("duk__ivalue_toplain_raw(): x={t=%ld,op=%ld,x1={%ld:%ld:%!T},x2={%ld:%ld:%!T}}, "
71340 "forced_reg=%ld",
71341 (long) x->t,
71342 (long) x->op,
71343 (long) x->x1.t,
71344 (long) x->x1.regconst,
71345 (duk_tval *) duk_get_tval(thr, x->x1.valstack_idx),
71346 (long) x->x2.t,
71347 (long) x->x2.regconst,
71348 (duk_tval *) duk_get_tval(thr, x->x2.valstack_idx),
71349 (long) forced_reg));
71350
71351 switch (x->t) {
71352 case DUK_IVAL_PLAIN: {
71353 return;
71354 }
71355 /* XXX: support unary arithmetic ivalues (useful?) */
71356 case DUK_IVAL_ARITH: {
71357 duk_regconst_t arg1;
71358 duk_regconst_t arg2;
71359 duk_regconst_t dest;
71360 duk_tval *tv1;
71361 duk_tval *tv2;
71362
71363 DUK_DDD(DUK_DDDPRINT("arith to plain conversion"));
71364
71365 /* inline arithmetic check for constant values */
71366 /* XXX: use the exactly same arithmetic function here as in executor */
71367 if (x->x1.t == DUK_ISPEC_VALUE && x->x2.t == DUK_ISPEC_VALUE && x->t == DUK_IVAL_ARITH) {
71368 tv1 = DUK_GET_TVAL_POSIDX(thr, x->x1.valstack_idx);
71369 tv2 = DUK_GET_TVAL_POSIDX(thr, x->x2.valstack_idx);
71370 DUK_ASSERT(tv1 != NULL);
71371 DUK_ASSERT(tv2 != NULL);
71372
71373 DUK_DDD(DUK_DDDPRINT("arith: tv1=%!T, tv2=%!T", (duk_tval *) tv1, (duk_tval *) tv2));
71374
71375 if (DUK_TVAL_IS_NUMBER(tv1) && DUK_TVAL_IS_NUMBER(tv2)) {
71378 duk_double_t d3;
71379 duk_bool_t accept_fold = 1;
71380
71381 DUK_DDD(DUK_DDDPRINT("arith inline check: d1=%lf, d2=%lf, op=%ld",
71382 (double) d1,
71383 (double) d2,
71384 (long) x->op));
71385 switch (x->op) {
71386 case DUK_OP_ADD: {
71387 d3 = d1 + d2;
71388 break;
71389 }
71390 case DUK_OP_SUB: {
71391 d3 = d1 - d2;
71392 break;
71393 }
71394 case DUK_OP_MUL: {
71395 d3 = d1 * d2;
71396 break;
71397 }
71398 case DUK_OP_DIV: {
71399 /* Division-by-zero is undefined
71400 * behavior, so rely on a helper.
71401 */
71402 d3 = duk_double_div(d1, d2);
71403 break;
71404 }
71405 case DUK_OP_EXP: {
71406 d3 = (duk_double_t) duk_js_arith_pow((double) d1, (double) d2);
71407 break;
71408 }
71409 default: {
71410 d3 = 0.0; /* Won't be used, but silence MSVC /W4 warning. */
71411 accept_fold = 0;
71412 break;
71413 }
71414 }
71415
71416 if (accept_fold) {
71418 du.d = d3;
71420 d3 = du.d;
71421
71422 x->t = DUK_IVAL_PLAIN;
71424 DUK_TVAL_SET_NUMBER(tv1, d3); /* old value is number: no refcount */
71425 return;
71426 }
71427 } else if (x->op == DUK_OP_ADD && DUK_TVAL_IS_STRING(tv1) && DUK_TVAL_IS_STRING(tv2)) {
71428 /* Inline string concatenation. No need to check for
71429 * symbols, as all inputs are valid ECMAScript strings.
71430 */
71431 duk_dup(thr, x->x1.valstack_idx);
71432 duk_dup(thr, x->x2.valstack_idx);
71433 duk_concat(thr, 2);
71434 duk_replace(thr, x->x1.valstack_idx);
71435 x->t = DUK_IVAL_PLAIN;
71437 return;
71438 }
71439 }
71440
71441 arg1 = duk__ispec_toregconst_raw(comp_ctx,
71442 &x->x1,
71443 -1,
71445 arg2 = duk__ispec_toregconst_raw(comp_ctx,
71446 &x->x2,
71447 -1,
71449
71450 /* If forced reg, use it as destination. Otherwise try to
71451 * use either coerced ispec if it is a temporary.
71452 */
71453 if (forced_reg >= 0) {
71454 dest = forced_reg;
71455 } else if (DUK__ISREG_TEMP(comp_ctx, arg1)) {
71456 dest = arg1;
71457 } else if (DUK__ISREG_TEMP(comp_ctx, arg2)) {
71458 dest = arg2;
71459 } else {
71460 dest = DUK__ALLOCTEMP(comp_ctx);
71461 }
71462
71463 DUK_ASSERT(DUK__ISREG(dest));
71464 duk__emit_a_b_c(comp_ctx, x->op | DUK__EMIT_FLAG_BC_REGCONST, dest, arg1, arg2);
71465
71466 duk__ivalue_regconst(x, dest);
71467 return;
71468 }
71469 case DUK_IVAL_PROP: {
71470 /* XXX: very similar to DUK_IVAL_ARITH - merge? */
71471 duk_regconst_t arg1;
71472 duk_regconst_t arg2;
71473 duk_regconst_t dest;
71474
71475 /* Need a short reg/const, does not have to be a mutable temp. */
71476 arg1 = duk__ispec_toregconst_raw(comp_ctx,
71477 &x->x1,
71478 -1,
71480 arg2 = duk__ispec_toregconst_raw(comp_ctx,
71481 &x->x2,
71482 -1,
71484
71485 /* Pick a destination register. If either base value or key
71486 * happens to be a temp value, reuse it as the destination.
71487 *
71488 * XXX: The temp must be a "mutable" one, i.e. such that no
71489 * other expression is using it anymore. Here this should be
71490 * the case because the value of a property access expression
71491 * is neither the base nor the key, but the lookup result.
71492 */
71493
71494 if (forced_reg >= 0) {
71495 dest = forced_reg;
71496 } else if (DUK__ISREG_TEMP(comp_ctx, arg1)) {
71497 dest = arg1;
71498 } else if (DUK__ISREG_TEMP(comp_ctx, arg2)) {
71499 dest = arg2;
71500 } else {
71501 dest = DUK__ALLOCTEMP(comp_ctx);
71502 }
71503
71504 duk__emit_a_b_c(comp_ctx, DUK_OP_GETPROP | DUK__EMIT_FLAG_BC_REGCONST, dest, arg1, arg2);
71505
71506 duk__ivalue_regconst(x, dest);
71507 return;
71508 }
71509 case DUK_IVAL_VAR: {
71510 /* x1 must be a string */
71511 duk_regconst_t dest;
71512 duk_regconst_t reg_varbind;
71513 duk_regconst_t rc_varname;
71514
71516
71517 duk_dup(thr, x->x1.valstack_idx);
71518 if (duk__lookup_lhs(comp_ctx, &reg_varbind, &rc_varname)) {
71519 duk__ivalue_regconst(x, reg_varbind);
71520 } else {
71521 dest = (forced_reg >= 0 ? forced_reg : DUK__ALLOCTEMP(comp_ctx));
71522 duk__emit_a_bc(comp_ctx, DUK_OP_GETVAR, dest, rc_varname);
71524 }
71525 return;
71526 }
71527 case DUK_IVAL_NONE:
71528 default: {
71529 DUK_D(DUK_DPRINT("invalid ivalue type: %ld", (long) x->t));
71530 break;
71531 }
71532 }
71533
71534 DUK_ERROR_INTERNAL(thr);
71535 DUK_WO_NORETURN(return;);
71536}
71537
71538/* evaluate to plain value, no forced register (temp/bound reg both ok) */
71540 duk__ivalue_toplain_raw(comp_ctx, x, -1 /*forced_reg*/);
71542
71543/* evaluate to final form (e.g. coerce GETPROP to code), throw away temp */
71545 duk_regconst_t temp;
71546
71547 /* If duk__ivalue_toplain_raw() allocates a temp, forget it and
71548 * restore next temp state.
71549 */
71550 temp = DUK__GETTEMP(comp_ctx);
71551 duk__ivalue_toplain_raw(comp_ctx, x, -1 /*forced_reg*/);
71552 DUK__SETTEMP(comp_ctx, temp);
71553}
71554
71555/* Coerce an duk_ivalue to a register or constant; result register may
71556 * be a temp or a bound register.
71557 *
71558 * The duk_ivalue argument ('x') is converted into a regconst as a
71559 * side effect.
71560 */
71563 duk_ivalue *x,
71564 duk_regconst_t forced_reg,
71565 duk_small_uint_t flags) {
71566 duk_hthread *thr = comp_ctx->thr;
71567 duk_regconst_t reg;
71568 DUK_UNREF(thr);
71569
71570 DUK_DDD(DUK_DDDPRINT("duk__ivalue_toregconst_raw(): x={t=%ld,op=%ld,x1={%ld:%ld:%!T},x2={%ld:%ld:%!T}}, "
71571 "forced_reg=%ld, flags 0x%08lx: allow_const=%ld require_temp=%ld require_short=%ld",
71572 (long) x->t,
71573 (long) x->op,
71574 (long) x->x1.t,
71575 (long) x->x1.regconst,
71577 (long) x->x2.t,
71578 (long) x->x2.regconst,
71579 (duk_tval *) duk_get_tval(thr, x->x2.valstack_idx),
71580 (long) forced_reg,
71581 (unsigned long) flags,
71582 (long) ((flags & DUK__IVAL_FLAG_ALLOW_CONST) ? 1 : 0),
71583 (long) ((flags & DUK__IVAL_FLAG_REQUIRE_TEMP) ? 1 : 0),
71584 (long) ((flags & DUK__IVAL_FLAG_REQUIRE_SHORT) ? 1 : 0)));
71585
71586 /* first coerce to a plain value */
71587 duk__ivalue_toplain_raw(comp_ctx, x, forced_reg);
71589
71590 /* then to a register */
71591 reg = duk__ispec_toregconst_raw(comp_ctx, &x->x1, forced_reg, flags);
71592 duk__ivalue_regconst(x, reg);
71593
71594 return reg;
71596
71598 return duk__ivalue_toregconst_raw(comp_ctx, x, -1, 0 /*flags*/);
71599}
71600
71601#if 0 /* unused */
71602DUK_LOCAL duk_regconst_t duk__ivalue_totemp(duk_compiler_ctx *comp_ctx, duk_ivalue *x) {
71603 return duk__ivalue_toregconst_raw(comp_ctx, x, -1, DUK__IVAL_FLAG_REQUIRE_TEMP /*flags*/);
71604}
71605#endif
71606
71608 DUK_ASSERT(forced_reg >= 0);
71609 (void) duk__ivalue_toregconst_raw(comp_ctx, x, forced_reg, 0 /*flags*/);
71610}
71613 return duk__ivalue_toregconst_raw(comp_ctx, x, -1, DUK__IVAL_FLAG_ALLOW_CONST /*flags*/);
71614}
71615
71618}
71619
71620/* The issues below can be solved with better flags */
71621
71622/* XXX: many operations actually want toforcedtemp() -- brand new temp? */
71623/* XXX: need a toplain_ignore() which will only coerce a value to a temp
71624 * register if it might have a side effect. Side-effect free values do not
71625 * need to be coerced.
71626 */
71627
71628/*
71629 * Identifier handling
71630 */
71631
71633 duk_hthread *thr = comp_ctx->thr;
71634 duk_hstring *h_varname;
71635 duk_regconst_t ret;
71636
71637 DUK_DDD(DUK_DDDPRINT("resolving identifier reference to '%!T'", (duk_tval *) duk_get_tval(thr, -1)));
71638
71639 /*
71640 * Special name handling
71641 */
71642
71643 h_varname = duk_known_hstring(thr, -1);
71644
71645 if (h_varname == DUK_HTHREAD_STRING_LC_ARGUMENTS(thr)) {
71646 DUK_DDD(DUK_DDDPRINT("flagging function as accessing 'arguments'"));
71647 comp_ctx->curr_func.id_access_arguments = 1;
71648 }
71649
71650 /*
71651 * Inside one or more 'with' statements fall back to slow path always.
71652 * (See e.g. test-stmt-with.js.)
71653 */
71654
71655 if (comp_ctx->curr_func.with_depth > 0) {
71656 DUK_DDD(DUK_DDDPRINT("identifier lookup inside a 'with' -> fall back to slow path"));
71657 goto slow_path_own;
71658 }
71659
71660 /*
71661 * Any catch bindings ("catch (e)") also affect identifier binding.
71662 *
71663 * Currently, the varmap is modified for the duration of the catch
71664 * clause to ensure any identifier accesses with the catch variable
71665 * name will use slow path.
71666 */
71667
71668 duk_get_prop(thr, comp_ctx->curr_func.varmap_idx);
71669 if (duk_is_number(thr, -1)) {
71670 ret = duk_to_int(thr, -1);
71671 duk_pop(thr);
71672 } else {
71673 duk_pop(thr);
71674 if (comp_ctx->curr_func.catch_depth > 0 || comp_ctx->curr_func.with_depth > 0) {
71675 DUK_DDD(DUK_DDDPRINT("slow path access from inside a try-catch or with needs _Varmap"));
71676 goto slow_path_own;
71677 } else {
71678 /* In this case we're doing a variable lookup that doesn't
71679 * match our own variables, so _Varmap won't be needed at
71680 * run time.
71681 */
71682 DUK_DDD(DUK_DDDPRINT("slow path access outside of try-catch and with, no need for _Varmap"));
71683 goto slow_path_notown;
71684 }
71685 }
71686
71687 DUK_DDD(DUK_DDDPRINT("identifier lookup -> reg %ld", (long) ret));
71688 return ret;
71689
71690slow_path_notown:
71691 DUK_DDD(DUK_DDDPRINT("identifier lookup -> slow path, not own variable"));
71692
71693 comp_ctx->curr_func.id_access_slow = 1;
71694 return (duk_regconst_t) -1;
71695
71696slow_path_own:
71697 DUK_DDD(DUK_DDDPRINT("identifier lookup -> slow path, may be own variable"));
71698
71699 comp_ctx->curr_func.id_access_slow = 1;
71700 comp_ctx->curr_func.id_access_slow_own = 1;
71701 return (duk_regconst_t) -1;
71702}
71703
71704/* Lookup an identifier name in the current varmap, indicating whether the
71705 * identifier is register-bound and if not, allocating a constant for the
71706 * identifier name. Returns 1 if register-bound, 0 otherwise. Caller can
71707 * also check (out_reg_varbind >= 0) to check whether or not identifier is
71708 * register bound. The caller must NOT use out_rc_varname at all unless
71709 * return code is 0 or out_reg_varbind is < 0; this is becuase out_rc_varname
71710 * is unsigned and doesn't have a "unused" / none value.
71711 */
71712DUK_LOCAL duk_bool_t duk__lookup_lhs(duk_compiler_ctx *comp_ctx, duk_regconst_t *out_reg_varbind, duk_regconst_t *out_rc_varname) {
71713 duk_hthread *thr = comp_ctx->thr;
71714 duk_regconst_t reg_varbind;
71715 duk_regconst_t rc_varname;
71716
71717 /* [ ... varname ] */
71718
71719 duk_dup_top(thr);
71720 reg_varbind = duk__lookup_active_register_binding(comp_ctx);
71721
71722 if (reg_varbind >= 0) {
71723 *out_reg_varbind = reg_varbind;
71724 *out_rc_varname = 0; /* duk_regconst_t is unsigned, so use 0 as dummy value (ignored by caller) */
71725 duk_pop(thr);
71726 return 1;
71727 } else {
71728 rc_varname = duk__getconst(comp_ctx);
71729 *out_reg_varbind = -1;
71730 *out_rc_varname = rc_varname;
71731 return 0;
71732 }
71733}
71734
71735/*
71736 * Label handling
71737 *
71738 * Labels are initially added with flags prohibiting both break and continue.
71739 * When the statement type is finally uncovered (after potentially multiple
71740 * labels), all the labels are updated to allow/prohibit break and continue.
71741 */
71742
71743DUK_LOCAL void duk__add_label(duk_compiler_ctx *comp_ctx, duk_hstring *h_label, duk_int_t pc_label, duk_int_t label_id) {
71744 duk_hthread *thr = comp_ctx->thr;
71745 duk_size_t n;
71746 duk_size_t new_size;
71747 duk_uint8_t *p;
71748 duk_labelinfo *li_start, *li;
71749
71750 /* Duplicate (shadowing) labels are not allowed, except for the empty
71751 * labels (which are used as default labels for switch and iteration
71752 * statements).
71753 *
71754 * We could also allow shadowing of non-empty pending labels without any
71755 * other issues than breaking the required label shadowing requirements
71756 * of the E5 specification, see Section 12.12.
71757 */
71758
71759 p = (duk_uint8_t *) DUK_HBUFFER_DYNAMIC_GET_DATA_PTR(thr->heap, comp_ctx->curr_func.h_labelinfos);
71760 li_start = (duk_labelinfo *) (void *) p;
71761 li = (duk_labelinfo *) (void *) (p + DUK_HBUFFER_GET_SIZE(comp_ctx->curr_func.h_labelinfos));
71762 n = (duk_size_t) (li - li_start);
71763
71764 while (li > li_start) {
71765 li--;
71766
71767 if (li->h_label == h_label && h_label != DUK_HTHREAD_STRING_EMPTY_STRING(thr)) {
71769 DUK_WO_NORETURN(return;);
71770 }
71771 }
71772
71773 duk_push_hstring(thr, h_label);
71774 DUK_ASSERT(n <= DUK_UARRIDX_MAX); /* label limits */
71775 (void) duk_put_prop_index(thr, comp_ctx->curr_func.labelnames_idx, (duk_uarridx_t) n);
71776
71777 new_size = (n + 1) * sizeof(duk_labelinfo);
71778 duk_hbuffer_resize(thr, comp_ctx->curr_func.h_labelinfos, new_size);
71779 /* XXX: slack handling, slow now */
71780
71781 /* relookup after possible realloc */
71782 p = (duk_uint8_t *) DUK_HBUFFER_DYNAMIC_GET_DATA_PTR(thr->heap, comp_ctx->curr_func.h_labelinfos);
71783 li_start = (duk_labelinfo *) (void *) p;
71784 DUK_UNREF(li_start); /* silence scan-build warning */
71785 li = (duk_labelinfo *) (void *) (p + DUK_HBUFFER_GET_SIZE(comp_ctx->curr_func.h_labelinfos));
71786 li--;
71787
71788 /* Labels can be used for iteration statements but also for other statements,
71789 * in particular a label can be used for a block statement. All cases of a
71790 * named label accept a 'break' so that flag is set here. Iteration statements
71791 * also allow 'continue', so that flag is updated when we figure out the
71792 * statement type.
71793 */
71794
71796 li->label_id = label_id;
71797 li->h_label = h_label;
71798 li->catch_depth = comp_ctx->curr_func.catch_depth; /* catch depth from current func */
71799 li->pc_label = pc_label;
71800
71801 DUK_DDD(DUK_DDDPRINT("registered label: flags=0x%08lx, id=%ld, name=%!O, catch_depth=%ld, pc_label=%ld",
71802 (unsigned long) li->flags,
71803 (long) li->label_id,
71804 (duk_heaphdr *) li->h_label,
71805 (long) li->catch_depth,
71806 (long) li->pc_label));
71807}
71808
71809/* Update all labels with matching label_id. */
71811 duk_uint8_t *p;
71812 duk_labelinfo *li_start, *li;
71813
71814 p = (duk_uint8_t *) DUK_HBUFFER_DYNAMIC_GET_DATA_PTR(comp_ctx->thr->heap, comp_ctx->curr_func.h_labelinfos);
71815 li_start = (duk_labelinfo *) (void *) p;
71816 li = (duk_labelinfo *) (void *) (p + DUK_HBUFFER_GET_SIZE(comp_ctx->curr_func.h_labelinfos));
71817
71818 /* Match labels starting from latest; once label_id no longer matches, we can
71819 * safely exit without checking the rest of the labels (only the topmost labels
71820 * are ever updated).
71821 */
71822 while (li > li_start) {
71823 li--;
71824
71825 if (li->label_id != label_id) {
71826 break;
71827 }
71828
71829 DUK_DDD(DUK_DDDPRINT("updating (overwriting) label flags for li=%p, label_id=%ld, flags=%ld",
71830 (void *) li,
71831 (long) label_id,
71832 (long) flags));
71833
71834 li->flags = flags;
71835 }
71836}
71837
71838/* Lookup active label information. Break/continue distinction is necessary to handle switch
71839 * statement related labels correctly: a switch will only catch a 'break', not a 'continue'.
71840 *
71841 * An explicit label cannot appear multiple times in the active set, but empty labels (unlabelled
71842 * iteration and switch statements) can. A break will match the closest unlabelled or labelled
71843 * statement. A continue will match the closest unlabelled or labelled iteration statement. It is
71844 * a syntax error if a continue matches a labelled switch statement; because an explicit label cannot
71845 * be duplicated, the continue cannot match any valid label outside the switch.
71846 *
71847 * A side effect of these rules is that a LABEL statement related to a switch should never actually
71848 * catch a continue abrupt completion at run-time. Hence an INVALID opcode can be placed in the
71849 * continue slot of the switch's LABEL statement.
71850 */
71851
71852/* XXX: awkward, especially the bunch of separate output values -> output struct? */
71854 duk_hstring *h_label,
71855 duk_bool_t is_break,
71856 duk_int_t *out_label_id,
71857 duk_int_t *out_label_catch_depth,
71858 duk_int_t *out_label_pc,
71859 duk_bool_t *out_is_closest) {
71860 duk_hthread *thr = comp_ctx->thr;
71861 duk_uint8_t *p;
71862 duk_labelinfo *li_start, *li_end, *li;
71863 duk_bool_t match = 0;
71864
71865 DUK_DDD(DUK_DDDPRINT("looking up active label: label='%!O', is_break=%ld", (duk_heaphdr *) h_label, (long) is_break));
71866
71867 DUK_UNREF(thr);
71868
71869 p = (duk_uint8_t *) DUK_HBUFFER_DYNAMIC_GET_DATA_PTR(thr->heap, comp_ctx->curr_func.h_labelinfos);
71870 li_start = (duk_labelinfo *) (void *) p;
71871 li_end = (duk_labelinfo *) (void *) (p + DUK_HBUFFER_GET_SIZE(comp_ctx->curr_func.h_labelinfos));
71872 li = li_end;
71873
71874 /* Match labels starting from latest label because there can be duplicate empty
71875 * labels in the label set.
71876 */
71877 while (li > li_start) {
71878 li--;
71879
71880 if (li->h_label != h_label) {
71881 DUK_DDD(DUK_DDDPRINT("labelinfo[%ld] ->'%!O' != %!O",
71882 (long) (li - li_start),
71883 (duk_heaphdr *) li->h_label,
71884 (duk_heaphdr *) h_label));
71885 continue;
71886 }
71887
71888 DUK_DDD(DUK_DDDPRINT("labelinfo[%ld] -> '%!O' label name matches (still need to check type)",
71889 (long) (li - li_start),
71890 (duk_heaphdr *) h_label));
71891
71892 /* currently all labels accept a break, so no explicit check for it now */
71894
71895 if (is_break) {
71896 /* break matches always */
71897 match = 1;
71898 break;
71899 } else if (li->flags & DUK_LABEL_FLAG_ALLOW_CONTINUE) {
71900 /* iteration statements allow continue */
71901 match = 1;
71902 break;
71903 } else {
71904 /* continue matched this label -- we can only continue if this is the empty
71905 * label, for which duplication is allowed, and thus there is hope of
71906 * finding a match deeper in the label stack.
71907 */
71908 if (h_label != DUK_HTHREAD_STRING_EMPTY_STRING(thr)) {
71910 DUK_WO_NORETURN(return;);
71911 } else {
71912 DUK_DDD(DUK_DDDPRINT("continue matched an empty label which does not "
71913 "allow a continue -> continue lookup deeper in label stack"));
71915 }
71916 }
71917 /* XXX: match flag is awkward, rework */
71918 if (!match) {
71920 DUK_WO_NORETURN(return;);
71921 }
71922
71923 DUK_DDD(DUK_DDDPRINT("label match: %!O -> label_id %ld, catch_depth=%ld, pc_label=%ld",
71924 (duk_heaphdr *) h_label,
71925 (long) li->label_id,
71926 (long) li->catch_depth,
71927 (long) li->pc_label));
71928
71929 *out_label_id = li->label_id;
71930 *out_label_catch_depth = li->catch_depth;
71931 *out_label_pc = li->pc_label;
71932 *out_is_closest = (li == li_end - 1);
71933}
71936 duk_hthread *thr = comp_ctx->thr;
71937
71938 duk_set_length(thr, comp_ctx->curr_func.labelnames_idx, len);
71939 duk_hbuffer_resize(thr, comp_ctx->curr_func.h_labelinfos, sizeof(duk_labelinfo) * len);
71940}
71941
71942/*
71943 * Expression parsing: duk__expr_nud(), duk__expr_led(), duk__expr_lbp(), and helpers.
71944 *
71945 * - duk__expr_nud(): ("null denotation"): process prev_token as a "start" of an expression (e.g. literal)
71946 * - duk__expr_led(): ("left denotation"): process prev_token in the "middle" of an expression (e.g. operator)
71947 * - duk__expr_lbp(): ("left-binding power"): return left-binding power of curr_token
71948 */
71949
71950/* object literal key tracking flags */
71951#define DUK__OBJ_LIT_KEY_PLAIN (1 << 0) /* key encountered as a plain property */
71952#define DUK__OBJ_LIT_KEY_GET (1 << 1) /* key encountered as a getter */
71953#define DUK__OBJ_LIT_KEY_SET (1 << 2) /* key encountered as a setter */
71954
71956 duk_hthread *thr = comp_ctx->thr;
71957 duk_regconst_t reg_obj; /* result reg */
71958 duk_regconst_t reg_temp; /* temp reg */
71959 duk_regconst_t temp_start; /* temp reg value for start of loop */
71960 duk_small_uint_t max_init_values; /* max # of values initialized in one MPUTARR set */
71961 duk_small_uint_t num_values; /* number of values in current MPUTARR set */
71962 duk_uarridx_t curr_idx; /* current (next) array index */
71963 duk_uarridx_t start_idx; /* start array index of current MPUTARR set */
71964 duk_uarridx_t init_idx; /* last array index explicitly initialized, +1 */
71965 duk_bool_t require_comma; /* next loop requires a comma */
71966#if !defined(DUK_USE_PREFER_SIZE)
71967 duk_int_t pc_newarr;
71968 duk_compiler_instr *instr;
71969#endif
71970
71971 /* DUK_TOK_LBRACKET already eaten, current token is right after that */
71973
71974 max_init_values = DUK__MAX_ARRAY_INIT_VALUES; /* XXX: depend on available temps? */
71975
71976 reg_obj = DUK__ALLOCTEMP(comp_ctx);
71977#if !defined(DUK_USE_PREFER_SIZE)
71978 pc_newarr = duk__get_current_pc(comp_ctx);
71979#endif
71980 duk__emit_bc(comp_ctx, DUK_OP_NEWARR, reg_obj); /* XXX: patch initial size hint afterwards? */
71981 temp_start = DUK__GETTEMP(comp_ctx);
71982
71983 /*
71984 * Emit initializers in sets of maximum max_init_values.
71985 * Corner cases such as single value initializers do not have
71986 * special handling now.
71987 *
71988 * Elided elements must not be emitted as 'undefined' values,
71989 * because such values would be enumerable (which is incorrect).
71990 * Also note that trailing elisions must be reflected in the
71991 * length of the final array but cause no elements to be actually
71992 * inserted.
71993 */
71994
71995 curr_idx = 0;
71996 init_idx = 0; /* tracks maximum initialized index + 1 */
71997 start_idx = 0;
71998 require_comma = 0;
71999
72000 for (;;) {
72001 num_values = 0;
72002 DUK__SETTEMP(comp_ctx, temp_start);
72003
72004 if (comp_ctx->curr_token.t == DUK_TOK_RBRACKET) {
72005 break;
72006 }
72007
72008 for (;;) {
72009 if (comp_ctx->curr_token.t == DUK_TOK_RBRACKET) {
72010 /* the outer loop will recheck and exit */
72011 break;
72012 }
72013
72014 /* comma check */
72015 if (require_comma) {
72016 if (comp_ctx->curr_token.t == DUK_TOK_COMMA) {
72017 /* comma after a value, expected */
72018 duk__advance(comp_ctx);
72019 require_comma = 0;
72020 continue;
72021 } else {
72022 goto syntax_error;
72023 }
72024 } else {
72025 if (comp_ctx->curr_token.t == DUK_TOK_COMMA) {
72026 /* elision - flush */
72027 curr_idx++;
72028 duk__advance(comp_ctx);
72029 /* if num_values > 0, MPUTARR emitted by outer loop after break */
72030 break;
72031 }
72032 }
72033 /* else an array initializer element */
72034
72035 /* initial index */
72036 if (num_values == 0) {
72037 start_idx = curr_idx;
72038 reg_temp = DUK__ALLOCTEMP(comp_ctx);
72039 duk__emit_load_int32(comp_ctx, reg_temp, (duk_int32_t) start_idx);
72040 }
72041
72042 reg_temp = DUK__ALLOCTEMP(comp_ctx); /* alloc temp just in case, to update max temp */
72043 DUK__SETTEMP(comp_ctx, reg_temp);
72044 duk__expr_toforcedreg(comp_ctx, res, DUK__BP_COMMA /*rbp_flags*/, reg_temp /*forced_reg*/);
72045 DUK__SETTEMP(comp_ctx, reg_temp + 1);
72046
72047 num_values++;
72048 curr_idx++;
72049 require_comma = 1;
72050
72051 if (num_values >= max_init_values) {
72052 /* MPUTARR emitted by outer loop */
72053 break;
72054 }
72055 }
72056
72057 if (num_values > 0) {
72058 /* - A is a source register (it's not a write target, but used
72059 * to identify the target object) but can be shuffled.
72060 * - B cannot be shuffled normally because it identifies a range
72061 * of registers, the emitter has special handling for this
72062 * (the "no shuffle" flag must not be set).
72063 * - C is a non-register number and cannot be shuffled, but
72064 * never needs to be.
72065 */
72066 duk__emit_a_b_c(comp_ctx,
72068 reg_obj,
72069 temp_start,
72070 (duk_regconst_t) (num_values + 1));
72071 init_idx = start_idx + num_values;
72072
72073 /* num_values and temp_start reset at top of outer loop */
72074 }
72075 }
72076
72077 /* Update initil size for NEWARR, doesn't need to be exact and is
72078 * capped at A field limit.
72079 */
72080#if !defined(DUK_USE_PREFER_SIZE)
72081 instr = duk__get_instr_ptr(comp_ctx, pc_newarr);
72082 instr->ins |= DUK_ENC_OP_A(0, curr_idx > DUK_BC_A_MAX ? DUK_BC_A_MAX : curr_idx);
72083#endif
72084
72086 duk__advance(comp_ctx);
72087
72088 DUK_DDD(DUK_DDDPRINT("array literal done, curridx=%ld, initidx=%ld", (long) curr_idx, (long) init_idx));
72090 /* trailing elisions? */
72091 if (curr_idx > init_idx) {
72092 /* yes, must set array length explicitly */
72093 DUK_DDD(DUK_DDDPRINT("array literal has trailing elisions which affect its length"));
72094 reg_temp = DUK__ALLOCTEMP(comp_ctx);
72095 duk__emit_load_int32(comp_ctx, reg_temp, (duk_int_t) curr_idx);
72096 duk__emit_a_bc(comp_ctx, DUK_OP_SETALEN | DUK__EMIT_FLAG_A_IS_SOURCE, reg_obj, reg_temp);
72097 }
72098
72099 DUK__SETTEMP(comp_ctx, temp_start);
72100
72101 duk__ivalue_regconst(res, reg_obj);
72102 return;
72103
72104syntax_error:
72106 DUK_WO_NORETURN(return;);
72107}
72108
72109typedef struct {
72110 duk_regconst_t reg_obj;
72111 duk_regconst_t temp_start;
72112 duk_small_uint_t num_pairs;
72113 duk_small_uint_t num_total_pairs;
72115
72117 if (st->num_pairs > 0) {
72118 /* - A is a source register (it's not a write target, but used
72119 * to identify the target object) but can be shuffled.
72120 * - B cannot be shuffled normally because it identifies a range
72121 * of registers, the emitter has special handling for this
72122 * (the "no shuffle" flag must not be set).
72123 * - C is a non-register number and cannot be shuffled, but
72124 * never needs to be.
72125 */
72126 DUK_ASSERT(st->num_pairs > 0);
72127 duk__emit_a_b_c(comp_ctx,
72129 st->reg_obj,
72130 st->temp_start,
72131 (duk_regconst_t) (st->num_pairs * 2));
72132 st->num_total_pairs += st->num_pairs;
72133 st->num_pairs = 0;
72134 }
72135 DUK__SETTEMP(comp_ctx, st->temp_start);
72137
72139 if (tok->t_nores == DUK_TOK_IDENTIFIER || tok->t_nores == DUK_TOK_STRING) {
72140 /* same handling for identifiers and strings */
72141 DUK_ASSERT(tok->str1 != NULL);
72142 duk_push_hstring(comp_ctx->thr, tok->str1);
72143 } else if (tok->t == DUK_TOK_NUMBER) {
72144 /* numbers can be loaded as numbers and coerced on the fly */
72145 duk_push_number(comp_ctx->thr, tok->num);
72146 } else {
72147 return 1; /* error */
72148 }
72149
72150 duk__ivalue_plain_fromstack(comp_ctx, res);
72151 DUK__SETTEMP(comp_ctx, reg_temp + 1);
72152 duk__ivalue_toforcedreg(comp_ctx, res, reg_temp);
72153 DUK__SETTEMP(comp_ctx, reg_temp + 1);
72154 return 0;
72155}
72156
72158 duk_hthread *thr = comp_ctx->thr;
72160 duk_regconst_t reg_temp; /* temp reg */
72161 duk_small_uint_t max_init_pairs; /* max # of key-value pairs initialized in one MPUTOBJ set */
72162 duk_bool_t first; /* first value: comma must not precede the value */
72163 duk_bool_t is_set, is_get; /* temps */
72164#if !defined(DUK_USE_PREFER_SIZE)
72165 duk_int_t pc_newobj;
72166 duk_compiler_instr *instr;
72167#endif
72168
72169 DUK_ASSERT(comp_ctx->prev_token.t == DUK_TOK_LCURLY);
72170
72171 max_init_pairs = DUK__MAX_OBJECT_INIT_PAIRS; /* XXX: depend on available temps? */
72172
72173 st.reg_obj = DUK__ALLOCTEMP(comp_ctx); /* target object */
72174 st.temp_start = DUK__GETTEMP(comp_ctx); /* start of MPUTOBJ argument list */
72175 st.num_pairs = 0; /* number of key/value pairs emitted for current MPUTOBJ set */
72176 st.num_total_pairs = 0; /* number of key/value pairs emitted overall */
72177
72178#if !defined(DUK_USE_PREFER_SIZE)
72179 pc_newobj = duk__get_current_pc(comp_ctx);
72180#endif
72181 duk__emit_bc(comp_ctx, DUK_OP_NEWOBJ, st.reg_obj);
72182
72183 /*
72184 * Emit initializers in sets of maximum max_init_pairs keys.
72185 * Setter/getter is handled separately and terminates the
72186 * current set of initializer values. Corner cases such as
72187 * single value initializers do not have special handling now.
72188 */
72189
72190 first = 1;
72191 for (;;) {
72192 /*
72193 * ES5 and ES2015+ provide a lot of different PropertyDefinition
72194 * formats, see http://www.ecma-international.org/ecma-262/6.0/#sec-object-initializer.
72195 *
72196 * PropertyName can be IdentifierName (includes reserved words), a string
72197 * literal, or a number literal. Note that IdentifierName allows 'get' and
72198 * 'set' too, so we need to look ahead to the next token to distinguish:
72199 *
72200 * { get : 1 }
72201 *
72202 * and
72203 *
72204 * { get foo() { return 1 } }
72205 * { get get() { return 1 } } // 'get' as getter propertyname
72206 *
72207 * Finally, a trailing comma is allowed.
72208 *
72209 * Key name is coerced to string at compile time (and ends up as a
72210 * a string constant) even for numeric keys (e.g. "{1:'foo'}").
72211 * These could be emitted using e.g. LDINT, but that seems hardly
72212 * worth the effort and would increase code size.
72213 */
72214
72215 DUK_DDD(DUK_DDDPRINT("object literal loop, curr_token->t = %ld", (long) comp_ctx->curr_token.t));
72216
72217 if (comp_ctx->curr_token.t == DUK_TOK_RCURLY) {
72218 break;
72219 }
72220
72221 if (first) {
72222 first = 0;
72223 } else {
72224 if (comp_ctx->curr_token.t != DUK_TOK_COMMA) {
72225 goto syntax_error;
72226 }
72227 duk__advance(comp_ctx);
72228 if (comp_ctx->curr_token.t == DUK_TOK_RCURLY) {
72229 /* trailing comma followed by rcurly */
72230 break;
72231 }
72232 }
72233
72234 /* Advance to get one step of lookup. */
72235 duk__advance(comp_ctx);
72236
72237 /* Flush current MPUTOBJ if enough many pairs gathered. */
72238 if (st.num_pairs >= max_init_pairs) {
72239 duk__objlit_flush_keys(comp_ctx, &st);
72240 DUK_ASSERT(st.num_pairs == 0);
72241 }
72242
72243 /* Reset temp register state and reserve reg_temp and
72244 * reg_temp + 1 for handling the current property.
72245 */
72246 DUK__SETTEMP(comp_ctx, st.temp_start + 2 * (duk_regconst_t) st.num_pairs);
72247 reg_temp = DUK__ALLOCTEMPS(comp_ctx, 2);
72248
72249 /* NOTE: "get" and "set" are not officially ReservedWords and the lexer
72250 * currently treats them always like ordinary identifiers (DUK_TOK_GET
72251 * and DUK_TOK_SET are unused). They need to be detected based on the
72252 * identifier string content.
72253 */
72254
72255 is_get = (comp_ctx->prev_token.t == DUK_TOK_IDENTIFIER && comp_ctx->prev_token.str1 == DUK_HTHREAD_STRING_GET(thr));
72256 is_set = (comp_ctx->prev_token.t == DUK_TOK_IDENTIFIER && comp_ctx->prev_token.str1 == DUK_HTHREAD_STRING_SET(thr));
72257 if ((is_get || is_set) && comp_ctx->curr_token.t != DUK_TOK_COLON) {
72258 /* getter/setter */
72259 duk_int_t fnum;
72260
72261 duk__objlit_flush_keys(comp_ctx, &st);
72262 DUK_ASSERT(DUK__GETTEMP(comp_ctx) ==
72263 st.temp_start); /* 2 regs are guaranteed to be allocated w.r.t. temp_max */
72264 reg_temp = DUK__ALLOCTEMPS(comp_ctx, 2);
72265
72266 if (duk__objlit_load_key(comp_ctx, res, &comp_ctx->curr_token, reg_temp) != 0) {
72267 goto syntax_error;
72268 }
72269
72270 /* curr_token = get/set name */
72272
72273 duk__emit_a_bc(comp_ctx, DUK_OP_CLOSURE, st.temp_start + 1, (duk_regconst_t) fnum);
72274
72275 /* Slot C is used in a non-standard fashion (range of regs),
72276 * emitter code has special handling for it (must not set the
72277 * "no shuffle" flag).
72278 */
72279 duk__emit_a_bc(comp_ctx,
72281 st.reg_obj,
72282 st.temp_start); /* temp_start+0 = key, temp_start+1 = closure */
72283
72284 DUK_ASSERT(st.num_pairs == 0); /* temp state is reset on next loop */
72285#if defined(DUK_USE_ES6)
72286 } else if (comp_ctx->prev_token.t == DUK_TOK_IDENTIFIER &&
72287 (comp_ctx->curr_token.t == DUK_TOK_COMMA || comp_ctx->curr_token.t == DUK_TOK_RCURLY)) {
72288 duk_bool_t load_rc;
72289
72290 load_rc = duk__objlit_load_key(comp_ctx, res, &comp_ctx->prev_token, reg_temp);
72291 DUK_UNREF(load_rc);
72292 DUK_ASSERT(load_rc == 0); /* always succeeds because token is identifier */
72293
72294 duk__ivalue_var_hstring(comp_ctx, res, comp_ctx->prev_token.str1);
72295 DUK_ASSERT(DUK__GETTEMP(comp_ctx) == reg_temp + 1);
72296 duk__ivalue_toforcedreg(comp_ctx, res, reg_temp + 1);
72297
72298 st.num_pairs++;
72299 } else if ((comp_ctx->prev_token.t == DUK_TOK_IDENTIFIER || comp_ctx->prev_token.t == DUK_TOK_STRING ||
72300 comp_ctx->prev_token.t == DUK_TOK_NUMBER) &&
72301 comp_ctx->curr_token.t == DUK_TOK_LPAREN) {
72302 duk_int_t fnum;
72303
72304 /* Parsing-wise there's a small hickup here: the token parsing
72305 * state is one step too advanced for the function parse helper
72306 * compared to other cases. The current solution is an extra
72307 * flag to indicate whether function parsing should use the
72308 * current or the previous token to starting parsing from.
72309 */
72310
72311 if (duk__objlit_load_key(comp_ctx, res, &comp_ctx->prev_token, reg_temp) != 0) {
72312 goto syntax_error;
72313 }
72314
72316
72317 duk__emit_a_bc(comp_ctx, DUK_OP_CLOSURE, reg_temp + 1, (duk_regconst_t) fnum);
72318
72319 st.num_pairs++;
72320#endif /* DUK_USE_ES6 */
72321 } else {
72322#if defined(DUK_USE_ES6)
72323 if (comp_ctx->prev_token.t == DUK_TOK_LBRACKET) {
72324 /* ES2015 computed property name. Executor ToPropertyKey()
72325 * coerces the key at runtime.
72326 */
72327 DUK__SETTEMP(comp_ctx, reg_temp);
72328 duk__expr_toforcedreg(comp_ctx, res, DUK__BP_FOR_EXPR, reg_temp);
72330
72331 /* XXX: If next token is '(' we're dealing with
72332 * the method shorthand with a computed name,
72333 * e.g. { [Symbol.for('foo')](a,b) {} }. This
72334 * form is not yet supported and causes a
72335 * SyntaxError on the DUK_TOK_COLON check below.
72336 */
72337 } else
72338#endif /* DUK_USE_ES6 */
72339 {
72340 if (duk__objlit_load_key(comp_ctx, res, &comp_ctx->prev_token, reg_temp) != 0) {
72341 goto syntax_error;
72342 }
72343 }
72344
72346
72347 DUK__SETTEMP(comp_ctx, reg_temp + 1);
72348 duk__expr_toforcedreg(comp_ctx, res, DUK__BP_COMMA /*rbp_flags*/, reg_temp + 1 /*forced_reg*/);
72349
72350 st.num_pairs++;
72351 }
72352 } /* property loop */
72353
72354 /* Flush remaining properties. */
72355 duk__objlit_flush_keys(comp_ctx, &st);
72356 DUK_ASSERT(st.num_pairs == 0);
72357 DUK_ASSERT(DUK__GETTEMP(comp_ctx) == st.temp_start);
72358
72359 /* Update initial size for NEWOBJ. The init size doesn't need to be
72360 * exact as the purpose is just to avoid object resizes in common
72361 * cases. The size is capped to field A limit, and will be too high
72362 * if the object literal contains duplicate keys (this is harmless but
72363 * increases memory traffic if the object is compacted later on).
72365#if !defined(DUK_USE_PREFER_SIZE)
72366 instr = duk__get_instr_ptr(comp_ctx, pc_newobj);
72368#endif
72369
72370 DUK_ASSERT(comp_ctx->curr_token.t == DUK_TOK_RCURLY);
72371 duk__advance(comp_ctx); /* No RegExp after object literal. */
72372
72374 return;
72375
72376syntax_error:
72378 DUK_WO_NORETURN(return;);
72379}
72380
72381/* Parse argument list. Arguments are written to temps starting from
72382 * "next temp". Returns number of arguments parsed. Expects left paren
72383 * to be already eaten, and eats the right paren before returning.
72384 */
72386 duk_int_t nargs = 0;
72387 duk_regconst_t reg_temp;
72388
72389 /* Note: expect that caller has already eaten the left paren */
72390
72391 DUK_DDD(DUK_DDDPRINT("start parsing arguments, prev_token.t=%ld, curr_token.t=%ld",
72392 (long) comp_ctx->prev_token.t,
72393 (long) comp_ctx->curr_token.t));
72394
72395 for (;;) {
72396 if (comp_ctx->curr_token.t == DUK_TOK_RPAREN) {
72397 break;
72398 }
72399 if (nargs > 0) {
72401 }
72402
72403 /* We want the argument expression value to go to "next temp"
72404 * without additional moves. That should almost always be the
72405 * case, but we double check after expression parsing.
72406 *
72407 * This is not the cleanest possible approach.
72408 */
72409
72410 reg_temp = DUK__ALLOCTEMP(comp_ctx); /* bump up "allocated" reg count, just in case */
72411 DUK__SETTEMP(comp_ctx, reg_temp);
72413 /* binding power must be high enough to NOT allow comma expressions directly */
72414 duk__expr_toforcedreg(comp_ctx,
72415 res,
72416 DUK__BP_COMMA /*rbp_flags*/,
72417 reg_temp); /* always allow 'in', coerce to 'tr' just in case */
72418
72419 DUK__SETTEMP(comp_ctx, reg_temp + 1);
72420 nargs++;
72421
72422 DUK_DDD(DUK_DDDPRINT("argument #%ld written into reg %ld", (long) nargs, (long) reg_temp));
72423 }
72424
72425 /* eat the right paren */
72426 duk__advance_expect(comp_ctx, DUK_TOK_RPAREN); /* RegExp mode does not matter. */
72427
72428 DUK_DDD(DUK_DDDPRINT("end parsing arguments"));
72429
72430 return nargs;
72431}
72432
72434 /* empty expressions can be detected conveniently with nud/led counts */
72435 return (comp_ctx->curr_func.nud_count == 0) && (comp_ctx->curr_func.led_count == 0);
72436}
72437
72438DUK_LOCAL void duk__expr_nud(duk_compiler_ctx *comp_ctx, duk_ivalue *res) {
72439 duk_hthread *thr = comp_ctx->thr;
72440 duk_token *tk;
72441 duk_regconst_t temp_at_entry;
72442 duk_small_uint_t tok;
72443 duk_uint32_t args; /* temp variable to pass constants and flags to shared code */
72444
72445 /*
72446 * ctx->prev_token token to process with duk__expr_nud()
72447 * ctx->curr_token updated by caller
72448 *
72449 * Note: the token in the switch below has already been eaten.
72450 */
72451
72452 temp_at_entry = DUK__GETTEMP(comp_ctx);
72453
72454 comp_ctx->curr_func.nud_count++;
72455
72456 tk = &comp_ctx->prev_token;
72457 tok = tk->t;
72458 res->t = DUK_IVAL_NONE;
72459
72460 DUK_DDD(DUK_DDDPRINT("duk__expr_nud(), prev_token.t=%ld, allow_in=%ld, paren_level=%ld",
72461 (long) tk->t,
72462 (long) comp_ctx->curr_func.allow_in,
72463 (long) comp_ctx->curr_func.paren_level));
72464
72465 switch (tok) {
72466 /* PRIMARY EXPRESSIONS */
72467
72468 case DUK_TOK_THIS: {
72469 duk_regconst_t reg_temp;
72470 reg_temp = DUK__ALLOCTEMP(comp_ctx);
72471 duk__emit_bc(comp_ctx, DUK_OP_LDTHIS, reg_temp);
72472 duk__ivalue_regconst(res, reg_temp);
72473 return;
72474 }
72475 case DUK_TOK_IDENTIFIER: {
72476 duk__ivalue_var_hstring(comp_ctx, res, tk->str1);
72477 return;
72478 }
72479 case DUK_TOK_NULL: {
72480 duk_push_null(thr);
72481 goto plain_value;
72482 }
72483 case DUK_TOK_TRUE: {
72484 duk_push_true(thr);
72485 goto plain_value;
72486 }
72487 case DUK_TOK_FALSE: {
72488 duk_push_false(thr);
72489 goto plain_value;
72490 }
72491 case DUK_TOK_NUMBER: {
72492 duk_push_number(thr, tk->num);
72493 goto plain_value;
72494 }
72495 case DUK_TOK_STRING: {
72496 DUK_ASSERT(tk->str1 != NULL);
72497 duk_push_hstring(thr, tk->str1);
72498 goto plain_value;
72499 }
72500 case DUK_TOK_REGEXP: {
72501#if defined(DUK_USE_REGEXP_SUPPORT)
72502 duk_regconst_t reg_temp;
72503 duk_regconst_t rc_re_bytecode; /* const */
72504 duk_regconst_t rc_re_source; /* const */
72505
72506 DUK_ASSERT(tk->str1 != NULL);
72507 DUK_ASSERT(tk->str2 != NULL);
72508
72509 DUK_DDD(DUK_DDDPRINT("emitting regexp op, str1=%!O, str2=%!O", (duk_heaphdr *) tk->str1, (duk_heaphdr *) tk->str2));
72510
72511 reg_temp = DUK__ALLOCTEMP(comp_ctx);
72512 duk_push_hstring(thr, tk->str1);
72513 duk_push_hstring(thr, tk->str2);
72514
72515 /* [ ... pattern flags ] */
72516
72517 duk_regexp_compile(thr);
72518
72519 /* [ ... escaped_source bytecode ] */
72520
72521 rc_re_bytecode = duk__getconst(comp_ctx);
72522 rc_re_source = duk__getconst(comp_ctx);
72523
72524 duk__emit_a_b_c(comp_ctx,
72526 reg_temp /*a*/,
72527 rc_re_bytecode /*b*/,
72528 rc_re_source /*c*/);
72529
72530 duk__ivalue_regconst(res, reg_temp);
72531 return;
72532#else /* DUK_USE_REGEXP_SUPPORT */
72533 goto syntax_error;
72534#endif /* DUK_USE_REGEXP_SUPPORT */
72535 }
72536 case DUK_TOK_LBRACKET: {
72537 DUK_DDD(DUK_DDDPRINT("parsing array literal"));
72538 duk__nud_array_literal(comp_ctx, res);
72539 return;
72540 }
72541 case DUK_TOK_LCURLY: {
72542 DUK_DDD(DUK_DDDPRINT("parsing object literal"));
72543 duk__nud_object_literal(comp_ctx, res);
72544 return;
72545 }
72546 case DUK_TOK_LPAREN: {
72547 duk_bool_t prev_allow_in;
72548
72549 comp_ctx->curr_func.paren_level++;
72550 prev_allow_in = comp_ctx->curr_func.allow_in;
72551 comp_ctx->curr_func.allow_in = 1; /* reset 'allow_in' for parenthesized expression */
72552
72553 duk__expr(comp_ctx, res, DUK__BP_FOR_EXPR /*rbp_flags*/); /* Expression, terminates at a ')' */
72554
72555 duk__advance_expect(comp_ctx, DUK_TOK_RPAREN); /* No RegExp after parenthesized expression. */
72556 comp_ctx->curr_func.allow_in = prev_allow_in;
72557 comp_ctx->curr_func.paren_level--;
72558 return;
72559 }
72560
72561 /* MEMBER/NEW/CALL EXPRESSIONS */
72562
72563 case DUK_TOK_NEW: {
72564 /*
72565 * Parsing an expression starting with 'new' is tricky because
72566 * there are multiple possible productions deriving from
72567 * LeftHandSideExpression which begin with 'new'.
72568 *
72569 * We currently resort to one-token lookahead to distinguish the
72570 * cases. Hopefully this is correct. The binding power must be
72571 * such that parsing ends at an LPAREN (CallExpression) but not at
72572 * a PERIOD or LBRACKET (MemberExpression).
72573 *
72574 * See doc/compiler.rst for discussion on the parsing approach,
72575 * and testcases/test-dev-new.js for a bunch of documented tests.
72576 */
72577
72578 duk_regconst_t reg_target;
72579 duk_int_t nargs;
72580
72581 DUK_DDD(DUK_DDDPRINT("begin parsing new expression"));
72582
72583 reg_target = DUK__ALLOCTEMPS(comp_ctx, 2);
72584
72585#if defined(DUK_USE_ES6)
72586 if (comp_ctx->curr_token.t == DUK_TOK_PERIOD) {
72587 /* new.target */
72588 DUK_DDD(DUK_DDDPRINT("new.target"));
72589 duk__advance(comp_ctx);
72590 if (comp_ctx->curr_token.t_nores != DUK_TOK_IDENTIFIER ||
72591 !duk_hstring_equals_ascii_cstring(comp_ctx->curr_token.str1, "target")) {
72592 goto syntax_error_newtarget;
72593 }
72594 if (comp_ctx->curr_func.is_global) {
72595 goto syntax_error_newtarget;
72596 }
72597 duk__advance(comp_ctx);
72598 duk__emit_bc(comp_ctx, DUK_OP_NEWTARGET, reg_target);
72599 duk__ivalue_regconst(res, reg_target);
72600 return;
72601 }
72602#endif /* DUK_USE_ES6 */
72603
72604 duk__expr_toforcedreg(comp_ctx, res, DUK__BP_CALL /*rbp_flags*/, reg_target /*forced_reg*/);
72605 duk__emit_bc(comp_ctx, DUK_OP_NEWOBJ, reg_target + 1); /* default instance */
72606 DUK__SETTEMP(comp_ctx, reg_target + 2);
72607
72608 /* XXX: 'new obj.noSuch()' doesn't use GETPROPC now which
72609 * makes the error message worse than for obj.noSuch().
72610 */
72611
72612 if (comp_ctx->curr_token.t == DUK_TOK_LPAREN) {
72613 /* 'new' MemberExpression Arguments */
72614 DUK_DDD(DUK_DDDPRINT("new expression has argument list"));
72615 duk__advance(comp_ctx);
72616 nargs = duk__parse_arguments(comp_ctx, res); /* parse args starting from "next temp", reg_target + 1 */
72617 /* right paren eaten */
72618 } else {
72619 /* 'new' MemberExpression */
72620 DUK_DDD(DUK_DDDPRINT("new expression has no argument list"));
72621 nargs = 0;
72622 }
72623
72624 duk__emit_a_bc(comp_ctx, DUK_OP_CALL0 | DUK_BC_CALL_FLAG_CONSTRUCT, nargs /*num_args*/, reg_target /*target*/);
72625
72626 DUK_DDD(DUK_DDDPRINT("end parsing new expression"));
72627
72628 duk__ivalue_regconst(res, reg_target);
72629 return;
72630 }
72631
72632 /* FUNCTION EXPRESSIONS */
72633
72634 case DUK_TOK_FUNCTION: {
72635 /* Function expression. Note that any statement beginning with 'function'
72636 * is handled by the statement parser as a function declaration, or a
72637 * non-standard function expression/statement (or a SyntaxError). We only
72638 * handle actual function expressions (occurring inside an expression) here.
72639 *
72640 * O(depth^2) parse count for inner functions is handled by recording a
72641 * lexer offset on the first compilation pass, so that the function can
72642 * be efficiently skipped on the second pass. This is encapsulated into
72643 * duk__parse_func_like_fnum().
72644 */
72645
72646 duk_regconst_t reg_temp;
72647 duk_int_t fnum;
72648
72649 reg_temp = DUK__ALLOCTEMP(comp_ctx);
72650
72651 /* curr_token follows 'function' */
72652 fnum = duk__parse_func_like_fnum(comp_ctx, 0 /*flags*/);
72653 DUK_DDD(DUK_DDDPRINT("parsed inner function -> fnum %ld", (long) fnum));
72654
72655 duk__emit_a_bc(comp_ctx, DUK_OP_CLOSURE, reg_temp /*a*/, (duk_regconst_t) fnum /*bc*/);
72656
72657 duk__ivalue_regconst(res, reg_temp);
72658 return;
72659 }
72660
72661 /* UNARY EXPRESSIONS */
72662
72663 case DUK_TOK_DELETE: {
72664 /* Delete semantics are a bit tricky. The description in E5 specification
72665 * is kind of confusing, because it distinguishes between resolvability of
72666 * a reference (which is only known at runtime) seemingly at compile time
72667 * (= SyntaxError throwing).
72668 */
72669 duk__expr(comp_ctx, res, DUK__BP_MULTIPLICATIVE /*rbp_flags*/); /* UnaryExpression */
72670 if (res->t == DUK_IVAL_VAR) {
72671 /* not allowed in strict mode, regardless of whether resolves;
72672 * in non-strict mode DELVAR handles both non-resolving and
72673 * resolving cases (the specification description is a bit confusing).
72674 */
72675
72676 duk_regconst_t reg_temp;
72677 duk_regconst_t reg_varbind;
72678 duk_regconst_t rc_varname;
72679
72680 if (comp_ctx->curr_func.is_strict) {
72682 DUK_WO_NORETURN(return;);
72683 }
72684
72685 DUK__SETTEMP(comp_ctx, temp_at_entry);
72686 reg_temp = DUK__ALLOCTEMP(comp_ctx);
72687
72688 duk_dup(thr, res->x1.valstack_idx);
72689 if (duk__lookup_lhs(comp_ctx, &reg_varbind, &rc_varname)) {
72690 /* register bound variables are non-configurable -> always false */
72691 duk__emit_bc(comp_ctx, DUK_OP_LDFALSE, reg_temp);
72692 } else {
72693 duk_dup(thr, res->x1.valstack_idx);
72694 rc_varname = duk__getconst(comp_ctx);
72695 duk__emit_a_bc(comp_ctx, DUK_OP_DELVAR, reg_temp, rc_varname);
72696 }
72697 duk__ivalue_regconst(res, reg_temp);
72698 } else if (res->t == DUK_IVAL_PROP) {
72699 duk_regconst_t reg_temp;
72700 duk_regconst_t reg_obj;
72701 duk_regconst_t rc_key;
72702
72703 DUK__SETTEMP(comp_ctx, temp_at_entry);
72704 reg_temp = DUK__ALLOCTEMP(comp_ctx);
72705 reg_obj =
72706 duk__ispec_toregconst_raw(comp_ctx, &res->x1, -1 /*forced_reg*/, 0 /*flags*/); /* don't allow const */
72707 rc_key =
72708 duk__ispec_toregconst_raw(comp_ctx, &res->x2, -1 /*forced_reg*/, DUK__IVAL_FLAG_ALLOW_CONST /*flags*/);
72709 duk__emit_a_b_c(comp_ctx, DUK_OP_DELPROP | DUK__EMIT_FLAG_BC_REGCONST, reg_temp, reg_obj, rc_key);
72710
72711 duk__ivalue_regconst(res, reg_temp);
72712 } else {
72713 /* non-Reference deletion is always 'true', even in strict mode */
72714 duk_push_true(thr);
72715 goto plain_value;
72716 }
72717 return;
72718 }
72719 case DUK_TOK_VOID: {
72720 duk__expr_toplain_ignore(comp_ctx, res, DUK__BP_MULTIPLICATIVE /*rbp_flags*/); /* UnaryExpression */
72721 duk_push_undefined(thr);
72722 goto plain_value;
72723 }
72724 case DUK_TOK_TYPEOF: {
72725 /* 'typeof' must handle unresolvable references without throwing
72726 * a ReferenceError (E5 Section 11.4.3). Register mapped values
72727 * will never be unresolvable so special handling is only required
72728 * when an identifier is a "slow path" one.
72729 */
72730 duk__expr(comp_ctx, res, DUK__BP_MULTIPLICATIVE /*rbp_flags*/); /* UnaryExpression */
72731
72732 if (res->t == DUK_IVAL_VAR) {
72733 duk_regconst_t reg_varbind;
72734 duk_regconst_t rc_varname;
72735 duk_regconst_t reg_temp;
72736
72737 duk_dup(thr, res->x1.valstack_idx);
72738 if (!duk__lookup_lhs(comp_ctx, &reg_varbind, &rc_varname)) {
72739 DUK_DDD(DUK_DDDPRINT("typeof for an identifier name which could not be resolved "
72740 "at compile time, need to use special run-time handling"));
72741 reg_temp = DUK__ALLOCTEMP(comp_ctx);
72742 duk__emit_a_bc(comp_ctx, DUK_OP_TYPEOFID, reg_temp, rc_varname);
72743 duk__ivalue_regconst(res, reg_temp);
72744 return;
72745 }
72746 }
72747
72748 args = DUK_OP_TYPEOF;
72749 goto unary;
72750 }
72751 case DUK_TOK_INCREMENT: {
72752 args = (DUK_OP_PREINCP << 8) + DUK_OP_PREINCR;
72753 goto preincdec;
72754 }
72755 case DUK_TOK_DECREMENT: {
72756 args = (DUK_OP_PREDECP << 8) + DUK_OP_PREDECR;
72757 goto preincdec;
72758 }
72759 case DUK_TOK_ADD: {
72760 /* unary plus */
72761 duk__expr(comp_ctx, res, DUK__BP_MULTIPLICATIVE /*rbp_flags*/); /* UnaryExpression */
72762 if (res->t == DUK_IVAL_PLAIN && res->x1.t == DUK_ISPEC_VALUE && duk_is_number(thr, res->x1.valstack_idx)) {
72763 /* unary plus of a number is identity */
72764 return;
72765 }
72766 args = DUK_OP_UNP;
72767 goto unary;
72768 }
72769 case DUK_TOK_SUB: {
72770 /* unary minus */
72771 duk__expr(comp_ctx, res, DUK__BP_MULTIPLICATIVE /*rbp_flags*/); /* UnaryExpression */
72772 if (res->t == DUK_IVAL_PLAIN && res->x1.t == DUK_ISPEC_VALUE && duk_is_number(thr, res->x1.valstack_idx)) {
72773 /* this optimization is important to handle negative literals
72774 * (which are not directly provided by the lexical grammar)
72775 */
72776 duk_tval *tv_num;
72778
72779 tv_num = DUK_GET_TVAL_POSIDX(thr, res->x1.valstack_idx);
72780 DUK_ASSERT(tv_num != NULL);
72782 du.d = DUK_TVAL_GET_NUMBER(tv_num);
72783 du.d = -du.d;
72785 DUK_TVAL_SET_NUMBER(tv_num, du.d);
72786 return;
72787 }
72788 args = DUK_OP_UNM;
72789 goto unary;
72790 }
72791 case DUK_TOK_BNOT: {
72792 duk__expr(comp_ctx, res, DUK__BP_MULTIPLICATIVE /*rbp_flags*/); /* UnaryExpression */
72793 args = DUK_OP_BNOT;
72794 goto unary;
72795 }
72796 case DUK_TOK_LNOT: {
72797 duk__expr(comp_ctx, res, DUK__BP_MULTIPLICATIVE /*rbp_flags*/); /* UnaryExpression */
72798 if (res->t == DUK_IVAL_PLAIN && res->x1.t == DUK_ISPEC_VALUE) {
72799 /* Very minimal inlining to handle common idioms '!0' and '!1',
72800 * and also boolean arguments like '!false' and '!true'.
72801 */
72802 duk_tval *tv_val;
72803
72804 tv_val = DUK_GET_TVAL_POSIDX(thr, res->x1.valstack_idx);
72805 DUK_ASSERT(tv_val != NULL);
72806 if (DUK_TVAL_IS_NUMBER(tv_val)) {
72807 duk_double_t d;
72808 d = DUK_TVAL_GET_NUMBER(tv_val);
72809 if (duk_double_equals(d, 0.0)) {
72810 /* Matches both +0 and -0 on purpose. */
72811 DUK_DDD(DUK_DDDPRINT("inlined lnot: !0 -> true"));
72813 return;
72814 } else if (duk_double_equals(d, 1.0)) {
72815 DUK_DDD(DUK_DDDPRINT("inlined lnot: !1 -> false"));
72817 return;
72818 }
72819 } else if (DUK_TVAL_IS_BOOLEAN(tv_val)) {
72821 v = DUK_TVAL_GET_BOOLEAN(tv_val);
72822 DUK_DDD(DUK_DDDPRINT("inlined lnot boolean: %ld", (long) v));
72823 DUK_ASSERT(v == 0 || v == 1);
72824 DUK_TVAL_SET_BOOLEAN(tv_val, v ^ 0x01);
72825 return;
72826 }
72827 }
72828 args = DUK_OP_LNOT;
72829 goto unary;
72830 }
72831
72832 } /* end switch */
72833
72835 DUK_WO_NORETURN(return;);
72836
72837unary : {
72838 /* Unary opcodes use just the 'BC' register source because it
72839 * matches current shuffle limits, and maps cleanly to 16 high
72840 * bits of the opcode.
72841 */
72842
72843 duk_regconst_t reg_src, reg_res;
72844
72845 reg_src = duk__ivalue_toregconst_raw(comp_ctx, res, -1 /*forced_reg*/, 0 /*flags*/);
72846 if (DUK__ISREG_TEMP(comp_ctx, reg_src)) {
72847 reg_res = reg_src;
72848 } else {
72849 reg_res = DUK__ALLOCTEMP(comp_ctx);
72850 }
72851 duk__emit_a_bc(comp_ctx, args, reg_res, reg_src);
72852 duk__ivalue_regconst(res, reg_res);
72853 return;
72854}
72855
72856preincdec : {
72857 /* preincrement and predecrement */
72858 duk_regconst_t reg_res;
72859 duk_small_uint_t args_op1 = args & 0xff; /* DUK_OP_PREINCR/DUK_OP_PREDECR */
72860 duk_small_uint_t args_op2 = args >> 8; /* DUK_OP_PREINCP_RR/DUK_OP_PREDECP_RR */
72861
72862 /* Specific assumptions for opcode numbering. */
72865
72866 reg_res = DUK__ALLOCTEMP(comp_ctx);
72867
72868 duk__expr(comp_ctx, res, DUK__BP_MULTIPLICATIVE /*rbp_flags*/); /* UnaryExpression */
72869 if (res->t == DUK_IVAL_VAR) {
72870 duk_hstring *h_varname;
72871 duk_regconst_t reg_varbind;
72872 duk_regconst_t rc_varname;
72873
72874 h_varname = duk_known_hstring(thr, res->x1.valstack_idx);
72875
72876 if (duk__hstring_is_eval_or_arguments_in_strict_mode(comp_ctx, h_varname)) {
72877 goto syntax_error;
72878 }
72879
72880 duk_dup(thr, res->x1.valstack_idx);
72881 if (duk__lookup_lhs(comp_ctx, &reg_varbind, &rc_varname)) {
72882 duk__emit_a_bc(comp_ctx,
72883 args_op1, /* e.g. DUK_OP_PREINCR */
72884 reg_res,
72885 reg_varbind);
72886 } else {
72887 duk__emit_a_bc(comp_ctx,
72888 args_op1 + 4, /* e.g. DUK_OP_PREINCV */
72889 reg_res,
72890 rc_varname);
72891 }
72892
72893 DUK_DDD(DUK_DDDPRINT("preincdec to '%!O' -> reg_varbind=%ld, rc_varname=%ld",
72894 (duk_heaphdr *) h_varname,
72895 (long) reg_varbind,
72896 (long) rc_varname));
72897 } else if (res->t == DUK_IVAL_PROP) {
72898 duk_regconst_t reg_obj; /* allocate to reg only (not const) */
72899 duk_regconst_t rc_key;
72900 reg_obj = duk__ispec_toregconst_raw(comp_ctx, &res->x1, -1 /*forced_reg*/, 0 /*flags*/); /* don't allow const */
72901 rc_key = duk__ispec_toregconst_raw(comp_ctx, &res->x2, -1 /*forced_reg*/, DUK__IVAL_FLAG_ALLOW_CONST /*flags*/);
72902 duk__emit_a_b_c(comp_ctx,
72903 args_op2 | DUK__EMIT_FLAG_BC_REGCONST, /* e.g. DUK_OP_PREINCP */
72904 reg_res,
72905 reg_obj,
72906 rc_key);
72907 } else {
72908 /* Technically return value is not needed because INVLHS will
72909 * unconditially throw a ReferenceError. Coercion is necessary
72910 * for proper semantics (consider ToNumber() called for an object).
72911 * Use DUK_OP_UNP with a dummy register to get ToNumber().
72912 */
72913
72914 duk__ivalue_toforcedreg(comp_ctx, res, reg_res);
72915 duk__emit_bc(comp_ctx, DUK_OP_UNP, reg_res); /* for side effects, result ignored */
72917 }
72918 DUK__SETTEMP(comp_ctx, reg_res + 1);
72919 duk__ivalue_regconst(res, reg_res);
72920 return;
72921}
72922
72923plain_value : {
72924 /* Stack top contains plain value */
72925 duk__ivalue_plain_fromstack(comp_ctx, res);
72926 return;
72927}
72928
72929#if defined(DUK_USE_ES6)
72930syntax_error_newtarget:
72932 DUK_WO_NORETURN(return;);
72933#endif
72934
72935syntax_error:
72937 DUK_WO_NORETURN(return;);
72938}
72939
72940/* XXX: add flag to indicate whether caller cares about return value; this
72941 * affects e.g. handling of assignment expressions. This change needs API
72942 * changes elsewhere too.
72943 */
72944DUK_LOCAL void duk__expr_led(duk_compiler_ctx *comp_ctx, duk_ivalue *left, duk_ivalue *res) {
72945 duk_hthread *thr = comp_ctx->thr;
72946 duk_token *tk;
72947 duk_small_uint_t tok;
72948 duk_uint32_t args; /* temp variable to pass constants and flags to shared code */
72949
72950 /*
72951 * ctx->prev_token token to process with duk__expr_led()
72952 * ctx->curr_token updated by caller
72953 */
72954
72955 comp_ctx->curr_func.led_count++;
72956
72957 /* The token in the switch has already been eaten here */
72958 tk = &comp_ctx->prev_token;
72959 tok = tk->t;
72960
72961 DUK_DDD(DUK_DDDPRINT("duk__expr_led(), prev_token.t=%ld, allow_in=%ld, paren_level=%ld",
72962 (long) tk->t,
72963 (long) comp_ctx->curr_func.allow_in,
72964 (long) comp_ctx->curr_func.paren_level));
72965
72966 /* XXX: default priority for infix operators is duk__expr_lbp(tok) -> get it here? */
72967
72968 switch (tok) {
72969 /* PRIMARY EXPRESSIONS */
72970
72971 case DUK_TOK_PERIOD: {
72972 /* Property access expressions are critical for correct LHS ordering,
72973 * see comments in duk__expr()!
72974 *
72975 * A conservative approach would be to use duk__ivalue_totempconst()
72976 * for 'left'. However, allowing a reg-bound variable seems safe here
72977 * and is nice because "foo.bar" is a common expression. If the ivalue
72978 * is used in an expression a GETPROP will occur before any changes to
72979 * the base value can occur. If the ivalue is used as an assignment
72980 * LHS, the assignment code will ensure the base value is safe from
72981 * RHS mutation.
72982 */
72983
72984 /* XXX: This now coerces an identifier into a GETVAR to a temp, which
72985 * causes an extra LDREG in call setup. It's sufficient to coerce to a
72986 * unary ivalue?
72987 */
72988 duk__ivalue_toplain(comp_ctx, left);
72989
72990 /* NB: must accept reserved words as property name */
72991 if (comp_ctx->curr_token.t_nores != DUK_TOK_IDENTIFIER) {
72993 DUK_WO_NORETURN(return;);
72994 }
72995
72996 res->t = DUK_IVAL_PROP;
72997 duk__copy_ispec(comp_ctx, &left->x1, &res->x1); /* left.x1 -> res.x1 */
72998 DUK_ASSERT(comp_ctx->curr_token.str1 != NULL);
72999 duk_push_hstring(thr, comp_ctx->curr_token.str1);
73000 duk_replace(thr, res->x2.valstack_idx);
73001 res->x2.t = DUK_ISPEC_VALUE;
73002
73003 /* special RegExp literal handling after IdentifierName */
73004 comp_ctx->curr_func.reject_regexp_in_adv = 1;
73005
73006 duk__advance(comp_ctx);
73007 return;
73008 }
73009 case DUK_TOK_LBRACKET: {
73010 /* Property access expressions are critical for correct LHS ordering,
73011 * see comments in duk__expr()!
73012 */
73013
73014 /* XXX: optimize temp reg use */
73015 /* XXX: similar coercion issue as in DUK_TOK_PERIOD */
73016 /* XXX: coerce to regs? it might be better for enumeration use, where the
73017 * same PROP ivalue is used multiple times. Or perhaps coerce PROP further
73018 * there?
73019 */
73020 /* XXX: for simple cases like x['y'] an unnecessary LDREG is
73021 * emitted for the base value; could avoid it if we knew that
73022 * the key expression is safe (e.g. just a single literal).
73023 */
73024
73025 /* The 'left' value must not be a register bound variable
73026 * because it may be mutated during the rest of the expression
73027 * and E5.1 Section 11.2.1 specifies the order of evaluation
73028 * so that the base value is evaluated first.
73029 * See: test-bug-nested-prop-mutate.js.
73030 */
73031 duk__ivalue_totempconst(comp_ctx, left);
73032 duk__expr_toplain(comp_ctx, res, DUK__BP_FOR_EXPR /*rbp_flags*/); /* Expression, ']' terminates */
73034
73035 res->t = DUK_IVAL_PROP;
73036 duk__copy_ispec(comp_ctx, &res->x1, &res->x2); /* res.x1 -> res.x2 */
73037 duk__copy_ispec(comp_ctx, &left->x1, &res->x1); /* left.x1 -> res.x1 */
73038 return;
73039 }
73040 case DUK_TOK_LPAREN: {
73041 /* function call */
73042 duk_regconst_t reg_cs = DUK__ALLOCTEMPS(comp_ctx, 2);
73043 duk_int_t nargs;
73045
73046 /* XXX: attempt to get the call result to "next temp" whenever
73047 * possible to avoid unnecessary register shuffles.
73048 */
73049
73050 /*
73051 * Setup call: target and 'this' binding. Three cases:
73052 *
73053 * 1. Identifier base (e.g. "foo()")
73054 * 2. Property base (e.g. "foo.bar()")
73055 * 3. Register base (e.g. "foo()()"; i.e. when a return value is a function)
73056 */
73057
73058 if (left->t == DUK_IVAL_VAR) {
73059 duk_hstring *h_varname;
73060 duk_regconst_t reg_varbind;
73061 duk_regconst_t rc_varname;
73062
73063 DUK_DDD(DUK_DDDPRINT("function call with identifier base"));
73064
73065 h_varname = duk_known_hstring(thr, left->x1.valstack_idx);
73066 if (h_varname == DUK_HTHREAD_STRING_EVAL(thr)) {
73067 /* Potential direct eval call detected, flag the CALL
73068 * so that a run-time "direct eval" check is made and
73069 * special behavior may be triggered. Note that this
73070 * does not prevent 'eval' from being register bound.
73071 */
73072 DUK_DDD(DUK_DDDPRINT("function call with identifier 'eval' "
73073 "-> using EVALCALL, marking function "
73074 "as may_direct_eval"));
73076 comp_ctx->curr_func.may_direct_eval = 1;
73077 }
73078
73079 duk_dup(thr, left->x1.valstack_idx);
73080 if (duk__lookup_lhs(comp_ctx, &reg_varbind, &rc_varname)) {
73081 duk__emit_a_bc(comp_ctx, DUK_OP_CSREG | DUK__EMIT_FLAG_A_IS_SOURCE, reg_varbind, reg_cs + 0);
73082 } else {
73083 /* XXX: expand target register or constant field to
73084 * reduce shuffling.
73085 */
73086 DUK_ASSERT(DUK__ISCONST(rc_varname));
73087 duk__emit_a_b(comp_ctx, DUK_OP_CSVAR | DUK__EMIT_FLAG_BC_REGCONST, reg_cs + 0, rc_varname);
73088 }
73089 } else if (left->t == DUK_IVAL_PROP) {
73090 /* Call through a property lookup, E5 Section 11.2.3, step 6.a.i,
73091 * E5 Section 10.4.3. There used to be a separate CSPROP opcode
73092 * but a typical call setup took 3 opcodes (e.g. LDREG, LDCONST,
73093 * CSPROP) and the same can be achieved with ordinary loads.
73094 */
73095#if defined(DUK_USE_VERBOSE_ERRORS)
73096 duk_regconst_t reg_key;
73097#endif
73098
73099 DUK_DDD(DUK_DDDPRINT("function call with property base"));
73100
73101 /* XXX: For Math.sin() this generates: LDCONST + LDREG +
73102 * GETPROPC + call. The LDREG is unnecessary because LDCONST
73103 * could be loaded directly into reg_cs + 1. This doesn't
73104 * happen now because a variable cannot be in left->x1 of a
73105 * DUK_IVAL_PROP. We could notice that left->x1 is a temp
73106 * and reuse, but it would still be in the wrong position
73107 * (reg_cs + 0 rather than reg_cs + 1).
73108 */
73109 duk__ispec_toforcedreg(comp_ctx, &left->x1, reg_cs + 1); /* base */
73110#if defined(DUK_USE_VERBOSE_ERRORS)
73111 reg_key = duk__ispec_toregconst_raw(comp_ctx, &left->x2, -1, DUK__IVAL_FLAG_ALLOW_CONST /*flags*/);
73112 duk__emit_a_b_c(comp_ctx, DUK_OP_GETPROPC | DUK__EMIT_FLAG_BC_REGCONST, reg_cs + 0, reg_cs + 1, reg_key);
73113#else
73114 duk__ivalue_toforcedreg(comp_ctx, left, reg_cs + 0); /* base[key] */
73115#endif
73116 } else {
73117 DUK_DDD(DUK_DDDPRINT("function call with register base"));
73118
73119 duk__ivalue_toforcedreg(comp_ctx, left, reg_cs + 0);
73120#if 0
73121 duk__emit_a_bc(comp_ctx,
73123 reg_cs + 0,
73124 reg_cs + 0); /* in-place setup */
73125#endif
73126 /* Because of in-place setup, REGCS is equivalent to
73127 * just this LDUNDEF.
73128 */
73129 duk__emit_bc(comp_ctx, DUK_OP_LDUNDEF, reg_cs + 1);
73130 }
73131
73132 DUK__SETTEMP(comp_ctx, reg_cs + 2);
73133 nargs = duk__parse_arguments(comp_ctx, res); /* parse args starting from "next temp" */
73134
73135 /* Tailcalls are handled by back-patching the already emitted opcode
73136 * later in return statement parser.
73137 */
73138
73139 duk__emit_a_bc(comp_ctx, call_op, (duk_regconst_t) nargs /*numargs*/, reg_cs /*basereg*/);
73140 DUK__SETTEMP(comp_ctx, reg_cs + 1); /* result in csreg */
73141
73142 duk__ivalue_regconst(res, reg_cs);
73143 return;
73144 }
73145
73146 /* POSTFIX EXPRESSION */
73147
73148 case DUK_TOK_INCREMENT: {
73149 args = (DUK_OP_POSTINCP_RR << 16) + (DUK_OP_POSTINCR << 8) + 0;
73150 goto postincdec;
73151 }
73152 case DUK_TOK_DECREMENT: {
73153 args = (DUK_OP_POSTDECP_RR << 16) + (DUK_OP_POSTDECR << 8) + 0;
73154 goto postincdec;
73155 }
73156
73157 /* EXPONENTIATION EXPRESSION */
73158
73159#if defined(DUK_USE_ES7_EXP_OPERATOR)
73160 case DUK_TOK_EXP: {
73161 args = (DUK_OP_EXP << 8) + DUK__BP_EXPONENTIATION - 1; /* UnaryExpression */
73162 goto binary;
73163 }
73164#endif
73165
73166 /* MULTIPLICATIVE EXPRESSION */
73167
73168 case DUK_TOK_MUL: {
73169 args = (DUK_OP_MUL << 8) + DUK__BP_MULTIPLICATIVE; /* ExponentiationExpression */
73170 goto binary;
73171 }
73172 case DUK_TOK_DIV: {
73173 args = (DUK_OP_DIV << 8) + DUK__BP_MULTIPLICATIVE; /* ExponentiationExpression */
73174 goto binary;
73175 }
73176 case DUK_TOK_MOD: {
73177 args = (DUK_OP_MOD << 8) + DUK__BP_MULTIPLICATIVE; /* ExponentiationExpression */
73178 goto binary;
73179 }
73180
73181 /* ADDITIVE EXPRESSION */
73182
73183 case DUK_TOK_ADD: {
73184 args = (DUK_OP_ADD << 8) + DUK__BP_ADDITIVE; /* MultiplicativeExpression */
73185 goto binary;
73186 }
73187 case DUK_TOK_SUB: {
73188 args = (DUK_OP_SUB << 8) + DUK__BP_ADDITIVE; /* MultiplicativeExpression */
73189 goto binary;
73190 }
73191
73192 /* SHIFT EXPRESSION */
73193
73194 case DUK_TOK_ALSHIFT: {
73195 /* << */
73196 args = (DUK_OP_BASL << 8) + DUK__BP_SHIFT;
73197 goto binary;
73198 }
73199 case DUK_TOK_ARSHIFT: {
73200 /* >> */
73201 args = (DUK_OP_BASR << 8) + DUK__BP_SHIFT;
73202 goto binary;
73203 }
73204 case DUK_TOK_RSHIFT: {
73205 /* >>> */
73206 args = (DUK_OP_BLSR << 8) + DUK__BP_SHIFT;
73207 goto binary;
73208 }
73209
73210 /* RELATIONAL EXPRESSION */
73211
73212 case DUK_TOK_LT: {
73213 /* < */
73214 args = (DUK_OP_LT << 8) + DUK__BP_RELATIONAL;
73215 goto binary;
73216 }
73217 case DUK_TOK_GT: {
73218 args = (DUK_OP_GT << 8) + DUK__BP_RELATIONAL;
73219 goto binary;
73220 }
73221 case DUK_TOK_LE: {
73222 args = (DUK_OP_LE << 8) + DUK__BP_RELATIONAL;
73223 goto binary;
73224 }
73225 case DUK_TOK_GE: {
73226 args = (DUK_OP_GE << 8) + DUK__BP_RELATIONAL;
73227 goto binary;
73228 }
73229 case DUK_TOK_INSTANCEOF: {
73230 args = (DUK_OP_INSTOF << 8) + DUK__BP_RELATIONAL;
73231 goto binary;
73232 }
73233 case DUK_TOK_IN: {
73234 args = (DUK_OP_IN << 8) + DUK__BP_RELATIONAL;
73235 goto binary;
73236 }
73237
73238 /* EQUALITY EXPRESSION */
73239
73240 case DUK_TOK_EQ: {
73241 args = (DUK_OP_EQ << 8) + DUK__BP_EQUALITY;
73242 goto binary;
73243 }
73244 case DUK_TOK_NEQ: {
73245 args = (DUK_OP_NEQ << 8) + DUK__BP_EQUALITY;
73246 goto binary;
73247 }
73248 case DUK_TOK_SEQ: {
73249 args = (DUK_OP_SEQ << 8) + DUK__BP_EQUALITY;
73250 goto binary;
73251 }
73252 case DUK_TOK_SNEQ: {
73253 args = (DUK_OP_SNEQ << 8) + DUK__BP_EQUALITY;
73254 goto binary;
73255 }
73256
73257 /* BITWISE EXPRESSIONS */
73258
73259 case DUK_TOK_BAND: {
73260 args = (DUK_OP_BAND << 8) + DUK__BP_BAND;
73261 goto binary;
73262 }
73263 case DUK_TOK_BXOR: {
73264 args = (DUK_OP_BXOR << 8) + DUK__BP_BXOR;
73265 goto binary;
73266 }
73267 case DUK_TOK_BOR: {
73268 args = (DUK_OP_BOR << 8) + DUK__BP_BOR;
73269 goto binary;
73270 }
73271
73272 /* LOGICAL EXPRESSIONS */
73273
73274 case DUK_TOK_LAND: {
73275 /* syntactically left-associative but parsed as right-associative */
73276 args = (1 << 8) + DUK__BP_LAND - 1;
73277 goto binary_logical;
73278 }
73279 case DUK_TOK_LOR: {
73280 /* syntactically left-associative but parsed as right-associative */
73281 args = (0 << 8) + DUK__BP_LOR - 1;
73282 goto binary_logical;
73283 }
73284
73285 /* CONDITIONAL EXPRESSION */
73286
73287 case DUK_TOK_QUESTION: {
73288 /* XXX: common reg allocation need is to reuse a sub-expression's temp reg,
73289 * but only if it really is a temp. Nothing fancy here now.
73290 */
73291 duk_regconst_t reg_temp;
73292 duk_int_t pc_jump1;
73293 duk_int_t pc_jump2;
73294
73295 reg_temp = DUK__ALLOCTEMP(comp_ctx);
73296 duk__ivalue_toforcedreg(comp_ctx, left, reg_temp);
73297 duk__emit_if_true_skip(comp_ctx, reg_temp);
73298 pc_jump1 = duk__emit_jump_empty(comp_ctx); /* jump to false */
73299 duk__expr_toforcedreg(comp_ctx,
73300 res,
73301 DUK__BP_COMMA /*rbp_flags*/,
73302 reg_temp /*forced_reg*/); /* AssignmentExpression */
73304 pc_jump2 = duk__emit_jump_empty(comp_ctx); /* jump to end */
73305 duk__patch_jump_here(comp_ctx, pc_jump1);
73306 duk__expr_toforcedreg(comp_ctx,
73307 res,
73308 DUK__BP_COMMA /*rbp_flags*/,
73309 reg_temp /*forced_reg*/); /* AssignmentExpression */
73310 duk__patch_jump_here(comp_ctx, pc_jump2);
73311
73312 DUK__SETTEMP(comp_ctx, reg_temp + 1);
73313 duk__ivalue_regconst(res, reg_temp);
73314 return;
73315 }
73316
73317 /* ASSIGNMENT EXPRESSION */
73318
73319 case DUK_TOK_EQUALSIGN: {
73320 /*
73321 * Assignments are right associative, allows e.g.
73322 * a = 5;
73323 * a += b = 9; // same as a += (b = 9)
73324 * -> expression value 14, a = 14, b = 9
73325 *
73326 * Right associativiness is reflected in the BP for recursion,
73327 * "-1" ensures assignment operations are allowed.
73328 *
73329 * XXX: just use DUK__BP_COMMA (i.e. no need for 2-step bp levels)?
73330 */
73331 args = (DUK_OP_NONE << 8) + DUK__BP_ASSIGNMENT - 1; /* DUK_OP_NONE marks a 'plain' assignment */
73332 goto assign;
73333 }
73334 case DUK_TOK_ADD_EQ: {
73335 /* right associative */
73336 args = (DUK_OP_ADD << 8) + DUK__BP_ASSIGNMENT - 1;
73337 goto assign;
73338 }
73339 case DUK_TOK_SUB_EQ: {
73340 /* right associative */
73341 args = (DUK_OP_SUB << 8) + DUK__BP_ASSIGNMENT - 1;
73342 goto assign;
73343 }
73344 case DUK_TOK_MUL_EQ: {
73345 /* right associative */
73346 args = (DUK_OP_MUL << 8) + DUK__BP_ASSIGNMENT - 1;
73347 goto assign;
73348 }
73349 case DUK_TOK_DIV_EQ: {
73350 /* right associative */
73351 args = (DUK_OP_DIV << 8) + DUK__BP_ASSIGNMENT - 1;
73352 goto assign;
73353 }
73354 case DUK_TOK_MOD_EQ: {
73355 /* right associative */
73356 args = (DUK_OP_MOD << 8) + DUK__BP_ASSIGNMENT - 1;
73357 goto assign;
73358 }
73359#if defined(DUK_USE_ES7_EXP_OPERATOR)
73360 case DUK_TOK_EXP_EQ: {
73361 /* right associative */
73362 args = (DUK_OP_EXP << 8) + DUK__BP_ASSIGNMENT - 1;
73363 goto assign;
73364 }
73365#endif
73366 case DUK_TOK_ALSHIFT_EQ: {
73367 /* right associative */
73368 args = (DUK_OP_BASL << 8) + DUK__BP_ASSIGNMENT - 1;
73369 goto assign;
73370 }
73371 case DUK_TOK_ARSHIFT_EQ: {
73372 /* right associative */
73373 args = (DUK_OP_BASR << 8) + DUK__BP_ASSIGNMENT - 1;
73374 goto assign;
73375 }
73376 case DUK_TOK_RSHIFT_EQ: {
73377 /* right associative */
73378 args = (DUK_OP_BLSR << 8) + DUK__BP_ASSIGNMENT - 1;
73379 goto assign;
73380 }
73381 case DUK_TOK_BAND_EQ: {
73382 /* right associative */
73383 args = (DUK_OP_BAND << 8) + DUK__BP_ASSIGNMENT - 1;
73384 goto assign;
73385 }
73386 case DUK_TOK_BOR_EQ: {
73387 /* right associative */
73388 args = (DUK_OP_BOR << 8) + DUK__BP_ASSIGNMENT - 1;
73389 goto assign;
73390 }
73391 case DUK_TOK_BXOR_EQ: {
73392 /* right associative */
73393 args = (DUK_OP_BXOR << 8) + DUK__BP_ASSIGNMENT - 1;
73394 goto assign;
73395 }
73396
73397 /* COMMA */
73398
73399 case DUK_TOK_COMMA: {
73400 /* right associative */
73401
73402 duk__ivalue_toplain_ignore(comp_ctx, left); /* need side effects, not value */
73403 duk__expr_toplain(comp_ctx, res, DUK__BP_COMMA - 1 /*rbp_flags*/);
73404
73405 /* return 'res' (of right part) as our result */
73406 return;
73407 }
73408
73409 default: {
73410 break;
73411 }
73412 }
73413
73414 DUK_D(DUK_DPRINT("parse error: unexpected token: %ld", (long) tok));
73416 DUK_WO_NORETURN(return;);
73417
73418#if 0
73419 /* XXX: shared handling for 'duk__expr_lhs'? */
73420 if (comp_ctx->curr_func.paren_level == 0 && XXX) {
73421 comp_ctx->curr_func.duk__expr_lhs = 0;
73422 }
73423#endif
73424
73425binary:
73426 /*
73427 * Shared handling of binary operations
73428 *
73429 * args = (opcode << 8) + rbp
73430 */
73431 {
73432 duk__ivalue_toplain(comp_ctx, left);
73433 duk__expr_toplain(comp_ctx, res, args & 0xff /*rbp_flags*/);
73434
73435 /* combine left->x1 and res->x1 (right->x1, really) -> (left->x1 OP res->x1) */
73436 DUK_ASSERT(left->t == DUK_IVAL_PLAIN);
73437 DUK_ASSERT(res->t == DUK_IVAL_PLAIN);
73438
73439 res->t = DUK_IVAL_ARITH;
73440 res->op = (args >> 8) & 0xff;
73441
73442 res->x2.t = res->x1.t;
73443 res->x2.regconst = res->x1.regconst;
73444 duk_copy(thr, res->x1.valstack_idx, res->x2.valstack_idx);
73445
73446 res->x1.t = left->x1.t;
73447 res->x1.regconst = left->x1.regconst;
73448 duk_copy(thr, left->x1.valstack_idx, res->x1.valstack_idx);
73449
73450 DUK_DDD(DUK_DDDPRINT("binary op, res: t=%ld, x1.t=%ld, x1.regconst=0x%08lx, x2.t=%ld, x2.regconst=0x%08lx",
73451 (long) res->t,
73452 (long) res->x1.t,
73453 (unsigned long) res->x1.regconst,
73454 (long) res->x2.t,
73455 (unsigned long) res->x2.regconst));
73456 return;
73457 }
73458
73459binary_logical:
73460 /*
73461 * Shared handling for logical AND and logical OR.
73462 *
73463 * args = (truthval << 8) + rbp
73464 *
73465 * Truthval determines when to skip right-hand-side.
73466 * For logical AND truthval=1, for logical OR truthval=0.
73467 *
73468 * See doc/compiler.rst for discussion on compiling logical
73469 * AND and OR expressions. The approach here is very simplistic,
73470 * generating extra jumps and multiple evaluations of truth values,
73471 * but generates code on-the-fly with only local back-patching.
73472 *
73473 * Both logical AND and OR are syntactically left-associated.
73474 * However, logical ANDs are compiled as right associative
73475 * expressions, i.e. "A && B && C" as "A && (B && C)", to allow
73476 * skip jumps to skip over the entire tail. Similarly for logical OR.
73477 */
73478
73479 {
73480 duk_regconst_t reg_temp;
73481 duk_int_t pc_jump;
73482 duk_small_uint_t args_truthval = args >> 8;
73483 duk_small_uint_t args_rbp = args & 0xff;
73484
73485 /* XXX: unoptimal use of temps, resetting */
73486
73487 reg_temp = DUK__ALLOCTEMP(comp_ctx);
73488
73489 duk__ivalue_toforcedreg(comp_ctx, left, reg_temp);
73490 DUK_ASSERT(DUK__ISREG(reg_temp));
73491 duk__emit_bc(comp_ctx,
73492 (args_truthval ? DUK_OP_IFTRUE_R : DUK_OP_IFFALSE_R),
73493 reg_temp); /* skip jump conditionally */
73494 pc_jump = duk__emit_jump_empty(comp_ctx);
73495 duk__expr_toforcedreg(comp_ctx, res, args_rbp /*rbp_flags*/, reg_temp /*forced_reg*/);
73496 duk__patch_jump_here(comp_ctx, pc_jump);
73497
73498 duk__ivalue_regconst(res, reg_temp);
73499 return;
73500 }
73501
73502assign:
73503 /*
73504 * Shared assignment expression handling
73505 *
73506 * args = (opcode << 8) + rbp
73507 *
73508 * If 'opcode' is DUK_OP_NONE, plain assignment without arithmetic.
73509 * Syntactically valid left-hand-side forms which are not accepted as
73510 * left-hand-side values (e.g. as in "f() = 1") must NOT cause a
73511 * SyntaxError, but rather a run-time ReferenceError.
73512 *
73513 * When evaluating X <op>= Y, the LHS (X) is conceptually evaluated
73514 * to a temporary first. The RHS is then evaluated. Finally, the
73515 * <op> is applied to the initial value of RHS (not the value after
73516 * RHS evaluation), and written to X. Doing so concretely generates
73517 * inefficient code so we'd like to avoid the temporary when possible.
73518 * See: https://github.com/svaarala/duktape/pull/992.
73519 *
73520 * The expression value (final LHS value, written to RHS) is
73521 * conceptually copied into a fresh temporary so that it won't
73522 * change even if the LHS/RHS values change in outer expressions.
73523 * For example, it'd be generally incorrect for the expression value
73524 * to be the RHS register binding, unless there's a guarantee that it
73525 * won't change during further expression evaluation. Using the
73526 * temporary concretely produces inefficient bytecode, so we try to
73527 * avoid the extra temporary for some known-to-be-safe cases.
73528 * Currently the only safe case we detect is a "top level assignment",
73529 * for example "x = y + z;", where the assignment expression value is
73530 * ignored.
73531 * See: test-dev-assign-expr.js and test-bug-assign-mutate-gh381.js.
73532 */
73533
73534 {
73535 duk_small_uint_t args_op = args >> 8;
73536 duk_small_uint_t args_rbp = args & 0xff;
73537 duk_bool_t toplevel_assign;
73538
73539 /* XXX: here we need to know if 'left' is left-hand-side compatible.
73540 * That information is no longer available from current expr parsing
73541 * state; it would need to be carried into the 'left' ivalue or by
73542 * some other means.
73543 */
73544
73545 /* A top-level assignment is e.g. "x = y;". For these it's safe
73546 * to use the RHS as-is as the expression value, even if the RHS
73547 * is a reg-bound identifier. The RHS ('res') is right associative
73548 * so it has consumed all other assignment level operations; the
73549 * only relevant lower binding power construct is comma operator
73550 * which will ignore the expression value provided here. Usually
73551 * the top level assignment expression value is ignored, but it
73552 * is relevant for e.g. eval code.
73553 */
73554 toplevel_assign = (comp_ctx->curr_func.nud_count == 1 && /* one token before */
73555 comp_ctx->curr_func.led_count == 1); /* one operator (= assign) */
73556 DUK_DDD(DUK_DDDPRINT("assignment: nud_count=%ld, led_count=%ld, toplevel_assign=%ld",
73557 (long) comp_ctx->curr_func.nud_count,
73558 (long) comp_ctx->curr_func.led_count,
73559 (long) toplevel_assign));
73560
73561 if (left->t == DUK_IVAL_VAR) {
73562 duk_hstring *h_varname;
73563 duk_regconst_t reg_varbind;
73564 duk_regconst_t rc_varname;
73565
73566 DUK_ASSERT(left->x1.t == DUK_ISPEC_VALUE); /* LHS is already side effect free */
73567
73568 h_varname = duk_known_hstring(thr, left->x1.valstack_idx);
73569 if (duk__hstring_is_eval_or_arguments_in_strict_mode(comp_ctx, h_varname)) {
73570 /* E5 Section 11.13.1 (and others for other assignments), step 4. */
73571 goto syntax_error_lvalue;
73572 }
73573 duk_dup(thr, left->x1.valstack_idx);
73574 (void) duk__lookup_lhs(comp_ctx, &reg_varbind, &rc_varname);
73575
73576 if (args_op == DUK_OP_NONE) {
73577 duk__expr(comp_ctx, res, args_rbp /*rbp_flags*/);
73578 if (toplevel_assign) {
73579 /* Any 'res' will do. */
73580 DUK_DDD(DUK_DDDPRINT("plain assignment, toplevel assign, use as is"));
73581 } else {
73582 /* 'res' must be a plain ivalue, and not register-bound variable. */
73584 "plain assignment, not toplevel assign, ensure not a reg-bound identifier"));
73585 if (res->t != DUK_IVAL_PLAIN ||
73586 (res->x1.t == DUK_ISPEC_REGCONST && DUK__ISREG_NOTTEMP(comp_ctx, res->x1.regconst))) {
73587 duk__ivalue_totempconst(comp_ctx, res);
73588 }
73589 }
73590 } else {
73591 /* For X <op>= Y we need to evaluate the pre-op
73592 * value of X before evaluating the RHS: the RHS
73593 * can change X, but when we do <op> we must use
73594 * the pre-op value.
73595 */
73596 duk_regconst_t reg_temp;
73597
73598 reg_temp = DUK__ALLOCTEMP(comp_ctx);
73599
73600 if (reg_varbind >= 0) {
73601 duk_regconst_t reg_res;
73602 duk_regconst_t reg_src;
73603 duk_int_t pc_temp_load;
73604 duk_int_t pc_before_rhs;
73605 duk_int_t pc_after_rhs;
73606
73607 if (toplevel_assign) {
73608 /* 'reg_varbind' is the operation result and can also
73609 * become the expression value for top level assignments
73610 * such as: "var x; x += y;".
73611 */
73612 DUK_DD(DUK_DDPRINT("<op>= expression is top level, write directly to reg_varbind"));
73613 reg_res = reg_varbind;
73614 } else {
73615 /* Not safe to use 'reg_varbind' as assignment expression
73616 * value, so go through a temp.
73617 */
73618 DUK_DD(DUK_DDPRINT("<op>= expression is not top level, write to reg_temp"));
73619 reg_res = reg_temp; /* reg_res should be smallest possible */
73620 reg_temp = DUK__ALLOCTEMP(comp_ctx);
73621 }
73622
73623 /* Try to optimize X <op>= Y for reg-bound
73624 * variables. Detect side-effect free RHS
73625 * narrowly by seeing whether it emits code.
73626 * If not, rewind the code emitter and overwrite
73627 * the unnecessary temp reg load.
73628 */
73629
73630 pc_temp_load = duk__get_current_pc(comp_ctx);
73631 duk__emit_a_bc(comp_ctx, DUK_OP_LDREG, reg_temp, reg_varbind);
73632
73633 pc_before_rhs = duk__get_current_pc(comp_ctx);
73634 duk__expr_toregconst(comp_ctx, res, args_rbp /*rbp_flags*/);
73635 DUK_ASSERT(res->t == DUK_IVAL_PLAIN && res->x1.t == DUK_ISPEC_REGCONST);
73636 pc_after_rhs = duk__get_current_pc(comp_ctx);
73637
73638 DUK_DD(DUK_DDPRINT("pc_temp_load=%ld, pc_before_rhs=%ld, pc_after_rhs=%ld",
73639 (long) pc_temp_load,
73640 (long) pc_before_rhs,
73641 (long) pc_after_rhs));
73642
73643 if (pc_after_rhs == pc_before_rhs) {
73644 /* Note: if the reg_temp load generated shuffling
73645 * instructions, we may need to rewind more than
73646 * one instruction, so use explicit PC computation.
73647 */
73648 DUK_DD(DUK_DDPRINT("rhs is side effect free, rewind and avoid unnecessary temp for "
73649 "reg-based <op>="));
73650 DUK_BW_ADD_PTR(comp_ctx->thr,
73651 &comp_ctx->curr_func.bw_code,
73652 (pc_temp_load - pc_before_rhs) *
73653 (duk_int_t) sizeof(duk_compiler_instr));
73654 reg_src = reg_varbind;
73655 } else {
73656 DUK_DD(DUK_DDPRINT("rhs evaluation emitted code, not sure if rhs is side effect "
73657 "free; use temp reg for LHS"));
73658 reg_src = reg_temp;
73659 }
73660
73661 duk__emit_a_b_c(comp_ctx,
73663 reg_res,
73664 reg_src,
73665 res->x1.regconst);
73666
73667 res->x1.regconst = reg_res;
73668
73669 /* Ensure compact use of temps. */
73670 if (DUK__ISREG_TEMP(comp_ctx, reg_res)) {
73671 DUK__SETTEMP(comp_ctx, reg_res + 1);
73672 }
73673 } else {
73674 /* When LHS is not register bound, always go through a
73675 * temporary. No optimization for top level assignment.
73676 */
73677
73678 duk__emit_a_bc(comp_ctx, DUK_OP_GETVAR, reg_temp, rc_varname);
73679
73680 duk__expr_toregconst(comp_ctx, res, args_rbp /*rbp_flags*/);
73681 DUK_ASSERT(res->t == DUK_IVAL_PLAIN && res->x1.t == DUK_ISPEC_REGCONST);
73682
73683 duk__emit_a_b_c(comp_ctx,
73685 reg_temp,
73686 reg_temp,
73687 res->x1.regconst);
73688 res->x1.regconst = reg_temp;
73689 }
73690
73691 DUK_ASSERT(res->t == DUK_IVAL_PLAIN && res->x1.t == DUK_ISPEC_REGCONST);
73692 }
73693
73694 /* At this point 'res' holds the potential expression value.
73695 * It can be basically any ivalue here, including a reg-bound
73696 * identifier (if code above deems it safe) or a unary/binary
73697 * operation. Operations must be resolved to a side effect free
73698 * plain value, and the side effects must happen exactly once.
73699 */
73700
73701 if (reg_varbind >= 0) {
73702 if (res->t != DUK_IVAL_PLAIN) {
73703 /* Resolve 'res' directly into the LHS binding, and use
73704 * that as the expression value if safe. If not safe,
73705 * resolve to a temp/const and copy to LHS.
73706 */
73707 if (toplevel_assign) {
73708 duk__ivalue_toforcedreg(comp_ctx, res, (duk_int_t) reg_varbind);
73709 } else {
73710 duk__ivalue_totempconst(comp_ctx, res);
73711 duk__copy_ivalue(comp_ctx, res, left); /* use 'left' as a temp */
73712 duk__ivalue_toforcedreg(comp_ctx, left, (duk_int_t) reg_varbind);
73713 }
73714 } else {
73715 /* Use 'res' as the expression value (it's side effect
73716 * free and may be a plain value, a register, or a
73717 * constant) and write it to the LHS binding too.
73718 */
73719 duk__copy_ivalue(comp_ctx, res, left); /* use 'left' as a temp */
73720 duk__ivalue_toforcedreg(comp_ctx, left, (duk_int_t) reg_varbind);
73721 }
73722 } else {
73723 /* Only a reg fits into 'A' so coerce 'res' into a register
73724 * for PUTVAR.
73725 *
73726 * XXX: here the current A/B/C split is suboptimal: we could
73727 * just use 9 bits for reg_res (and support constants) and 17
73728 * instead of 18 bits for the varname const index.
73729 */
73730
73731 duk__ivalue_toreg(comp_ctx, res);
73732 duk__emit_a_bc(comp_ctx, DUK_OP_PUTVAR | DUK__EMIT_FLAG_A_IS_SOURCE, res->x1.regconst, rc_varname);
73733 }
73734
73735 /* 'res' contains expression value */
73736 } else if (left->t == DUK_IVAL_PROP) {
73737 /* E5 Section 11.13.1 (and others) step 4 never matches for prop writes -> no check */
73738 duk_regconst_t reg_obj;
73739 duk_regconst_t rc_key;
73740 duk_regconst_t rc_res;
73741 duk_regconst_t reg_temp;
73742
73743 /* Property access expressions ('a[b]') are critical to correct
73744 * LHS evaluation ordering, see test-dev-assign-eval-order*.js.
73745 * We must make sure that the LHS target slot (base object and
73746 * key) don't change during RHS evaluation. The only concrete
73747 * problem is a register reference to a variable-bound register
73748 * (i.e., non-temp). Require temp regs for both key and base.
73749 *
73750 * Don't allow a constant for the object (even for a number
73751 * etc), as it goes into the 'A' field of the opcode.
73752 */
73753
73754 reg_obj = duk__ispec_toregconst_raw(comp_ctx,
73755 &left->x1,
73756 -1 /*forced_reg*/,
73757 DUK__IVAL_FLAG_REQUIRE_TEMP /*flags*/);
73758
73759 rc_key = duk__ispec_toregconst_raw(comp_ctx,
73760 &left->x2,
73761 -1 /*forced_reg*/,
73763
73764 /* Evaluate RHS only when LHS is safe. */
73765
73766 if (args_op == DUK_OP_NONE) {
73767 duk__expr_toregconst(comp_ctx, res, args_rbp /*rbp_flags*/);
73768 DUK_ASSERT(res->t == DUK_IVAL_PLAIN && res->x1.t == DUK_ISPEC_REGCONST);
73769 rc_res = res->x1.regconst;
73770 } else {
73771 reg_temp = DUK__ALLOCTEMP(comp_ctx);
73772 duk__emit_a_b_c(comp_ctx, DUK_OP_GETPROP | DUK__EMIT_FLAG_BC_REGCONST, reg_temp, reg_obj, rc_key);
73773
73774 duk__expr_toregconst(comp_ctx, res, args_rbp /*rbp_flags*/);
73775 DUK_ASSERT(res->t == DUK_IVAL_PLAIN && res->x1.t == DUK_ISPEC_REGCONST);
73776
73777 duk__emit_a_b_c(comp_ctx,
73779 reg_temp,
73780 reg_temp,
73781 res->x1.regconst);
73782 rc_res = reg_temp;
73783 }
73784
73785 duk__emit_a_b_c(comp_ctx,
73787 reg_obj,
73788 rc_key,
73789 rc_res);
73790
73791 duk__ivalue_regconst(res, rc_res);
73792 } else {
73793 /* No support for lvalues returned from new or function call expressions.
73794 * However, these must NOT cause compile-time SyntaxErrors, but run-time
73795 * ReferenceErrors. Both left and right sides of the assignment must be
73796 * evaluated before throwing a ReferenceError. For instance:
73797 *
73798 * f() = g();
73799 *
73800 * must result in f() being evaluated, then g() being evaluated, and
73801 * finally, a ReferenceError being thrown. See E5 Section 11.13.1.
73802 */
73803
73804 duk_regconst_t rc_res;
73805
73806 /* First evaluate LHS fully to ensure all side effects are out. */
73807 duk__ivalue_toplain_ignore(comp_ctx, left);
73808
73809 /* Then evaluate RHS fully (its value becomes the expression value too).
73810 * Technically we'd need the side effect safety check here too, but because
73811 * we always throw using INVLHS the result doesn't matter.
73812 */
73813 rc_res = duk__expr_toregconst(comp_ctx, res, args_rbp /*rbp_flags*/);
73814
73816
73817 duk__ivalue_regconst(res, rc_res);
73818 }
73819
73820 return;
73821 }
73822
73823postincdec : {
73824 /*
73825 * Post-increment/decrement will return the original value as its
73826 * result value. However, even that value will be coerced using
73827 * ToNumber() which is quite awkward. Specific bytecode opcodes
73828 * are used to handle these semantics.
73829 *
73830 * Note that post increment/decrement has a "no LineTerminator here"
73831 * restriction. This is handled by duk__expr_lbp(), which forcibly terminates
73832 * the previous expression if a LineTerminator occurs before '++'/'--'.
73833 */
73834
73835 duk_regconst_t reg_res;
73836 duk_small_uint_t args_op1 = (args >> 8) & 0xff; /* DUK_OP_POSTINCR/DUK_OP_POSTDECR */
73837 duk_small_uint_t args_op2 = args >> 16; /* DUK_OP_POSTINCP_RR/DUK_OP_POSTDECP_RR */
73838
73839 /* Specific assumptions for opcode numbering. */
73842
73843 reg_res = DUK__ALLOCTEMP(comp_ctx);
73844
73845 if (left->t == DUK_IVAL_VAR) {
73846 duk_hstring *h_varname;
73847 duk_regconst_t reg_varbind;
73848 duk_regconst_t rc_varname;
73849
73850 h_varname = duk_known_hstring(thr, left->x1.valstack_idx);
73851
73852 if (duk__hstring_is_eval_or_arguments_in_strict_mode(comp_ctx, h_varname)) {
73853 goto syntax_error;
73854 }
73855
73856 duk_dup(thr, left->x1.valstack_idx);
73857 if (duk__lookup_lhs(comp_ctx, &reg_varbind, &rc_varname)) {
73858 duk__emit_a_bc(comp_ctx,
73859 args_op1, /* e.g. DUK_OP_POSTINCR */
73860 reg_res,
73861 reg_varbind);
73862 } else {
73863 duk__emit_a_bc(comp_ctx,
73864 args_op1 + 4, /* e.g. DUK_OP_POSTINCV */
73865 reg_res,
73866 rc_varname);
73867 }
73868
73869 DUK_DDD(DUK_DDDPRINT("postincdec to '%!O' -> reg_varbind=%ld, rc_varname=%ld",
73870 (duk_heaphdr *) h_varname,
73871 (long) reg_varbind,
73872 (long) rc_varname));
73873 } else if (left->t == DUK_IVAL_PROP) {
73874 duk_regconst_t reg_obj; /* allocate to reg only (not const) */
73875 duk_regconst_t rc_key;
73876
73877 reg_obj = duk__ispec_toregconst_raw(comp_ctx, &left->x1, -1 /*forced_reg*/, 0 /*flags*/); /* don't allow const */
73878 rc_key = duk__ispec_toregconst_raw(comp_ctx, &left->x2, -1 /*forced_reg*/, DUK__IVAL_FLAG_ALLOW_CONST /*flags*/);
73879 duk__emit_a_b_c(comp_ctx,
73880 args_op2 | DUK__EMIT_FLAG_BC_REGCONST, /* e.g. DUK_OP_POSTINCP */
73881 reg_res,
73882 reg_obj,
73883 rc_key);
73884 } else {
73885 /* Technically return value is not needed because INVLHS will
73886 * unconditially throw a ReferenceError. Coercion is necessary
73887 * for proper semantics (consider ToNumber() called for an object).
73888 * Use DUK_OP_UNP with a dummy register to get ToNumber().
73889 */
73890 duk__ivalue_toforcedreg(comp_ctx, left, reg_res);
73891 duk__emit_bc(comp_ctx, DUK_OP_UNP, reg_res); /* for side effects, result ignored */
73893 }
73894
73895 DUK__SETTEMP(comp_ctx, reg_res + 1);
73896 duk__ivalue_regconst(res, reg_res);
73897 return;
73898}
73899
73900syntax_error:
73902 DUK_WO_NORETURN(return;);
73903
73904syntax_error_lvalue:
73906 DUK_WO_NORETURN(return;);
73907}
73908
73910 duk_small_uint_t tok = comp_ctx->curr_token.t;
73911
73912 DUK_ASSERT_DISABLE(tok >= DUK_TOK_MINVAL); /* unsigned */
73913 DUK_ASSERT(tok <= DUK_TOK_MAXVAL);
73915
73916 /* XXX: integrate support for this into led() instead?
73917 * Similar issue as post-increment/post-decrement.
73918 */
73919
73920 /* prevent duk__expr_led() by using a binding power less than anything valid */
73921 if (tok == DUK_TOK_IN && !comp_ctx->curr_func.allow_in) {
73922 return 0;
73923 }
73924
73925 if ((tok == DUK_TOK_DECREMENT || tok == DUK_TOK_INCREMENT) && (comp_ctx->curr_token.lineterm)) {
73926 /* '++' or '--' in a post-increment/decrement position,
73927 * and a LineTerminator occurs between the operator and
73928 * the preceding expression. Force the previous expr
73929 * to terminate, in effect treating e.g. "a,b\n++" as
73930 * "a,b;++" (= SyntaxError).
73931 */
73932 return 0;
73933 }
73934
73935 return DUK__TOKEN_LBP_GET_BP(duk__token_lbp[tok]); /* format is bit packed */
73936}
73937
73938/*
73939 * Expression parsing.
73940 *
73941 * Upon entry to 'expr' and its variants, 'curr_tok' is assumed to be the
73942 * first token of the expression. Upon exit, 'curr_tok' will be the first
73943 * token not part of the expression (e.g. semicolon terminating an expression
73944 * statement).
73945 */
73946
73947#define DUK__EXPR_RBP_MASK 0xff
73948#define DUK__EXPR_FLAG_REJECT_IN (1 << 8) /* reject 'in' token (used for for-in) */
73949#define DUK__EXPR_FLAG_ALLOW_EMPTY (1 << 9) /* allow empty expression */
73950#define DUK__EXPR_FLAG_REQUIRE_INIT (1 << 10) /* require initializer for var/const */
73951
73952/* main expression parser function */
73953DUK_LOCAL void duk__expr(duk_compiler_ctx *comp_ctx, duk_ivalue *res, duk_small_uint_t rbp_flags) {
73954 duk_hthread *thr = comp_ctx->thr;
73955 duk_ivalue tmp_alloc; /* 'res' is used for "left", and 'tmp' for "right" */
73956 duk_ivalue *tmp = &tmp_alloc;
73957 duk_small_uint_t rbp;
73958
73959 DUK__RECURSION_INCREASE(comp_ctx, thr);
73960
73962
73963 /* filter out flags from exprtop rbp_flags here to save space */
73964 rbp = rbp_flags & DUK__EXPR_RBP_MASK;
73965
73966 DUK_DDD(DUK_DDDPRINT("duk__expr(), rbp_flags=%ld, rbp=%ld, allow_in=%ld, paren_level=%ld",
73967 (long) rbp_flags,
73968 (long) rbp,
73969 (long) comp_ctx->curr_func.allow_in,
73970 (long) comp_ctx->curr_func.paren_level));
73971
73972 duk_memzero(&tmp_alloc, sizeof(tmp_alloc));
73973 tmp->x1.valstack_idx = duk_get_top(thr);
73974 tmp->x2.valstack_idx = tmp->x1.valstack_idx + 1;
73975 duk_push_undefined(thr);
73976 duk_push_undefined(thr);
73977
73978 /* XXX: where to release temp regs in intermediate expressions?
73979 * e.g. 1+2+3 -> don't inflate temp register count when parsing this.
73980 * that particular expression temp regs can be forced here.
73981 */
73982
73983 /* XXX: increase ctx->expr_tokens here for every consumed token
73984 * (this would be a nice statistic)?
73985 */
73986
73987 if (comp_ctx->curr_token.t == DUK_TOK_SEMICOLON || comp_ctx->curr_token.t == DUK_TOK_RPAREN) {
73988 /* XXX: possibly incorrect handling of empty expression */
73989 DUK_DDD(DUK_DDDPRINT("empty expression"));
73990 if (!(rbp_flags & DUK__EXPR_FLAG_ALLOW_EMPTY)) {
73992 DUK_WO_NORETURN(return;);
73993 }
73995 duk__ivalue_plain_fromstack(comp_ctx, res);
73996 goto cleanup;
73997 }
73998
73999 duk__advance(comp_ctx);
74000 duk__expr_nud(comp_ctx, res); /* reuse 'res' as 'left' */
74001 while (rbp < duk__expr_lbp(comp_ctx)) {
74002 duk__advance(comp_ctx);
74003 duk__expr_led(comp_ctx, res, tmp);
74004 duk__copy_ivalue(comp_ctx, tmp, res); /* tmp -> res */
74005 }
74006
74007cleanup:
74008 /* final result is already in 'res' */
74009
74010 duk_pop_2(thr);
74011
74012 DUK__RECURSION_DECREASE(comp_ctx, thr);
74013}
74014
74015DUK_LOCAL void duk__exprtop(duk_compiler_ctx *comp_ctx, duk_ivalue *res, duk_small_uint_t rbp_flags) {
74016 duk_hthread *thr = comp_ctx->thr;
74017
74018 /* Note: these variables must reside in 'curr_func' instead of the global
74019 * context: when parsing function expressions, expression parsing is nested.
74020 */
74021 comp_ctx->curr_func.nud_count = 0;
74022 comp_ctx->curr_func.led_count = 0;
74023 comp_ctx->curr_func.paren_level = 0;
74024 comp_ctx->curr_func.expr_lhs = 1;
74025 comp_ctx->curr_func.allow_in = (rbp_flags & DUK__EXPR_FLAG_REJECT_IN ? 0 : 1);
74026
74027 duk__expr(comp_ctx, res, rbp_flags);
74028
74029 if (!(rbp_flags & DUK__EXPR_FLAG_ALLOW_EMPTY) && duk__expr_is_empty(comp_ctx)) {
74031 DUK_WO_NORETURN(return;);
74032 }
74033}
74035/* A bunch of helpers (for size optimization) that combine duk__expr()/duk__exprtop()
74036 * and result conversions.
74037 *
74038 * Each helper needs at least 2-3 calls to make it worth while to wrap.
74039 */
74040
74041#if 0 /* unused */
74042DUK_LOCAL duk_regconst_t duk__expr_toreg(duk_compiler_ctx *comp_ctx, duk_ivalue *res, duk_small_uint_t rbp_flags) {
74043 duk__expr(comp_ctx, res, rbp_flags);
74044 return duk__ivalue_toreg(comp_ctx, res);
74045}
74046#endif
74047
74048#if 0 /* unused */
74049DUK_LOCAL duk_regconst_t duk__expr_totemp(duk_compiler_ctx *comp_ctx, duk_ivalue *res, duk_small_uint_t rbp_flags) {
74050 duk__expr(comp_ctx, res, rbp_flags);
74051 return duk__ivalue_totemp(comp_ctx, res);
74052}
74053#endif
74054
74056 duk_ivalue *res,
74057 duk_small_uint_t rbp_flags,
74058 duk_regconst_t forced_reg) {
74059 DUK_ASSERT(forced_reg >= 0);
74060 duk__expr(comp_ctx, res, rbp_flags);
74061 duk__ivalue_toforcedreg(comp_ctx, res, forced_reg);
74062}
74063
74065 duk__expr(comp_ctx, res, rbp_flags);
74066 return duk__ivalue_toregconst(comp_ctx, res);
74067}
74068
74069#if 0 /* unused */
74070DUK_LOCAL duk_regconst_t duk__expr_totempconst(duk_compiler_ctx *comp_ctx, duk_ivalue *res, duk_small_uint_t rbp_flags) {
74071 duk__expr(comp_ctx, res, rbp_flags);
74072 return duk__ivalue_totempconst(comp_ctx, res);
74073}
74074#endif
74075
74077 duk__expr(comp_ctx, res, rbp_flags);
74078 duk__ivalue_toplain(comp_ctx, res);
74079}
74080
74082 duk__expr(comp_ctx, res, rbp_flags);
74083 duk__ivalue_toplain_ignore(comp_ctx, res);
74084}
74085
74087 duk__exprtop(comp_ctx, res, rbp_flags);
74088 return duk__ivalue_toreg(comp_ctx, res);
74089}
74090
74091#if 0 /* unused */
74092DUK_LOCAL duk_regconst_t duk__exprtop_totemp(duk_compiler_ctx *comp_ctx, duk_ivalue *res, duk_small_uint_t rbp_flags) {
74093 duk__exprtop(comp_ctx, res, rbp_flags);
74094 return duk__ivalue_totemp(comp_ctx, res);
74095}
74096#endif
74097
74099 duk_ivalue *res,
74100 duk_small_uint_t rbp_flags,
74101 duk_regconst_t forced_reg) {
74102 DUK_ASSERT(forced_reg >= 0);
74103 duk__exprtop(comp_ctx, res, rbp_flags);
74104 duk__ivalue_toforcedreg(comp_ctx, res, forced_reg);
74105}
74106
74108 duk__exprtop(comp_ctx, res, rbp_flags);
74109 return duk__ivalue_toregconst(comp_ctx, res);
74112#if 0 /* unused */
74113DUK_LOCAL void duk__exprtop_toplain_ignore(duk_compiler_ctx *comp_ctx, duk_ivalue *res, int rbp_flags) {
74114 duk__exprtop(comp_ctx, res, rbp_flags);
74115 duk__ivalue_toplain_ignore(comp_ctx, res);
74116}
74117#endif
74118
74119/*
74120 * Parse an individual source element (top level statement) or a statement.
74121 *
74122 * Handles labeled statements automatically (peeling away labels before
74123 * parsing an expression that follows the label(s)).
74124 *
74125 * Upon entry, 'curr_tok' contains the first token of the statement (parsed
74126 * in "allow regexp literal" mode). Upon exit, 'curr_tok' contains the first
74127 * token following the statement (if the statement has a terminator, this is
74128 * the token after the terminator).
74129 */
74130
74131#define DUK__HAS_VAL (1 << 0) /* stmt has non-empty value */
74132#define DUK__HAS_TERM (1 << 1) /* stmt has explicit/implicit semicolon terminator */
74133#define DUK__ALLOW_AUTO_SEMI_ALWAYS (1 << 2) /* allow automatic semicolon even without lineterm (compatibility) */
74134#define DUK__STILL_PROLOGUE (1 << 3) /* statement does not terminate directive prologue */
74135#define DUK__IS_TERMINAL (1 << 4) /* statement is guaranteed to be terminal (control doesn't flow to next statement) */
74136
74137/* Parse a single variable declaration (e.g. "i" or "i=10"). A leading 'var'
74138 * has already been eaten. These is no return value in 'res', it is used only
74139 * as a temporary.
74140 *
74141 * When called from 'for-in' statement parser, the initializer expression must
74142 * not allow the 'in' token. The caller supply additional expression parsing
74143 * flags (like DUK__EXPR_FLAG_REJECT_IN) in 'expr_flags'.
74144 *
74145 * Finally, out_rc_varname and out_reg_varbind are updated to reflect where
74146 * the identifier is bound:
74147 *
74148 * If register bound: out_reg_varbind >= 0, out_rc_varname == 0 (ignore)
74149 * If not register bound: out_reg_varbind < 0, out_rc_varname >= 0
74150 *
74151 * These allow the caller to use the variable for further assignment, e.g.
74152 * as is done in 'for-in' parsing.
74153 */
74154
74156 duk_ivalue *res,
74157 duk_small_uint_t expr_flags,
74158 duk_regconst_t *out_reg_varbind,
74159 duk_regconst_t *out_rc_varname) {
74160 duk_hthread *thr = comp_ctx->thr;
74161 duk_hstring *h_varname;
74162 duk_regconst_t reg_varbind;
74163 duk_regconst_t rc_varname;
74164
74165 /* assume 'var' has been eaten */
74166
74167 /* Note: Identifier rejects reserved words */
74168 if (comp_ctx->curr_token.t != DUK_TOK_IDENTIFIER) {
74169 goto syntax_error;
74170 }
74171 h_varname = comp_ctx->curr_token.str1;
74172
74173 DUK_ASSERT(h_varname != NULL);
74174
74175 /* strict mode restrictions (E5 Section 12.2.1) */
74176 if (duk__hstring_is_eval_or_arguments_in_strict_mode(comp_ctx, h_varname)) {
74177 goto syntax_error;
74178 }
74179
74180 /* register declarations in first pass */
74181 if (comp_ctx->curr_func.in_scanning) {
74182 duk_uarridx_t n;
74183 DUK_DDD(DUK_DDDPRINT("register variable declaration %!O in pass 1", (duk_heaphdr *) h_varname));
74184 n = (duk_uarridx_t) duk_get_length(thr, comp_ctx->curr_func.decls_idx);
74185 duk_push_hstring(thr, h_varname);
74186 duk_put_prop_index(thr, comp_ctx->curr_func.decls_idx, n);
74187 duk_push_int(thr, DUK_DECL_TYPE_VAR + (0 << 8));
74188 duk_put_prop_index(thr, comp_ctx->curr_func.decls_idx, n + 1);
74189 }
74190
74191 duk_push_hstring(thr, h_varname); /* push before advancing to keep reachable */
74192
74193 /* register binding lookup is based on varmap (even in first pass) */
74194 duk_dup_top(thr);
74195 (void) duk__lookup_lhs(comp_ctx, &reg_varbind, &rc_varname);
74196
74197 duk__advance(comp_ctx); /* eat identifier */
74198
74199 if (comp_ctx->curr_token.t == DUK_TOK_EQUALSIGN) {
74200 duk__advance(comp_ctx);
74201
74202 DUK_DDD(DUK_DDDPRINT("vardecl, assign to '%!O' -> reg_varbind=%ld, rc_varname=%ld",
74203 (duk_heaphdr *) h_varname,
74204 (long) reg_varbind,
74205 (long) rc_varname));
74206
74207 duk__exprtop(comp_ctx, res, DUK__BP_COMMA | expr_flags /*rbp_flags*/); /* AssignmentExpression */
74208
74209 if (reg_varbind >= 0) {
74210 duk__ivalue_toforcedreg(comp_ctx, res, reg_varbind);
74211 } else {
74212 duk_regconst_t reg_val;
74213 reg_val = duk__ivalue_toreg(comp_ctx, res);
74215 }
74216 } else {
74217 if (expr_flags & DUK__EXPR_FLAG_REQUIRE_INIT) {
74218 /* Used for minimal 'const': initializer required. */
74219 goto syntax_error;
74220 }
74221 }
74222
74223 duk_pop(thr); /* pop varname */
74224
74225 *out_rc_varname = rc_varname;
74226 *out_reg_varbind = reg_varbind;
74227
74228 return;
74229
74230syntax_error:
74232 DUK_WO_NORETURN(return;);
74233}
74234
74236 duk_regconst_t reg_varbind;
74237 duk_regconst_t rc_varname;
74238
74239 duk__advance(comp_ctx); /* eat 'var' */
74240
74241 for (;;) {
74242 /* rc_varname and reg_varbind are ignored here */
74243 duk__parse_var_decl(comp_ctx, res, 0 | expr_flags, &reg_varbind, &rc_varname);
74244
74245 if (comp_ctx->curr_token.t != DUK_TOK_COMMA) {
74246 break;
74247 }
74248 duk__advance(comp_ctx);
74249 }
74250}
74251
74252DUK_LOCAL void duk__parse_for_stmt(duk_compiler_ctx *comp_ctx, duk_ivalue *res, duk_int_t pc_label_site) {
74253 duk_hthread *thr = comp_ctx->thr;
74254 duk_int_t pc_v34_lhs; /* start variant 3/4 left-hand-side code (L1 in doc/compiler.rst example) */
74255 duk_regconst_t temp_reset; /* knock back "next temp" to this whenever possible */
74256 duk_regconst_t reg_temps; /* preallocated temporaries (2) for variants 3 and 4 */
74257
74258 DUK_DDD(DUK_DDDPRINT("start parsing a for/for-in statement"));
74259
74260 /* Two temporaries are preallocated here for variants 3 and 4 which need
74261 * registers which are never clobbered by expressions in the loop
74262 * (concretely: for the enumerator object and the next enumerated value).
74263 * Variants 1 and 2 "release" these temps.
74264 */
74265
74266 reg_temps = DUK__ALLOCTEMPS(comp_ctx, 2);
74267
74268 temp_reset = DUK__GETTEMP(comp_ctx);
74269
74270 /*
74271 * For/for-in main variants are:
74272 *
74273 * 1. for (ExpressionNoIn_opt; Expression_opt; Expression_opt) Statement
74274 * 2. for (var VariableDeclarationNoIn; Expression_opt; Expression_opt) Statement
74275 * 3. for (LeftHandSideExpression in Expression) Statement
74276 * 4. for (var VariableDeclarationNoIn in Expression) Statement
74277 *
74278 * Parsing these without arbitrary lookahead or backtracking is relatively
74279 * tricky but we manage to do so for now.
74280 *
74281 * See doc/compiler.rst for a detailed discussion of control flow
74282 * issues, evaluation order issues, etc.
74283 */
74284
74285 duk__advance(comp_ctx); /* eat 'for' */
74287
74288 DUK_DDD(DUK_DDDPRINT("detecting for/for-in loop variant, pc=%ld", (long) duk__get_current_pc(comp_ctx)));
74289
74290 /* a label site has been emitted by duk__parse_stmt() automatically
74291 * (it will also emit the ENDLABEL).
74292 */
74293
74294 if (comp_ctx->curr_token.t == DUK_TOK_VAR) {
74295 /*
74296 * Variant 2 or 4
74297 */
74298
74299 duk_regconst_t reg_varbind; /* variable binding register if register-bound (otherwise < 0) */
74300 duk_regconst_t rc_varname; /* variable name reg/const, if variable not register-bound */
74301
74302 duk__advance(comp_ctx); /* eat 'var' */
74303 duk__parse_var_decl(comp_ctx, res, DUK__EXPR_FLAG_REJECT_IN, &reg_varbind, &rc_varname);
74304 DUK__SETTEMP(comp_ctx, temp_reset);
74305
74306 if (comp_ctx->curr_token.t == DUK_TOK_IN) {
74307 /*
74308 * Variant 4
74309 */
74310
74311 DUK_DDD(DUK_DDDPRINT("detected for variant 4: for (var VariableDeclarationNoIn in Expression) Statement"));
74312 pc_v34_lhs = duk__get_current_pc(comp_ctx); /* jump is inserted here */
74313 if (reg_varbind >= 0) {
74314 duk__emit_a_bc(comp_ctx, DUK_OP_LDREG, reg_varbind, reg_temps + 0);
74315 } else {
74316 duk__emit_a_bc(comp_ctx, DUK_OP_PUTVAR | DUK__EMIT_FLAG_A_IS_SOURCE, reg_temps + 0, rc_varname);
74317 }
74318 goto parse_3_or_4;
74319 } else {
74320 /*
74321 * Variant 2
74322 */
74323
74325 "detected for variant 2: for (var VariableDeclarationNoIn; Expression_opt; Expression_opt) Statement"));
74326 for (;;) {
74327 /* more initializers */
74328 if (comp_ctx->curr_token.t != DUK_TOK_COMMA) {
74329 break;
74330 }
74331 DUK_DDD(DUK_DDDPRINT("variant 2 has another variable initializer"));
74332
74333 duk__advance(comp_ctx); /* eat comma */
74334 duk__parse_var_decl(comp_ctx, res, DUK__EXPR_FLAG_REJECT_IN, &reg_varbind, &rc_varname);
74335 }
74336 goto parse_1_or_2;
74337 }
74338 } else {
74339 /*
74340 * Variant 1 or 3
74341 */
74342
74343 pc_v34_lhs = duk__get_current_pc(comp_ctx); /* jump is inserted here (variant 3) */
74344
74345 /* Note that duk__exprtop() here can clobber any reg above current temp_next,
74346 * so any loop variables (e.g. enumerator) must be "preallocated".
74347 */
74348
74349 /* don't coerce yet to a plain value (variant 3 needs special handling) */
74350 duk__exprtop(comp_ctx,
74351 res,
74353 DUK__EXPR_FLAG_ALLOW_EMPTY /*rbp_flags*/); /* Expression */
74354 if (comp_ctx->curr_token.t == DUK_TOK_IN) {
74355 /*
74356 * Variant 3
74357 */
74358
74359 /* XXX: need to determine LHS type, and check that it is LHS compatible */
74360 DUK_DDD(DUK_DDDPRINT("detected for variant 3: for (LeftHandSideExpression in Expression) Statement"));
74361 if (duk__expr_is_empty(comp_ctx)) {
74362 goto syntax_error; /* LeftHandSideExpression does not allow empty expression */
74363 }
74364
74365 if (res->t == DUK_IVAL_VAR) {
74366 duk_regconst_t reg_varbind;
74367 duk_regconst_t rc_varname;
74368
74369 duk_dup(thr, res->x1.valstack_idx);
74370 if (duk__lookup_lhs(comp_ctx, &reg_varbind, &rc_varname)) {
74371 duk__emit_a_bc(comp_ctx, DUK_OP_LDREG, reg_varbind, reg_temps + 0);
74372 } else {
74373 duk__emit_a_bc(comp_ctx,
74375 reg_temps + 0,
74376 rc_varname);
74377 }
74378 } else if (res->t == DUK_IVAL_PROP) {
74379 /* Don't allow a constant for the object (even for a number etc), as
74380 * it goes into the 'A' field of the opcode.
74381 */
74382 duk_regconst_t reg_obj;
74383 duk_regconst_t rc_key;
74384 reg_obj = duk__ispec_toregconst_raw(comp_ctx,
74385 &res->x1,
74386 -1 /*forced_reg*/,
74387 0 /*flags*/); /* don't allow const */
74388 rc_key = duk__ispec_toregconst_raw(comp_ctx,
74389 &res->x2,
74390 -1 /*forced_reg*/,
74391 DUK__IVAL_FLAG_ALLOW_CONST /*flags*/);
74392 duk__emit_a_b_c(comp_ctx,
74394 reg_obj,
74395 rc_key,
74396 reg_temps + 0);
74397 } else {
74398 duk__ivalue_toplain_ignore(comp_ctx, res); /* just in case */
74400 }
74401 goto parse_3_or_4;
74402 } else {
74403 /*
74404 * Variant 1
74405 */
74406
74408 "detected for variant 1: for (ExpressionNoIn_opt; Expression_opt; Expression_opt) Statement"));
74409 duk__ivalue_toplain_ignore(comp_ctx, res);
74410 goto parse_1_or_2;
74411 }
74412 }
74413
74414parse_1_or_2:
74415 /*
74416 * Parse variant 1 or 2. The first part expression (which differs
74417 * in the variants) has already been parsed and its code emitted.
74418 *
74419 * reg_temps + 0: unused
74420 * reg_temps + 1: unused
74421 */
74422 {
74423 duk_regconst_t rc_cond;
74424 duk_int_t pc_l1, pc_l2, pc_l3, pc_l4;
74425 duk_int_t pc_jumpto_l3, pc_jumpto_l4;
74426 duk_bool_t expr_c_empty;
74427
74428 DUK_DDD(DUK_DDDPRINT("shared code for parsing variants 1 and 2"));
74429
74430 /* "release" preallocated temps since we won't need them */
74431 temp_reset = reg_temps + 0;
74432 DUK__SETTEMP(comp_ctx, temp_reset);
74433
74435
74436 pc_l1 = duk__get_current_pc(comp_ctx);
74437 duk__exprtop(comp_ctx, res, DUK__BP_FOR_EXPR | DUK__EXPR_FLAG_ALLOW_EMPTY /*rbp_flags*/); /* Expression_opt */
74438 if (duk__expr_is_empty(comp_ctx)) {
74439 /* no need to coerce */
74440 pc_jumpto_l3 = duk__emit_jump_empty(comp_ctx); /* to body */
74441 pc_jumpto_l4 = -1; /* omitted */
74442 } else {
74443 rc_cond = duk__ivalue_toregconst(comp_ctx, res);
74444 duk__emit_if_false_skip(comp_ctx, rc_cond);
74445 pc_jumpto_l3 = duk__emit_jump_empty(comp_ctx); /* to body */
74446 pc_jumpto_l4 = duk__emit_jump_empty(comp_ctx); /* to exit */
74447 }
74448 DUK__SETTEMP(comp_ctx, temp_reset);
74449
74451
74452 pc_l2 = duk__get_current_pc(comp_ctx);
74453 duk__exprtop(comp_ctx, res, DUK__BP_FOR_EXPR | DUK__EXPR_FLAG_ALLOW_EMPTY /*rbp_flags*/); /* Expression_opt */
74454 if (duk__expr_is_empty(comp_ctx)) {
74455 /* no need to coerce */
74456 expr_c_empty = 1;
74457 /* JUMP L1 omitted */
74458 } else {
74459 duk__ivalue_toplain_ignore(comp_ctx, res);
74460 expr_c_empty = 0;
74461 duk__emit_jump(comp_ctx, pc_l1);
74462 }
74463 DUK__SETTEMP(comp_ctx, temp_reset);
74464
74465 comp_ctx->curr_func.allow_regexp_in_adv = 1;
74466 duk__advance_expect(comp_ctx, DUK_TOK_RPAREN); /* Allow RegExp as part of next stmt. */
74467
74468 pc_l3 = duk__get_current_pc(comp_ctx);
74469 duk__parse_stmt(comp_ctx, res, 0 /*allow_source_elem*/);
74470 if (expr_c_empty) {
74471 duk__emit_jump(comp_ctx, pc_l1);
74472 } else {
74473 duk__emit_jump(comp_ctx, pc_l2);
74474 }
74475 /* temp reset is not necessary after duk__parse_stmt(), which already does it */
74476
74477 pc_l4 = duk__get_current_pc(comp_ctx);
74478
74479 DUK_DDD(DUK_DDDPRINT("patching jumps: jumpto_l3: %ld->%ld, jumpto_l4: %ld->%ld, "
74480 "break: %ld->%ld, continue: %ld->%ld",
74481 (long) pc_jumpto_l3,
74482 (long) pc_l3,
74483 (long) pc_jumpto_l4,
74484 (long) pc_l4,
74485 (long) (pc_label_site + 1),
74486 (long) pc_l4,
74487 (long) (pc_label_site + 2),
74488 (long) pc_l2));
74489
74490 duk__patch_jump(comp_ctx, pc_jumpto_l3, pc_l3);
74491 duk__patch_jump(comp_ctx, pc_jumpto_l4, pc_l4);
74492 duk__patch_jump(comp_ctx, pc_label_site + 1, pc_l4); /* break jump */
74493 duk__patch_jump(comp_ctx, pc_label_site + 2, expr_c_empty ? pc_l1 : pc_l2); /* continue jump */
74494 }
74495 goto finished;
74496
74497parse_3_or_4:
74498 /*
74499 * Parse variant 3 or 4.
74500 *
74501 * For variant 3 (e.g. "for (A in C) D;") the code for A (except the
74502 * final property/variable write) has already been emitted. The first
74503 * instruction of that code is at pc_v34_lhs; a JUMP needs to be inserted
74504 * there to satisfy control flow needs.
74505 *
74506 * For variant 4, if the variable declaration had an initializer
74507 * (e.g. "for (var A = B in C) D;") the code for the assignment
74508 * (B) has already been emitted.
74509 *
74510 * Variables set before entering here:
74511 *
74512 * pc_v34_lhs: insert a "JUMP L2" here (see doc/compiler.rst example).
74513 * reg_temps + 0: iteration target value (written to LHS)
74514 * reg_temps + 1: enumerator object
74515 */
74516 {
74517 duk_int_t pc_l1, pc_l2, pc_l3, pc_l4, pc_l5;
74518 duk_int_t pc_jumpto_l2, pc_jumpto_l3, pc_jumpto_l4, pc_jumpto_l5;
74519 duk_regconst_t reg_target;
74520
74521 DUK_DDD(DUK_DDDPRINT("shared code for parsing variants 3 and 4, pc_v34_lhs=%ld", (long) pc_v34_lhs));
74522
74523 DUK__SETTEMP(comp_ctx, temp_reset);
74524
74525 /* First we need to insert a jump in the middle of previously
74526 * emitted code to get the control flow right. No jumps can
74527 * cross the position where the jump is inserted. See doc/compiler.rst
74528 * for discussion on the intricacies of control flow and side effects
74529 * for variants 3 and 4.
74530 */
74531
74532 duk__insert_jump_entry(comp_ctx, pc_v34_lhs);
74533 pc_jumpto_l2 = pc_v34_lhs; /* inserted jump */
74534 pc_l1 = pc_v34_lhs + 1; /* +1, right after inserted jump */
74535
74536 /* The code for writing reg_temps + 0 to the left hand side has already
74537 * been emitted.
74538 */
74539
74540 pc_jumpto_l3 = duk__emit_jump_empty(comp_ctx); /* -> loop body */
74541
74542 duk__advance(comp_ctx); /* eat 'in' */
74543
74544 /* Parse enumeration target and initialize enumerator. For 'null' and 'undefined',
74545 * INITENUM will creates a 'null' enumerator which works like an empty enumerator
74546 * (E5 Section 12.6.4, step 3). Note that INITENUM requires the value to be in a
74547 * register (constant not allowed).
74548 */
74549
74550 pc_l2 = duk__get_current_pc(comp_ctx);
74551 reg_target = duk__exprtop_toreg(comp_ctx, res, DUK__BP_FOR_EXPR /*rbp_flags*/); /* Expression */
74552 duk__emit_b_c(comp_ctx, DUK_OP_INITENUM | DUK__EMIT_FLAG_B_IS_TARGET, reg_temps + 1, reg_target);
74553 pc_jumpto_l4 = duk__emit_jump_empty(comp_ctx);
74554 DUK__SETTEMP(comp_ctx, temp_reset);
74555
74556 comp_ctx->curr_func.allow_regexp_in_adv = 1;
74557 duk__advance_expect(comp_ctx, DUK_TOK_RPAREN); /* Allow RegExp as part of next stmt. */
74558
74559 pc_l3 = duk__get_current_pc(comp_ctx);
74560 duk__parse_stmt(comp_ctx, res, 0 /*allow_source_elem*/);
74561 /* temp reset is not necessary after duk__parse_stmt(), which already does it */
74562
74563 /* NEXTENUM needs a jump slot right after the main opcode.
74564 * We need the code emitter to reserve the slot: if there's
74565 * target shuffling, the target shuffle opcodes must happen
74566 * after the jump slot (for NEXTENUM the shuffle opcodes are
74567 * not needed if the enum is finished).
74568 */
74569 pc_l4 = duk__get_current_pc(comp_ctx);
74570 duk__emit_b_c(comp_ctx,
74572 reg_temps + 0,
74573 reg_temps + 1);
74574 pc_jumpto_l5 = comp_ctx->emit_jumpslot_pc; /* NEXTENUM jump slot: executed when enum finished */
74575 duk__emit_jump(comp_ctx, pc_l1); /* jump to next loop, using reg_v34_iter as iterated value */
74576
74577 pc_l5 = duk__get_current_pc(comp_ctx);
74578
74579 /* XXX: since the enumerator may be a memory expensive object,
74580 * perhaps clear it explicitly here? If so, break jump must
74581 * go through this clearing operation.
74582 */
74583
74584 DUK_DDD(DUK_DDDPRINT("patching jumps: jumpto_l2: %ld->%ld, jumpto_l3: %ld->%ld, "
74585 "jumpto_l4: %ld->%ld, jumpto_l5: %ld->%ld, "
74586 "break: %ld->%ld, continue: %ld->%ld",
74587 (long) pc_jumpto_l2,
74588 (long) pc_l2,
74589 (long) pc_jumpto_l3,
74590 (long) pc_l3,
74591 (long) pc_jumpto_l4,
74592 (long) pc_l4,
74593 (long) pc_jumpto_l5,
74594 (long) pc_l5,
74595 (long) (pc_label_site + 1),
74596 (long) pc_l5,
74597 (long) (pc_label_site + 2),
74598 (long) pc_l4));
74599
74600 duk__patch_jump(comp_ctx, pc_jumpto_l2, pc_l2);
74601 duk__patch_jump(comp_ctx, pc_jumpto_l3, pc_l3);
74602 duk__patch_jump(comp_ctx, pc_jumpto_l4, pc_l4);
74603 duk__patch_jump(comp_ctx, pc_jumpto_l5, pc_l5);
74604 duk__patch_jump(comp_ctx, pc_label_site + 1, pc_l5); /* break jump */
74605 duk__patch_jump(comp_ctx, pc_label_site + 2, pc_l4); /* continue jump */
74606 }
74607 goto finished;
74608
74609finished:
74610 DUK_DDD(DUK_DDDPRINT("end parsing a for/for-in statement"));
74611 return;
74612
74613syntax_error:
74615 DUK_WO_NORETURN(return;);
74616}
74617
74618DUK_LOCAL void duk__parse_switch_stmt(duk_compiler_ctx *comp_ctx, duk_ivalue *res, duk_int_t pc_label_site) {
74619 duk_hthread *thr = comp_ctx->thr;
74620 duk_regconst_t temp_at_loop;
74621 duk_regconst_t rc_switch; /* reg/const for switch value */
74622 duk_regconst_t rc_case; /* reg/const for case value */
74623 duk_regconst_t reg_temp; /* general temp register */
74624 duk_int_t pc_prevcase = -1;
74625 duk_int_t pc_prevstmt = -1;
74626 duk_int_t pc_default = -1; /* -1 == not set, -2 == pending (next statement list) */
74627
74628 /* Note: negative pc values are ignored when patching jumps, so no explicit checks needed */
74629
74630 /*
74631 * Switch is pretty complicated because of several conflicting concerns:
74632 *
74633 * - Want to generate code without an intermediate representation,
74634 * i.e., in one go
74635 *
74636 * - Case selectors are expressions, not values, and may thus e.g. throw
74637 * exceptions (which causes evaluation order concerns)
74638 *
74639 * - Evaluation semantics of case selectors and default clause need to be
74640 * carefully implemented to provide correct behavior even with case value
74641 * side effects
74642 *
74643 * - Fall through case and default clauses; avoiding dead JUMPs if case
74644 * ends with an unconditional jump (a break or a continue)
74645 *
74646 * - The same case value may occur multiple times, but evaluation rules
74647 * only process the first match before switching to a "propagation" mode
74648 * where case values are no longer evaluated
74649 *
74650 * See E5 Section 12.11. Also see doc/compiler.rst for compilation
74651 * discussion.
74652 */
74653
74654 duk__advance(comp_ctx);
74656 rc_switch = duk__exprtop_toregconst(comp_ctx, res, DUK__BP_FOR_EXPR /*rbp_flags*/);
74657 duk__advance_expect(comp_ctx, DUK_TOK_RPAREN); /* RegExp mode does not matter. */
74659
74660 DUK_DDD(DUK_DDDPRINT("switch value in register %ld", (long) rc_switch));
74661
74662 temp_at_loop = DUK__GETTEMP(comp_ctx);
74663
74664 for (;;) {
74665 duk_int_t num_stmts;
74666 duk_small_uint_t tok;
74667
74668 /* sufficient for keeping temp reg numbers in check */
74669 DUK__SETTEMP(comp_ctx, temp_at_loop);
74670
74671 if (comp_ctx->curr_token.t == DUK_TOK_RCURLY) {
74672 break;
74673 }
74674
74675 /*
74676 * Parse a case or default clause.
74677 */
74678
74679 if (comp_ctx->curr_token.t == DUK_TOK_CASE) {
74680 /*
74681 * Case clause.
74682 *
74683 * Note: cannot use reg_case as a temp register (for SEQ target)
74684 * because it may be a constant.
74685 */
74686
74687 duk__patch_jump_here(comp_ctx, pc_prevcase); /* chain jumps for case
74688 * evaluation and checking
74689 */
74690
74691 duk__advance(comp_ctx);
74692 rc_case = duk__exprtop_toregconst(comp_ctx, res, DUK__BP_FOR_EXPR /*rbp_flags*/);
74694
74695 reg_temp = DUK__ALLOCTEMP(comp_ctx);
74696 duk__emit_a_b_c(comp_ctx, DUK_OP_SEQ | DUK__EMIT_FLAG_BC_REGCONST, reg_temp, rc_switch, rc_case);
74697 duk__emit_if_true_skip(comp_ctx, reg_temp);
74698
74699 /* jump to next case clause */
74700 pc_prevcase = duk__emit_jump_empty(comp_ctx); /* no match, next case */
74701
74702 /* statements go here (if any) on next loop */
74703 } else if (comp_ctx->curr_token.t == DUK_TOK_DEFAULT) {
74704 /*
74705 * Default clause.
74706 */
74707
74708 if (pc_default >= 0) {
74709 goto syntax_error;
74710 }
74711 duk__advance(comp_ctx);
74713
74714 /* Fix for https://github.com/svaarala/duktape/issues/155:
74715 * If 'default' is first clause (detected by pc_prevcase < 0)
74716 * we need to ensure we stay in the matching chain.
74717 */
74718 if (pc_prevcase < 0) {
74719 DUK_DD(DUK_DDPRINT("default clause is first, emit prevcase jump"));
74720 pc_prevcase = duk__emit_jump_empty(comp_ctx);
74721 }
74722
74723 /* default clause matches next statement list (if any) */
74724 pc_default = -2;
74725 } else {
74726 /* Code is not accepted before the first case/default clause */
74727 goto syntax_error;
74728 }
74729
74730 /*
74731 * Parse code after the clause. Possible terminators are
74732 * 'case', 'default', and '}'.
74733 *
74734 * Note that there may be no code at all, not even an empty statement,
74735 * between case clauses. This must be handled just like an empty statement
74736 * (omitting seemingly pointless JUMPs), to avoid situations like
74737 * test-bug-case-fallthrough.js.
74738 */
74739
74740 num_stmts = 0;
74741 if (pc_default == -2) {
74742 pc_default = duk__get_current_pc(comp_ctx);
74743 }
74744
74745 /* Note: this is correct even for default clause statements:
74746 * they participate in 'fall-through' behavior even if the
74747 * default clause is in the middle.
74748 */
74749 duk__patch_jump_here(comp_ctx, pc_prevstmt); /* chain jumps for 'fall-through'
74750 * after a case matches.
74751 */
74752
74753 for (;;) {
74754 tok = comp_ctx->curr_token.t;
74755 if (tok == DUK_TOK_CASE || tok == DUK_TOK_DEFAULT || tok == DUK_TOK_RCURLY) {
74756 break;
74757 }
74758 num_stmts++;
74759 duk__parse_stmt(comp_ctx, res, 0 /*allow_source_elem*/);
74760 }
74761
74762 /* fall-through jump to next code of next case (backpatched) */
74763 pc_prevstmt = duk__emit_jump_empty(comp_ctx);
74764
74765 /* XXX: would be nice to omit this jump when the jump is not
74766 * reachable, at least in the obvious cases (such as the case
74767 * ending with a 'break'.
74768 *
74769 * Perhaps duk__parse_stmt() could provide some info on whether
74770 * the statement is a "dead end"?
74771 *
74772 * If implemented, just set pc_prevstmt to -1 when not needed.
74773 */
74774 }
74775
74776 DUK_ASSERT(comp_ctx->curr_token.t == DUK_TOK_RCURLY);
74777 comp_ctx->curr_func.allow_regexp_in_adv = 1;
74778 duk__advance(comp_ctx); /* Allow RegExp as part of next stmt. */
74779
74780 /* default case control flow patchup; note that if pc_prevcase < 0
74781 * (i.e. no case clauses), control enters default case automatically.
74782 */
74783 if (pc_default >= 0) {
74784 /* default case exists: go there if no case matches */
74785 duk__patch_jump(comp_ctx, pc_prevcase, pc_default);
74786 } else {
74787 /* default case does not exist, or no statements present
74788 * after default case: finish case evaluation
74789 */
74790 duk__patch_jump_here(comp_ctx, pc_prevcase);
74791 }
74792
74793 /* fall-through control flow patchup; note that pc_prevstmt may be
74794 * < 0 (i.e. no case clauses), in which case this is a no-op.
74795 */
74796 duk__patch_jump_here(comp_ctx, pc_prevstmt);
74797
74798 /* continue jump not patched, an INVALID opcode remains there */
74799 duk__patch_jump_here(comp_ctx, pc_label_site + 1); /* break jump */
74800
74801 /* Note: 'fast' breaks will jump to pc_label_site + 1, which will
74802 * then jump here. The double jump will be eliminated by a
74803 * peephole pass, resulting in an optimal jump here. The label
74804 * site jumps will remain in bytecode and will waste code size.
74805 */
74806
74807 return;
74808
74809syntax_error:
74811 DUK_WO_NORETURN(return;);
74812}
74813
74815 duk_regconst_t temp_reset;
74816 duk_regconst_t rc_cond;
74817 duk_int_t pc_jump_false;
74818
74819 DUK_DDD(DUK_DDDPRINT("begin parsing if statement"));
74820
74821 temp_reset = DUK__GETTEMP(comp_ctx);
74822
74823 duk__advance(comp_ctx); /* eat 'if' */
74825
74826 rc_cond = duk__exprtop_toregconst(comp_ctx, res, DUK__BP_FOR_EXPR /*rbp_flags*/);
74827 duk__emit_if_true_skip(comp_ctx, rc_cond);
74828 pc_jump_false = duk__emit_jump_empty(comp_ctx); /* jump to end or else part */
74829 DUK__SETTEMP(comp_ctx, temp_reset);
74830
74831 comp_ctx->curr_func.allow_regexp_in_adv = 1;
74832 duk__advance_expect(comp_ctx, DUK_TOK_RPAREN); /* Allow RegExp as part of next stmt. */
74833
74834 duk__parse_stmt(comp_ctx, res, 0 /*allow_source_elem*/);
74835
74836 /* The 'else' ambiguity is resolved by 'else' binding to the innermost
74837 * construct, so greedy matching is correct here.
74838 */
74839
74840 if (comp_ctx->curr_token.t == DUK_TOK_ELSE) {
74841 duk_int_t pc_jump_end;
74842
74843 DUK_DDD(DUK_DDDPRINT("if has else part"));
74844
74845 duk__advance(comp_ctx);
74846
74847 pc_jump_end = duk__emit_jump_empty(comp_ctx); /* jump from true part to end */
74848 duk__patch_jump_here(comp_ctx, pc_jump_false);
74849
74850 duk__parse_stmt(comp_ctx, res, 0 /*allow_source_elem*/);
74851
74852 duk__patch_jump_here(comp_ctx, pc_jump_end);
74853 } else {
74854 DUK_DDD(DUK_DDDPRINT("if does not have else part"));
74855
74856 duk__patch_jump_here(comp_ctx, pc_jump_false);
74857 }
74858
74859 DUK_DDD(DUK_DDDPRINT("end parsing if statement"));
74860}
74861
74862DUK_LOCAL void duk__parse_do_stmt(duk_compiler_ctx *comp_ctx, duk_ivalue *res, duk_int_t pc_label_site) {
74863 duk_regconst_t rc_cond;
74864 duk_int_t pc_start;
74865
74866 DUK_DDD(DUK_DDDPRINT("begin parsing do statement"));
74867
74868 duk__advance(comp_ctx); /* Eat 'do'; allow RegExp as part of next stmt. */
74870 pc_start = duk__get_current_pc(comp_ctx);
74871 duk__parse_stmt(comp_ctx, res, 0 /*allow_source_elem*/);
74872 duk__patch_jump_here(comp_ctx, pc_label_site + 2); /* continue jump */
74873
74876
74877 rc_cond = duk__exprtop_toregconst(comp_ctx, res, DUK__BP_FOR_EXPR /*rbp_flags*/);
74878 duk__emit_if_false_skip(comp_ctx, rc_cond);
74879 duk__emit_jump(comp_ctx, pc_start);
74880 /* no need to reset temps, as we're finished emitting code */
74881
74882 comp_ctx->curr_func.allow_regexp_in_adv = 1; /* Allow RegExp as part of next stmt. */
74884
74885 duk__patch_jump_here(comp_ctx, pc_label_site + 1); /* break jump */
74886
74887 DUK_DDD(DUK_DDDPRINT("end parsing do statement"));
74888}
74889
74890DUK_LOCAL void duk__parse_while_stmt(duk_compiler_ctx *comp_ctx, duk_ivalue *res, duk_int_t pc_label_site) {
74891 duk_regconst_t temp_reset;
74892 duk_regconst_t rc_cond;
74893 duk_int_t pc_start;
74894 duk_int_t pc_jump_false;
74895
74896 DUK_DDD(DUK_DDDPRINT("begin parsing while statement"));
74897
74898 temp_reset = DUK__GETTEMP(comp_ctx);
74899
74900 duk__advance(comp_ctx); /* eat 'while' */
74901
74904 pc_start = duk__get_current_pc(comp_ctx);
74905 duk__patch_jump_here(comp_ctx, pc_label_site + 2); /* continue jump */
74906
74907 rc_cond = duk__exprtop_toregconst(comp_ctx, res, DUK__BP_FOR_EXPR /*rbp_flags*/);
74908 duk__emit_if_true_skip(comp_ctx, rc_cond);
74909 pc_jump_false = duk__emit_jump_empty(comp_ctx);
74910 DUK__SETTEMP(comp_ctx, temp_reset);
74911
74912 comp_ctx->curr_func.allow_regexp_in_adv = 1;
74913 duk__advance_expect(comp_ctx, DUK_TOK_RPAREN); /* Allow RegExp as part of next stmt. */
74914
74915 duk__parse_stmt(comp_ctx, res, 0 /*allow_source_elem*/);
74916 duk__emit_jump(comp_ctx, pc_start);
74917
74918 duk__patch_jump_here(comp_ctx, pc_jump_false);
74919 duk__patch_jump_here(comp_ctx, pc_label_site + 1); /* break jump */
74920
74921 DUK_DDD(DUK_DDDPRINT("end parsing while statement"));
74922}
74923
74925 duk_hthread *thr = comp_ctx->thr;
74926 duk_bool_t is_break = (comp_ctx->curr_token.t == DUK_TOK_BREAK);
74927 duk_int_t label_id;
74928 duk_int_t label_catch_depth;
74929 duk_int_t label_pc; /* points to LABEL; pc+1 = jump site for break; pc+2 = jump site for continue */
74930 duk_bool_t label_is_closest;
74931
74932 DUK_UNREF(res);
74933
74934 duk__advance(comp_ctx); /* eat 'break' or 'continue' */
74935
74936 if (comp_ctx->curr_token.t == DUK_TOK_SEMICOLON || /* explicit semi follows */
74937 comp_ctx->curr_token.lineterm || /* automatic semi will be inserted */
74938 comp_ctx->curr_token.allow_auto_semi) { /* automatic semi will be inserted */
74939 /* break/continue without label */
74940
74941 duk__lookup_active_label(comp_ctx,
74943 is_break,
74944 &label_id,
74945 &label_catch_depth,
74946 &label_pc,
74947 &label_is_closest);
74948 } else if (comp_ctx->curr_token.t == DUK_TOK_IDENTIFIER) {
74949 /* break/continue with label (label cannot be a reserved word, production is 'Identifier' */
74950 DUK_ASSERT(comp_ctx->curr_token.str1 != NULL);
74951 duk__lookup_active_label(comp_ctx,
74952 comp_ctx->curr_token.str1,
74953 is_break,
74954 &label_id,
74955 &label_catch_depth,
74956 &label_pc,
74957 &label_is_closest);
74958 duk__advance(comp_ctx);
74959 } else {
74961 DUK_WO_NORETURN(return;);
74962 }
74963
74964 /* Use a fast break/continue when possible. A fast break/continue is
74965 * just a jump to the LABEL break/continue jump slot, which then jumps
74966 * to an appropriate place (for break, going through ENDLABEL correctly).
74967 * The peephole optimizer will optimize the jump to a direct one.
74968 */
74969
74970 if (label_catch_depth == comp_ctx->curr_func.catch_depth && label_is_closest) {
74971 DUK_DDD(DUK_DDDPRINT("break/continue: is_break=%ld, label_id=%ld, label_is_closest=%ld, "
74972 "label_catch_depth=%ld, catch_depth=%ld "
74973 "-> use fast variant (direct jump)",
74974 (long) is_break,
74975 (long) label_id,
74976 (long) label_is_closest,
74977 (long) label_catch_depth,
74978 (long) comp_ctx->curr_func.catch_depth));
74979
74980 duk__emit_jump(comp_ctx, label_pc + (is_break ? 1 : 2));
74981 } else {
74982 DUK_DDD(DUK_DDDPRINT("break/continue: is_break=%ld, label_id=%ld, label_is_closest=%ld, "
74983 "label_catch_depth=%ld, catch_depth=%ld "
74984 "-> use slow variant (longjmp)",
74985 (long) is_break,
74986 (long) label_id,
74987 (long) label_is_closest,
74988 (long) label_catch_depth,
74989 (long) comp_ctx->curr_func.catch_depth));
74990
74991 duk__emit_bc(comp_ctx, is_break ? DUK_OP_BREAK : DUK_OP_CONTINUE, (duk_regconst_t) label_id);
74992 }
74993}
74994
74996 duk_hthread *thr = comp_ctx->thr;
74997 duk_regconst_t rc_val;
74998
74999 duk__advance(comp_ctx); /* eat 'return' */
75000
75001 /* A 'return' statement is only allowed inside an actual function body,
75002 * not as part of eval or global code.
75003 */
75004 if (!comp_ctx->curr_func.is_function) {
75006 DUK_WO_NORETURN(return;);
75007 }
75008
75009 if (comp_ctx->curr_token.t == DUK_TOK_SEMICOLON || /* explicit semi follows */
75010 comp_ctx->curr_token.lineterm || /* automatic semi will be inserted */
75011 comp_ctx->curr_token.allow_auto_semi) { /* automatic semi will be inserted */
75012 DUK_DDD(DUK_DDDPRINT("empty return value -> undefined"));
75014 } else {
75015 duk_int_t pc_before_expr;
75016 duk_int_t pc_after_expr;
75017
75018 DUK_DDD(DUK_DDDPRINT("return with a value"));
75019
75020 DUK_UNREF(pc_before_expr);
75021 DUK_UNREF(pc_after_expr);
75022
75023 pc_before_expr = duk__get_current_pc(comp_ctx);
75024 rc_val = duk__exprtop_toregconst(comp_ctx, res, DUK__BP_FOR_EXPR /*rbp_flags*/);
75025 pc_after_expr = duk__get_current_pc(comp_ctx);
75026
75027 /* Tail call check: if last opcode emitted was CALL, and
75028 * the context allows it, add a tailcall flag to the CALL.
75029 * This doesn't guarantee that a tail call will be allowed at
75030 * runtime, so the RETURN must still be emitted. (Duktape
75031 * 0.10.0 avoided this and simulated a RETURN if a tail call
75032 * couldn't be used at runtime; but this didn't work
75033 * correctly with a thread yield/resume, see
75034 * test-bug-tailcall-thread-yield-resume.js for discussion.)
75035 *
75036 * In addition to the last opcode being CALL, we also need to
75037 * be sure that 'rc_val' is the result register of the CALL.
75038 * For instance, for the expression 'return 0, (function ()
75039 * { return 1; }), 2' the last opcode emitted is CALL (no
75040 * bytecode is emitted for '2') but 'rc_val' indicates
75041 * constant '2'. Similarly if '2' is replaced by a register
75042 * bound variable, no opcodes are emitted but tail call would
75043 * be incorrect.
75044 *
75045 * This is tricky and easy to get wrong. It would be best to
75046 * track enough expression metadata to check that 'rc_val' came
75047 * from that last CALL instruction. We don't have that metadata
75048 * now, so we check that 'rc_val' is a temporary register result
75049 * (not a constant or a register bound variable). There should
75050 * be no way currently for 'rc_val' to be a temporary for an
75051 * expression following the CALL instruction without emitting
75052 * some opcodes following the CALL. This proxy check is used
75053 * below.
75054 *
75055 * See: test-bug-comma-expr-gh131.js.
75056 *
75057 * The non-standard 'caller' property disables tail calls
75058 * because they pose some special cases which haven't been
75059 * fixed yet.
75060 */
75061
75062#if defined(DUK_USE_TAILCALL)
75063 if (comp_ctx->curr_func.catch_depth == 0 && /* no catchers */
75064 pc_after_expr > pc_before_expr) { /* at least one opcode emitted */
75065 duk_compiler_instr *instr;
75066 duk_instr_t ins;
75068
75069 instr = duk__get_instr_ptr(comp_ctx, pc_after_expr - 1);
75070 DUK_ASSERT(instr != NULL);
75071
75072 ins = instr->ins;
75073 op = (duk_small_uint_t) DUK_DEC_OP(ins);
75074 if ((op & ~0x0fU) == DUK_OP_CALL0 && DUK__ISREG_TEMP(comp_ctx, rc_val) /* see above */) {
75075 DUK_DDD(DUK_DDDPRINT("return statement detected a tail call opportunity: "
75076 "catch depth is 0, duk__exprtop() emitted >= 1 instructions, "
75077 "and last instruction is a CALL "
75078 "-> change to TAILCALL"));
75080 instr->ins = ins;
75081 }
75082 }
75083#endif /* DUK_USE_TAILCALL */
75084
75085 if (DUK__ISREG(rc_val)) {
75086 duk__emit_bc(comp_ctx, DUK_OP_RETREG, rc_val);
75087 } else {
75088 rc_val = DUK__REMOVECONST(rc_val);
75089 if (duk__const_needs_refcount(comp_ctx, rc_val)) {
75090 duk__emit_bc(comp_ctx, DUK_OP_RETCONST, rc_val);
75091 } else {
75092 duk__emit_bc(comp_ctx, DUK_OP_RETCONSTN, rc_val);
75094 }
75095 }
75096}
75097
75099 duk_regconst_t reg_val;
75100
75101 duk__advance(comp_ctx); /* eat 'throw' */
75102
75103 /* Unlike break/continue, throw statement does not allow an empty value. */
75104
75105 if (comp_ctx->curr_token.lineterm) {
75107 DUK_WO_NORETURN(return;);
75108 }
75109
75110 reg_val = duk__exprtop_toreg(comp_ctx, res, DUK__BP_FOR_EXPR /*rbp_flags*/);
75111 duk__emit_bc(comp_ctx, DUK_OP_THROW, reg_val);
75112}
75113
75115 duk_hthread *thr = comp_ctx->thr;
75116 duk_regconst_t reg_catch; /* reg_catch+0 and reg_catch+1 are reserved for TRYCATCH */
75117 duk_regconst_t rc_varname = 0;
75118 duk_small_uint_t trycatch_flags = 0;
75119 duk_int_t pc_ldconst = -1;
75120 duk_int_t pc_trycatch = -1;
75121 duk_int_t pc_catch = -1;
75122 duk_int_t pc_finally = -1;
75123
75124 DUK_UNREF(res);
75125
75126 /*
75127 * See the following documentation for discussion:
75128 *
75129 * doc/execution.rst: control flow details
75130 *
75131 * Try, catch, and finally "parts" are Blocks, not Statements, so
75132 * they must always be delimited by curly braces. This is unlike e.g.
75133 * the if statement, which accepts any Statement. This eliminates any
75134 * questions of matching parts of nested try statements. The Block
75135 * parsing is implemented inline here (instead of calling out).
75136 *
75137 * Finally part has a 'let scoped' variable, which requires a few kinks
75138 * here.
75139 */
75140
75141 comp_ctx->curr_func.catch_depth++;
75142
75143 duk__advance(comp_ctx); /* eat 'try' */
75144
75145 reg_catch = DUK__ALLOCTEMPS(comp_ctx, 2);
75146
75147 /* The target for this LDCONST may need output shuffling, but we assume
75148 * that 'pc_ldconst' will be the LDCONST that we can patch later. This
75149 * should be the case because there's no input shuffling. (If there's
75150 * no catch clause, this LDCONST will be replaced with a NOP.)
75151 */
75152 pc_ldconst = duk__get_current_pc(comp_ctx);
75153 duk__emit_a_bc(comp_ctx, DUK_OP_LDCONST, reg_catch, 0 /*patched later*/);
75154
75155 pc_trycatch = duk__get_current_pc(comp_ctx);
75156 duk__emit_invalid(comp_ctx); /* TRYCATCH, cannot emit now (not enough info) */
75157 duk__emit_invalid(comp_ctx); /* jump for 'catch' case */
75158 duk__emit_invalid(comp_ctx); /* jump for 'finally' case or end (if no finally) */
75159
75160 /* try part */
75162 duk__parse_stmts(comp_ctx, 0 /*allow_source_elem*/, 0 /*expect_eof*/, 1 /*regexp_after*/);
75163 /* the DUK_TOK_RCURLY is eaten by duk__parse_stmts() */
75165
75166 if (comp_ctx->curr_token.t == DUK_TOK_CATCH) {
75167 /*
75168 * The catch variable must be updated to reflect the new allocated
75169 * register for the duration of the catch clause. We need to store
75170 * and restore the original value for the varmap entry (if any).
75171 */
75172
75173 /*
75174 * Note: currently register bindings must be fixed for the entire
75175 * function. So, even though the catch variable is in a register
75176 * we know, we must use an explicit environment record and slow path
75177 * accesses to read/write the catch binding to make closures created
75178 * within the catch clause work correctly. This restriction should
75179 * be fixable (at least in common cases) later.
75180 *
75181 * See: test-bug-catch-binding-2.js.
75182 *
75183 * XXX: improve to get fast path access to most catch clauses.
75184 */
75185
75186 duk_hstring *h_var;
75187 duk_int_t varmap_value; /* for storing/restoring the varmap binding for catch variable */
75188
75189 DUK_DDD(DUK_DDDPRINT("stack top at start of catch clause: %ld", (long) duk_get_top(thr)));
75190
75191 trycatch_flags |= DUK_BC_TRYCATCH_FLAG_HAVE_CATCH;
75192
75193 pc_catch = duk__get_current_pc(comp_ctx);
75194
75195 duk__advance(comp_ctx);
75197
75198 if (comp_ctx->curr_token.t != DUK_TOK_IDENTIFIER) {
75199 /* Identifier, i.e. don't allow reserved words */
75200 goto syntax_error;
75201 }
75202 h_var = comp_ctx->curr_token.str1;
75203 DUK_ASSERT(h_var != NULL);
75204
75205 duk_push_hstring(thr, h_var); /* keep in on valstack, use borrowed ref below */
75206
75207 if (comp_ctx->curr_func.is_strict &&
75208 ((h_var == DUK_HTHREAD_STRING_EVAL(thr)) || (h_var == DUK_HTHREAD_STRING_LC_ARGUMENTS(thr)))) {
75209 DUK_DDD(DUK_DDDPRINT("catch identifier 'eval' or 'arguments' in strict mode -> SyntaxError"));
75210 goto syntax_error;
75211 }
75212
75213 duk_dup_top(thr);
75214 rc_varname = duk__getconst(comp_ctx);
75215 DUK_DDD(DUK_DDDPRINT("catch clause, rc_varname=0x%08lx (%ld)", (unsigned long) rc_varname, (long) rc_varname));
75216
75217 duk__advance(comp_ctx);
75219
75221
75222 DUK_DDD(DUK_DDDPRINT("varmap before modifying for catch clause: %!iT",
75223 (duk_tval *) duk_get_tval(thr, comp_ctx->curr_func.varmap_idx)));
75224
75225 duk_dup_top(thr);
75226 duk_get_prop(thr, comp_ctx->curr_func.varmap_idx);
75227 if (duk_is_undefined(thr, -1)) {
75228 varmap_value = -2;
75229 } else if (duk_is_null(thr, -1)) {
75230 varmap_value = -1;
75231 } else {
75232 DUK_ASSERT(duk_is_number(thr, -1));
75233 varmap_value = duk_get_int(thr, -1);
75234 DUK_ASSERT(varmap_value >= 0);
75235 }
75236 duk_pop(thr);
75237
75238#if 0
75239 /* It'd be nice to do something like this - but it doesn't
75240 * work for closures created inside the catch clause.
75241 */
75242 duk_dup_top(thr);
75243 duk_push_int(thr, (duk_int_t) (reg_catch + 0));
75244 duk_put_prop(thr, comp_ctx->curr_func.varmap_idx);
75245#endif
75246 duk_dup_top(thr);
75247 duk_push_null(thr);
75248 duk_put_prop(thr, comp_ctx->curr_func.varmap_idx);
75249
75250 duk__emit_a_bc(comp_ctx,
75252 reg_catch + 0 /*value*/,
75253 rc_varname /*varname*/);
75254
75255 DUK_DDD(DUK_DDDPRINT("varmap before parsing catch clause: %!iT",
75256 (duk_tval *) duk_get_tval(thr, comp_ctx->curr_func.varmap_idx)));
75257
75258 duk__parse_stmts(comp_ctx, 0 /*allow_source_elem*/, 0 /*expect_eof*/, 1 /*regexp_after*/);
75259 /* the DUK_TOK_RCURLY is eaten by duk__parse_stmts() */
75260
75261 if (varmap_value == -2) {
75262 /* not present */
75263 duk_del_prop(thr, comp_ctx->curr_func.varmap_idx);
75264 } else {
75265 if (varmap_value == -1) {
75266 duk_push_null(thr);
75267 } else {
75268 DUK_ASSERT(varmap_value >= 0);
75269 duk_push_int(thr, varmap_value);
75270 }
75271 duk_put_prop(thr, comp_ctx->curr_func.varmap_idx);
75272 }
75273 /* varname is popped by above code */
75274
75275 DUK_DDD(DUK_DDDPRINT("varmap after restore catch clause: %!iT",
75276 (duk_tval *) duk_get_tval(thr, comp_ctx->curr_func.varmap_idx)));
75277
75279
75280 /*
75281 * XXX: for now, indicate that an expensive catch binding
75282 * declarative environment is always needed. If we don't
75283 * need it, we don't need the const_varname either.
75284 */
75285
75286 trycatch_flags |= DUK_BC_TRYCATCH_FLAG_CATCH_BINDING;
75287
75288 DUK_DDD(DUK_DDDPRINT("stack top at end of catch clause: %ld", (long) duk_get_top(thr)));
75289 }
75290
75291 if (comp_ctx->curr_token.t == DUK_TOK_FINALLY) {
75292 trycatch_flags |= DUK_BC_TRYCATCH_FLAG_HAVE_FINALLY;
75293
75294 pc_finally = duk__get_current_pc(comp_ctx);
75295
75296 duk__advance(comp_ctx);
75297
75299 duk__parse_stmts(comp_ctx, 0 /*allow_source_elem*/, 0 /*expect_eof*/, 1 /*regexp_after*/);
75300 /* the DUK_TOK_RCURLY is eaten by duk__parse_stmts() */
75301 duk__emit_abc(comp_ctx, DUK_OP_ENDFIN, reg_catch); /* rethrow */
75302 }
75303
75304 if (!(trycatch_flags & DUK_BC_TRYCATCH_FLAG_HAVE_CATCH) && !(trycatch_flags & DUK_BC_TRYCATCH_FLAG_HAVE_FINALLY)) {
75305 /* must have catch and/or finally */
75306 goto syntax_error;
75307 }
75308
75309 /* If there's no catch block, rc_varname will be 0 and duk__patch_trycatch()
75310 * will replace the LDCONST with a NOP. For any actual constant (including
75311 * constant 0) the DUK__CONST_MARKER flag will be set in rc_varname.
75312 */
75313
75314 duk__patch_trycatch(comp_ctx, pc_ldconst, pc_trycatch, reg_catch, rc_varname, trycatch_flags);
75315
75316 if (trycatch_flags & DUK_BC_TRYCATCH_FLAG_HAVE_CATCH) {
75317 DUK_ASSERT(pc_catch >= 0);
75318 duk__patch_jump(comp_ctx, pc_trycatch + 1, pc_catch);
75319 }
75320
75321 if (trycatch_flags & DUK_BC_TRYCATCH_FLAG_HAVE_FINALLY) {
75322 DUK_ASSERT(pc_finally >= 0);
75323 duk__patch_jump(comp_ctx, pc_trycatch + 2, pc_finally);
75324 } else {
75325 /* without finally, the second jump slot is used to jump to end of stmt */
75326 duk__patch_jump_here(comp_ctx, pc_trycatch + 2);
75327 }
75328
75329 comp_ctx->curr_func.catch_depth--;
75330 return;
75331
75332syntax_error:
75334 DUK_WO_NORETURN(return;);
75335}
75336
75338 duk_int_t pc_trycatch;
75339 duk_int_t pc_finished;
75340 duk_regconst_t reg_catch;
75341 duk_small_uint_t trycatch_flags;
75342
75343 if (comp_ctx->curr_func.is_strict) {
75345 DUK_WO_NORETURN(return;);
75346 }
75347
75348 comp_ctx->curr_func.catch_depth++;
75349
75350 duk__advance(comp_ctx); /* eat 'with' */
75351
75352 reg_catch = DUK__ALLOCTEMPS(comp_ctx, 2);
75353
75355 duk__exprtop_toforcedreg(comp_ctx, res, DUK__BP_FOR_EXPR /*rbp_flags*/, reg_catch);
75356 comp_ctx->curr_func.allow_regexp_in_adv = 1;
75357 duk__advance_expect(comp_ctx, DUK_TOK_RPAREN); /* Allow RegExp as part of next stmt. */
75358
75359 pc_trycatch = duk__get_current_pc(comp_ctx);
75360 trycatch_flags = DUK_BC_TRYCATCH_FLAG_WITH_BINDING;
75361 duk__emit_a_bc(comp_ctx,
75363 (duk_regconst_t) trycatch_flags /*a*/,
75364 reg_catch /*bc*/);
75365 duk__emit_invalid(comp_ctx); /* catch jump */
75366 duk__emit_invalid(comp_ctx); /* finished jump */
75367
75368 duk__parse_stmt(comp_ctx, res, 0 /*allow_source_elem*/);
75370
75371 pc_finished = duk__get_current_pc(comp_ctx);
75372
75373 duk__patch_jump(comp_ctx, pc_trycatch + 2, pc_finished);
75374
75375 comp_ctx->curr_func.catch_depth--;
75376}
75377
75379 /* if a site already exists, nop: max one label site per statement */
75380 if (label_id >= 0) {
75381 return label_id;
75382 }
75383
75384 label_id = comp_ctx->curr_func.label_next++;
75385 DUK_DDD(DUK_DDDPRINT("allocated new label id for label site: %ld", (long) label_id));
75386
75387 duk__emit_bc(comp_ctx, DUK_OP_LABEL, (duk_regconst_t) label_id);
75388 duk__emit_invalid(comp_ctx);
75389 duk__emit_invalid(comp_ctx);
75390
75391 return label_id;
75392}
75393
75394/* Parse a single statement.
75395 *
75396 * Creates a label site (with an empty label) automatically for iteration
75397 * statements. Also "peels off" any label statements for explicit labels.
75398 */
75399DUK_LOCAL void duk__parse_stmt(duk_compiler_ctx *comp_ctx, duk_ivalue *res, duk_bool_t allow_source_elem) {
75400 duk_hthread *thr = comp_ctx->thr;
75401 duk_bool_t dir_prol_at_entry; /* directive prologue status at entry */
75402 duk_regconst_t temp_at_entry;
75403 duk_size_t labels_len_at_entry;
75404 duk_int_t pc_at_entry; /* assumed to also be PC of "LABEL" */
75405 duk_int_t stmt_id;
75406 duk_small_uint_t stmt_flags = 0;
75407 duk_int_t label_id = -1;
75408 duk_small_uint_t tok;
75409 duk_bool_t test_func_decl;
75410
75411 DUK__RECURSION_INCREASE(comp_ctx, thr);
75412
75413 temp_at_entry = DUK__GETTEMP(comp_ctx);
75414 pc_at_entry = duk__get_current_pc(comp_ctx);
75415 labels_len_at_entry = duk_get_length(thr, comp_ctx->curr_func.labelnames_idx);
75416 stmt_id = comp_ctx->curr_func.stmt_next++;
75417 dir_prol_at_entry = comp_ctx->curr_func.in_directive_prologue;
75418
75419 DUK_UNREF(stmt_id);
75420
75421 DUK_DDD(DUK_DDDPRINT("parsing a statement, stmt_id=%ld, temp_at_entry=%ld, labels_len_at_entry=%ld, "
75422 "is_strict=%ld, in_directive_prologue=%ld, catch_depth=%ld",
75423 (long) stmt_id,
75424 (long) temp_at_entry,
75425 (long) labels_len_at_entry,
75426 (long) comp_ctx->curr_func.is_strict,
75427 (long) comp_ctx->curr_func.in_directive_prologue,
75428 (long) comp_ctx->curr_func.catch_depth));
75429
75430 /* The directive prologue flag is cleared by default so that it is
75431 * unset for any recursive statement parsing. It is only "revived"
75432 * if a directive is detected. (We could also make directives only
75433 * allowed if 'allow_source_elem' was true.)
75434 */
75435 comp_ctx->curr_func.in_directive_prologue = 0;
75436
75437retry_parse:
75438
75439 DUK_DDD(DUK_DDDPRINT("try stmt parse, stmt_id=%ld, label_id=%ld, allow_source_elem=%ld, catch_depth=%ld",
75440 (long) stmt_id,
75441 (long) label_id,
75442 (long) allow_source_elem,
75443 (long) comp_ctx->curr_func.catch_depth));
75444
75445 /*
75446 * Detect iteration statements; if encountered, establish an
75447 * empty label.
75448 */
75449
75450 tok = comp_ctx->curr_token.t;
75451 if (tok == DUK_TOK_FOR || tok == DUK_TOK_DO || tok == DUK_TOK_WHILE || tok == DUK_TOK_SWITCH) {
75452 DUK_DDD(DUK_DDDPRINT("iteration/switch statement -> add empty label"));
75453
75454 label_id = duk__stmt_label_site(comp_ctx, label_id);
75455 duk__add_label(comp_ctx, DUK_HTHREAD_STRING_EMPTY_STRING(thr), pc_at_entry /*pc_label*/, label_id);
75456 }
75457
75458 /*
75459 * Main switch for statement / source element type.
75460 */
75461
75462 switch (comp_ctx->curr_token.t) {
75463 case DUK_TOK_FUNCTION: {
75464 /*
75465 * Function declaration, function expression, or (non-standard)
75466 * function statement.
75467 *
75468 * The E5 specification only allows function declarations at
75469 * the top level (in "source elements"). An ExpressionStatement
75470 * is explicitly not allowed to begin with a "function" keyword
75471 * (E5 Section 12.4). Hence any non-error semantics for such
75472 * non-top-level statements are non-standard. Duktape semantics
75473 * for function statements are modelled after V8, see
75474 * test-dev-func-decl-outside-top.js.
75475 */
75476 test_func_decl = allow_source_elem;
75477#if defined(DUK_USE_NONSTD_FUNC_STMT)
75478 /* Lenient: allow function declarations outside top level in both
75479 * strict and non-strict modes. However, don't allow labelled
75480 * function declarations in strict mode.
75481 */
75482 test_func_decl = test_func_decl || !comp_ctx->curr_func.is_strict || label_id < 0;
75483#endif /* DUK_USE_NONSTD_FUNC_STMT */
75484 /* Strict: never allow function declarations outside top level. */
75485 if (test_func_decl) {
75486 /* FunctionDeclaration: not strictly a statement but handled as such.
75487 *
75488 * O(depth^2) parse count for inner functions is handled by recording a
75489 * lexer offset on the first compilation pass, so that the function can
75490 * be efficiently skipped on the second pass. This is encapsulated into
75491 * duk__parse_func_like_fnum().
75492 */
75493
75494 duk_int_t fnum;
75495#if defined(DUK_USE_ASSERTIONS)
75496 duk_idx_t top_before;
75497#endif
75498
75499 DUK_DDD(DUK_DDDPRINT("function declaration statement"));
75500
75501#if defined(DUK_USE_ASSERTIONS)
75502 top_before = duk_get_top(thr);
75503#endif
75504
75505 duk__advance(comp_ctx); /* eat 'function' */
75507
75508 /* The value stack convention here is a bit odd: the function
75509 * name is only pushed on pass 1 (in_scanning), and is needed
75510 * to process function declarations.
75511 */
75512 if (comp_ctx->curr_func.in_scanning) {
75513 duk_uarridx_t n;
75514
75515#if defined(DUK_USE_ASSERTIONS)
75516 DUK_ASSERT(duk_get_top(thr) == top_before + 1);
75517#endif
75518 DUK_DDD(DUK_DDDPRINT("register function declaration %!T in pass 1, fnum %ld",
75519 duk_get_tval(thr, -1),
75520 (long) fnum));
75521 n = (duk_uarridx_t) duk_get_length(thr, comp_ctx->curr_func.decls_idx);
75522 /* funcname is at index -1 */
75523 duk_put_prop_index(thr, comp_ctx->curr_func.decls_idx, n);
75524 duk_push_int(thr, (duk_int_t) (DUK_DECL_TYPE_FUNC + (fnum << 8)));
75525 duk_put_prop_index(thr, comp_ctx->curr_func.decls_idx, n + 1);
75526 } else {
75527#if defined(DUK_USE_ASSERTIONS)
75528 DUK_ASSERT(duk_get_top(thr) == top_before);
75529#endif
75530 }
75531
75532 /* no statement value (unlike function expression) */
75533 stmt_flags = 0;
75534 break;
75535 } else {
75537 DUK_WO_NORETURN(return;);
75538 }
75539 break;
75540 }
75541 case DUK_TOK_LCURLY: {
75542 DUK_DDD(DUK_DDDPRINT("block statement"));
75543 duk__advance(comp_ctx);
75544 duk__parse_stmts(comp_ctx, 0 /*allow_source_elem*/, 0 /*expect_eof*/, 1 /*regexp_after*/);
75545 /* the DUK_TOK_RCURLY is eaten by duk__parse_stmts() */
75546 if (label_id >= 0) {
75547 duk__patch_jump_here(comp_ctx, pc_at_entry + 1); /* break jump */
75548 }
75549 stmt_flags = 0;
75550 break;
75551 }
75552 case DUK_TOK_CONST: {
75553 DUK_DDD(DUK_DDDPRINT("constant declaration statement"));
75554 duk__parse_var_stmt(comp_ctx, res, DUK__EXPR_FLAG_REQUIRE_INIT /*expr_flags*/);
75555 stmt_flags = DUK__HAS_TERM;
75556 break;
75557 }
75558 case DUK_TOK_VAR: {
75559 DUK_DDD(DUK_DDDPRINT("variable declaration statement"));
75560 duk__parse_var_stmt(comp_ctx, res, 0 /*expr_flags*/);
75561 stmt_flags = DUK__HAS_TERM;
75562 break;
75563 }
75564 case DUK_TOK_SEMICOLON: {
75565 /* empty statement with an explicit semicolon */
75566 DUK_DDD(DUK_DDDPRINT("empty statement"));
75567 stmt_flags = DUK__HAS_TERM;
75568 break;
75569 }
75570 case DUK_TOK_IF: {
75571 DUK_DDD(DUK_DDDPRINT("if statement"));
75572 duk__parse_if_stmt(comp_ctx, res);
75573 if (label_id >= 0) {
75574 duk__patch_jump_here(comp_ctx, pc_at_entry + 1); /* break jump */
75575 }
75576 stmt_flags = 0;
75577 break;
75578 }
75579 case DUK_TOK_DO: {
75580 /*
75581 * Do-while statement is mostly trivial, but there is special
75582 * handling for automatic semicolon handling (triggered by the
75583 * DUK__ALLOW_AUTO_SEMI_ALWAYS) flag related to a bug filed at:
75584 *
75585 * https://bugs.ecmascript.org/show_bug.cgi?id=8
75586 *
75587 * See doc/compiler.rst for details.
75588 */
75589 DUK_DDD(DUK_DDDPRINT("do statement"));
75590 DUK_ASSERT(label_id >= 0);
75592 duk__parse_do_stmt(comp_ctx, res, pc_at_entry);
75593 stmt_flags = DUK__HAS_TERM | DUK__ALLOW_AUTO_SEMI_ALWAYS; /* DUK__ALLOW_AUTO_SEMI_ALWAYS workaround */
75594 break;
75595 }
75596 case DUK_TOK_WHILE: {
75597 DUK_DDD(DUK_DDDPRINT("while statement"));
75598 DUK_ASSERT(label_id >= 0);
75600 duk__parse_while_stmt(comp_ctx, res, pc_at_entry);
75601 stmt_flags = 0;
75602 break;
75603 }
75604 case DUK_TOK_FOR: {
75605 /*
75606 * For/for-in statement is complicated to parse because
75607 * determining the statement type (three-part for vs. a
75608 * for-in) requires potential backtracking.
75609 *
75610 * See the helper for the messy stuff.
75611 */
75612 DUK_DDD(DUK_DDDPRINT("for/for-in statement"));
75613 DUK_ASSERT(label_id >= 0);
75615 duk__parse_for_stmt(comp_ctx, res, pc_at_entry);
75616 stmt_flags = 0;
75617 break;
75618 }
75619 case DUK_TOK_CONTINUE:
75620 case DUK_TOK_BREAK: {
75621 DUK_DDD(DUK_DDDPRINT("break/continue statement"));
75622 duk__parse_break_or_continue_stmt(comp_ctx, res);
75623 stmt_flags = DUK__HAS_TERM | DUK__IS_TERMINAL;
75624 break;
75625 }
75626 case DUK_TOK_RETURN: {
75627 DUK_DDD(DUK_DDDPRINT("return statement"));
75628 duk__parse_return_stmt(comp_ctx, res);
75629 stmt_flags = DUK__HAS_TERM | DUK__IS_TERMINAL;
75630 break;
75631 }
75632 case DUK_TOK_WITH: {
75633 DUK_DDD(DUK_DDDPRINT("with statement"));
75634 comp_ctx->curr_func.with_depth++;
75635 duk__parse_with_stmt(comp_ctx, res);
75636 if (label_id >= 0) {
75637 duk__patch_jump_here(comp_ctx, pc_at_entry + 1); /* break jump */
75638 }
75639 comp_ctx->curr_func.with_depth--;
75640 stmt_flags = 0;
75641 break;
75642 }
75643 case DUK_TOK_SWITCH: {
75644 /*
75645 * The switch statement is pretty messy to compile.
75646 * See the helper for details.
75647 */
75648 DUK_DDD(DUK_DDDPRINT("switch statement"));
75649 DUK_ASSERT(label_id >= 0);
75650 duk__update_label_flags(comp_ctx, label_id, DUK_LABEL_FLAG_ALLOW_BREAK); /* don't allow continue */
75651 duk__parse_switch_stmt(comp_ctx, res, pc_at_entry);
75652 stmt_flags = 0;
75653 break;
75654 }
75655 case DUK_TOK_THROW: {
75656 DUK_DDD(DUK_DDDPRINT("throw statement"));
75657 duk__parse_throw_stmt(comp_ctx, res);
75658 stmt_flags = DUK__HAS_TERM | DUK__IS_TERMINAL;
75659 break;
75660 }
75661 case DUK_TOK_TRY: {
75662 DUK_DDD(DUK_DDDPRINT("try statement"));
75663 duk__parse_try_stmt(comp_ctx, res);
75664 stmt_flags = 0;
75665 break;
75666 }
75667 case DUK_TOK_DEBUGGER: {
75668 duk__advance(comp_ctx);
75669#if defined(DUK_USE_DEBUGGER_SUPPORT)
75670 DUK_DDD(DUK_DDDPRINT("debugger statement: debugging enabled, emit debugger opcode"));
75672#else
75673 DUK_DDD(DUK_DDDPRINT("debugger statement: ignored"));
75674#endif
75675 stmt_flags = DUK__HAS_TERM;
75676 break;
75677 }
75678 default: {
75679 /*
75680 * Else, must be one of:
75681 * - ExpressionStatement, possibly a directive (String)
75682 * - LabelledStatement (Identifier followed by ':')
75683 *
75684 * Expressions beginning with 'function' keyword are covered by a case
75685 * above (such expressions are not allowed in standard E5 anyway).
75686 * Also expressions starting with '{' are interpreted as block
75687 * statements. See E5 Section 12.4.
75688 *
75689 * Directive detection is tricky; see E5 Section 14.1 on directive
75690 * prologue. A directive is an expression statement with a single
75691 * string literal and an explicit or automatic semicolon. Escape
75692 * characters are significant and no parens etc are allowed:
75693 *
75694 * 'use strict'; // valid 'use strict' directive
75695 * 'use\u0020strict'; // valid directive, not a 'use strict' directive
75696 * ('use strict'); // not a valid directive
75697 *
75698 * The expression is determined to consist of a single string literal
75699 * based on duk__expr_nud() and duk__expr_led() call counts. The string literal
75700 * of a 'use strict' directive is determined to lack any escapes based
75701 * num_escapes count from the lexer. Note that other directives may be
75702 * allowed to contain escapes, so a directive with escapes does not
75703 * terminate a directive prologue.
75704 *
75705 * We rely on the fact that the expression parser will not emit any
75706 * code for a single token expression. However, it will generate an
75707 * intermediate value which we will then successfully ignore.
75708 *
75709 * A similar approach is used for labels.
75710 */
75711
75712 duk_bool_t single_token;
75713
75714 DUK_DDD(DUK_DDDPRINT("expression statement"));
75715 duk__exprtop(comp_ctx, res, DUK__BP_FOR_EXPR /*rbp_flags*/);
75716
75717 single_token = (comp_ctx->curr_func.nud_count == 1 && /* one token */
75718 comp_ctx->curr_func.led_count == 0); /* no operators */
75719
75720 if (single_token && comp_ctx->prev_token.t == DUK_TOK_IDENTIFIER && comp_ctx->curr_token.t == DUK_TOK_COLON) {
75721 /*
75722 * Detected label
75723 */
75724
75725 duk_hstring *h_lab;
75726
75727 /* expected ival */
75728 DUK_ASSERT(res->t == DUK_IVAL_VAR);
75729 DUK_ASSERT(res->x1.t == DUK_ISPEC_VALUE);
75731 h_lab = comp_ctx->prev_token.str1;
75732 DUK_ASSERT(h_lab != NULL);
75733
75734 DUK_DDD(DUK_DDDPRINT("explicit label site for label '%!O'", (duk_heaphdr *) h_lab));
75735
75736 duk__advance(comp_ctx); /* eat colon */
75737
75738 label_id = duk__stmt_label_site(comp_ctx, label_id);
75739
75740 duk__add_label(comp_ctx, h_lab, pc_at_entry /*pc_label*/, label_id);
75741
75742 /* a statement following a label cannot be a source element
75743 * (a function declaration).
75744 */
75745 allow_source_elem = 0;
75746
75747 DUK_DDD(DUK_DDDPRINT("label handled, retry statement parsing"));
75748 goto retry_parse;
75749 }
75750
75751 stmt_flags = 0;
75752
75753 if (dir_prol_at_entry && /* still in prologue */
75754 single_token && /* single string token */
75755 comp_ctx->prev_token.t == DUK_TOK_STRING) {
75756 /*
75757 * Detected a directive
75758 */
75759 duk_hstring *h_dir;
75760
75761 /* expected ival */
75762 DUK_ASSERT(res->t == DUK_IVAL_PLAIN);
75763 DUK_ASSERT(res->x1.t == DUK_ISPEC_VALUE);
75765 h_dir = comp_ctx->prev_token.str1;
75766 DUK_ASSERT(h_dir != NULL);
75767
75768 DUK_DDD(DUK_DDDPRINT("potential directive: %!O", h_dir));
75769
75770 stmt_flags |= DUK__STILL_PROLOGUE;
75771
75772 /* Note: escaped characters differentiate directives */
75773
75774 if (comp_ctx->prev_token.num_escapes > 0) {
75775 DUK_DDD(DUK_DDDPRINT("directive contains escapes: valid directive "
75776 "but we ignore such directives"));
75777 } else {
75778 /*
75779 * The length comparisons are present to handle
75780 * strings like "use strict\u0000foo" as required.
75781 */
75782
75783 if (DUK_HSTRING_GET_BYTELEN(h_dir) == 10 &&
75784 DUK_STRCMP((const char *) DUK_HSTRING_GET_DATA(h_dir), "use strict") == 0) {
75785#if defined(DUK_USE_STRICT_DECL)
75786 DUK_DDD(DUK_DDDPRINT("use strict directive detected: strict flag %ld -> %ld",
75787 (long) comp_ctx->curr_func.is_strict,
75788 (long) 1));
75789 comp_ctx->curr_func.is_strict = 1;
75790#else
75791 DUK_DDD(DUK_DDDPRINT("use strict detected but strict declarations disabled, ignoring"));
75792#endif
75793 } else if (DUK_HSTRING_GET_BYTELEN(h_dir) == 14 &&
75794 DUK_STRCMP((const char *) DUK_HSTRING_GET_DATA(h_dir), "use duk notail") == 0) {
75795 DUK_DDD(DUK_DDDPRINT("use duk notail directive detected: notail flag %ld -> %ld",
75796 (long) comp_ctx->curr_func.is_notail,
75797 (long) 1));
75798 comp_ctx->curr_func.is_notail = 1;
75799 } else {
75800 DUK_DD(DUK_DDPRINT("unknown directive: '%!O', ignoring but not terminating "
75801 "directive prologue",
75802 (duk_hobject *) h_dir));
75803 }
75804 }
75805 } else {
75806 DUK_DDD(DUK_DDDPRINT("non-directive expression statement or no longer in prologue; "
75807 "prologue terminated if still active"));
75808 }
75809
75810 stmt_flags |= DUK__HAS_VAL | DUK__HAS_TERM;
75811 }
75812 } /* end switch (tok) */
75813
75814 /*
75815 * Statement value handling.
75816 *
75817 * Global code and eval code has an implicit return value
75818 * which comes from the last statement with a value
75819 * (technically a non-"empty" continuation, which is
75820 * different from an empty statement).
75821 *
75822 * Since we don't know whether a later statement will
75823 * override the value of the current statement, we need
75824 * to coerce the statement value to a register allocated
75825 * for implicit return values. In other cases we need
75826 * to coerce the statement value to a plain value to get
75827 * any side effects out (consider e.g. "foo.bar;").
75828 */
75829
75830 /* XXX: what about statements which leave a half-cooked value in 'res'
75831 * but have no stmt value? Any such statements?
75832 */
75833
75834 if (stmt_flags & DUK__HAS_VAL) {
75835 duk_regconst_t reg_stmt_value = comp_ctx->curr_func.reg_stmt_value;
75836 if (reg_stmt_value >= 0) {
75837 duk__ivalue_toforcedreg(comp_ctx, res, reg_stmt_value);
75838 } else {
75839 duk__ivalue_toplain_ignore(comp_ctx, res);
75840 }
75841 } else {
75842 ;
75843 }
75844
75845 /*
75846 * Statement terminator check, including automatic semicolon
75847 * handling. After this step, 'curr_tok' should be the first
75848 * token after a possible statement terminator.
75849 */
75850
75851 if (stmt_flags & DUK__HAS_TERM) {
75852 if (comp_ctx->curr_token.t == DUK_TOK_SEMICOLON) {
75853 DUK_DDD(DUK_DDDPRINT("explicit semicolon terminates statement"));
75854 duk__advance(comp_ctx);
75855 } else {
75856 if (comp_ctx->curr_token.allow_auto_semi) {
75857 DUK_DDD(DUK_DDDPRINT("automatic semicolon terminates statement"));
75858 } else if (stmt_flags & DUK__ALLOW_AUTO_SEMI_ALWAYS) {
75859 /* XXX: make this lenience dependent on flags or strictness? */
75860 DUK_DDD(DUK_DDDPRINT("automatic semicolon terminates statement (allowed for compatibility "
75861 "even though no lineterm present before next token)"));
75862 } else {
75864 DUK_WO_NORETURN(return;);
75865 }
75866 }
75867 } else {
75868 DUK_DDD(DUK_DDDPRINT("statement has no terminator"));
75869 }
75870
75871 /*
75872 * Directive prologue tracking.
75873 */
75874
75875 if (stmt_flags & DUK__STILL_PROLOGUE) {
75876 DUK_DDD(DUK_DDDPRINT("setting in_directive_prologue"));
75877 comp_ctx->curr_func.in_directive_prologue = 1;
75878 }
75879
75880 /*
75881 * Cleanups (all statement parsing flows through here).
75882 *
75883 * Pop label site and reset labels. Reset 'next temp' to value at
75884 * entry to reuse temps.
75885 */
75886
75887 if (label_id >= 0) {
75888 duk__emit_bc(comp_ctx, DUK_OP_ENDLABEL, (duk_regconst_t) label_id);
75889 }
75891 DUK__SETTEMP(comp_ctx, temp_at_entry);
75892
75893 duk__reset_labels_to_length(comp_ctx, labels_len_at_entry);
75894
75895 /* XXX: return indication of "terminalness" (e.g. a 'throw' is terminal) */
75896
75897 DUK__RECURSION_DECREASE(comp_ctx, thr);
75898}
75899
75900/*
75901 * Parse a statement list.
75902 *
75903 * Handles automatic semicolon insertion and implicit return value.
75904 *
75905 * Upon entry, 'curr_tok' should contain the first token of the first
75906 * statement (parsed in the "allow regexp literal" mode). Upon exit,
75907 * 'curr_tok' contains the token following the statement list terminator
75908 * (EOF or closing brace).
75909 */
75910
75912 duk_bool_t allow_source_elem,
75913 duk_bool_t expect_eof,
75914 duk_bool_t regexp_after) {
75915 duk_hthread *thr = comp_ctx->thr;
75916 duk_ivalue res_alloc;
75917 duk_ivalue *res = &res_alloc;
75918
75919 /* Setup state. Initial ivalue is 'undefined'. */
75920
75922
75923 /* XXX: 'res' setup can be moved to function body level; in fact, two 'res'
75924 * intermediate values suffice for parsing of each function. Nesting is needed
75925 * for nested functions (which may occur inside expressions).
75926 */
75927
75928 duk_memzero(&res_alloc, sizeof(res_alloc));
75929 res->t = DUK_IVAL_PLAIN;
75930 res->x1.t = DUK_ISPEC_VALUE;
75931 res->x1.valstack_idx = duk_get_top(thr);
75932 res->x2.valstack_idx = res->x1.valstack_idx + 1;
75933 duk_push_undefined(thr);
75934 duk_push_undefined(thr);
75935
75936 /* Parse statements until a closing token (EOF or '}') is found. */
75937
75938 for (;;) {
75939 /* Check whether statement list ends. */
75940
75941 if (expect_eof) {
75942 if (comp_ctx->curr_token.t == DUK_TOK_EOF) {
75943 break;
75944 }
75945 } else {
75946 if (comp_ctx->curr_token.t == DUK_TOK_RCURLY) {
75947 break;
75948 }
75949 }
75950
75951 /* Check statement type based on the first token type.
75952 *
75953 * Note: expression parsing helpers expect 'curr_tok' to
75954 * contain the first token of the expression upon entry.
75955 */
75956
75957 DUK_DDD(DUK_DDDPRINT("TOKEN %ld (non-whitespace, non-comment)", (long) comp_ctx->curr_token.t));
75958
75959 duk__parse_stmt(comp_ctx, res, allow_source_elem);
75960 }
75961
75962 /* RegExp is allowed / not allowed depending on context. For function
75963 * declarations RegExp is allowed because it follows a function
75964 * declaration statement and may appear as part of the next statement.
75965 * For function expressions RegExp is not allowed, and it's possible
75966 * to do something like '(function () {} / 123)'.
75967 */
75968 if (regexp_after) {
75969 comp_ctx->curr_func.allow_regexp_in_adv = 1;
75970 }
75971 duk__advance(comp_ctx);
75972
75973 /* Tear down state. */
75974
75975 duk_pop_2(thr);
75976}
75977
75978/*
75979 * Declaration binding instantiation conceptually happens when calling a
75980 * function; for us it essentially means that function prologue. The
75981 * conceptual process is described in E5 Section 10.5.
75982 *
75983 * We need to keep track of all encountered identifiers to (1) create an
75984 * identifier-to-register map ("varmap"); and (2) detect duplicate
75985 * declarations. Identifiers which are not bound to registers still need
75986 * to be tracked for detecting duplicates. Currently such identifiers
75987 * are put into the varmap with a 'null' value, which is later cleaned up.
75988 *
75989 * To support functions with a large number of variable and function
75990 * declarations, registers are not allocated beyond a certain limit;
75991 * after that limit, variables and functions need slow path access.
75992 * Arguments are currently always register bound, which imposes a hard
75993 * (and relatively small) argument count limit.
75994 *
75995 * Some bindings in E5 are not configurable (= deletable) and almost all
75996 * are mutable (writable). Exceptions are:
75997 *
75998 * - The 'arguments' binding, established only if no shadowing argument
75999 * or function declaration exists. We handle 'arguments' creation
76000 * and binding through an explicit slow path environment record.
76001 *
76002 * - The "name" binding for a named function expression. This is also
76003 * handled through an explicit slow path environment record.
76004 */
76005
76006/* XXX: add support for variables to not be register bound always, to
76007 * handle cases with a very large number of variables?
76008 */
76009
76011 duk_hthread *thr = comp_ctx->thr;
76012 duk_hstring *h_name;
76013 duk_bool_t configurable_bindings;
76014 duk_uarridx_t num_args;
76015 duk_uarridx_t num_decls;
76016 duk_regconst_t rc_name;
76017 duk_small_uint_t declvar_flags;
76018 duk_uarridx_t i;
76019#if defined(DUK_USE_ASSERTIONS)
76020 duk_idx_t entry_top;
76021#endif
76022
76023#if defined(DUK_USE_ASSERTIONS)
76024 entry_top = duk_get_top(thr);
76025#endif
76026
76027 /*
76028 * Preliminaries
76029 */
76030
76031 configurable_bindings = comp_ctx->curr_func.is_eval;
76032 DUK_DDD(DUK_DDDPRINT("configurable_bindings=%ld", (long) configurable_bindings));
76033
76034 /* varmap is already in comp_ctx->curr_func.varmap_idx */
76035
76036 /*
76037 * Function formal arguments, always bound to registers
76038 * (there's no support for shuffling them now).
76039 */
76040
76041 num_args = (duk_uarridx_t) duk_get_length(thr, comp_ctx->curr_func.argnames_idx);
76042 DUK_DDD(DUK_DDDPRINT("num_args=%ld", (long) num_args));
76043 /* XXX: check num_args */
76044
76045 for (i = 0; i < num_args; i++) {
76046 duk_get_prop_index(thr, comp_ctx->curr_func.argnames_idx, i);
76047 h_name = duk_known_hstring(thr, -1);
76048
76049 if (comp_ctx->curr_func.is_strict) {
76050 if (duk__hstring_is_eval_or_arguments(comp_ctx, h_name)) {
76051 DUK_DDD(DUK_DDDPRINT("arg named 'eval' or 'arguments' in strict mode -> SyntaxError"));
76052 goto error_argname;
76053 }
76054 duk_dup_top(thr);
76055 if (duk_has_prop(thr, comp_ctx->curr_func.varmap_idx)) {
76056 DUK_DDD(DUK_DDDPRINT("duplicate arg name in strict mode -> SyntaxError"));
76057 goto error_argname;
76058 }
76059
76060 /* Ensure argument name is not a reserved word in current
76061 * (final) strictness. Formal argument parsing may not
76062 * catch reserved names if strictness changes during
76063 * parsing.
76064 *
76065 * We only need to do this in strict mode because non-strict
76066 * keyword are always detected in formal argument parsing.
76067 */
76068
76070 goto error_argname;
76071 }
76072 }
76073
76074 /* overwrite any previous binding of the same name; the effect is
76075 * that last argument of a certain name wins.
76076 */
76077
76078 /* only functions can have arguments */
76079 DUK_ASSERT(comp_ctx->curr_func.is_function);
76080 duk_push_uarridx(thr, i); /* -> [ ... name index ] */
76081 duk_put_prop(thr, comp_ctx->curr_func.varmap_idx); /* -> [ ... ] */
76082
76083 /* no code needs to be emitted, the regs already have values */
76084 }
76085
76086 /* use temp_next for tracking register allocations */
76087 DUK__SETTEMP_CHECKMAX(comp_ctx, (duk_regconst_t) num_args);
76088
76089 /*
76090 * After arguments, allocate special registers (like shuffling temps)
76091 */
76092
76093 if (out_stmt_value_reg) {
76094 *out_stmt_value_reg = DUK__ALLOCTEMP(comp_ctx);
76095 }
76096 if (comp_ctx->curr_func.needs_shuffle) {
76097 duk_regconst_t shuffle_base = DUK__ALLOCTEMPS(comp_ctx, 3);
76098 comp_ctx->curr_func.shuffle1 = shuffle_base;
76099 comp_ctx->curr_func.shuffle2 = shuffle_base + 1;
76100 comp_ctx->curr_func.shuffle3 = shuffle_base + 2;
76101 DUK_D(DUK_DPRINT("shuffle registers needed by function, allocated: %ld %ld %ld",
76102 (long) comp_ctx->curr_func.shuffle1,
76103 (long) comp_ctx->curr_func.shuffle2,
76104 (long) comp_ctx->curr_func.shuffle3));
76105 }
76106 if (comp_ctx->curr_func.temp_next > 0x100) {
76107 DUK_D(DUK_DPRINT("not enough 8-bit regs: temp_next=%ld", (long) comp_ctx->curr_func.temp_next));
76108 goto error_outofregs;
76109 }
76110
76111 /*
76112 * Function declarations
76113 */
76114
76115 num_decls = (duk_uarridx_t) duk_get_length(thr, comp_ctx->curr_func.decls_idx);
76116 DUK_DDD(
76117 DUK_DDDPRINT("num_decls=%ld -> %!T", (long) num_decls, (duk_tval *) duk_get_tval(thr, comp_ctx->curr_func.decls_idx)));
76118 for (i = 0; i < num_decls; i += 2) {
76119 duk_int_t decl_type;
76120 duk_int_t fnum;
76121
76122 duk_get_prop_index(thr, comp_ctx->curr_func.decls_idx, i + 1); /* decl type */
76123 decl_type = duk_to_int(thr, -1);
76124 fnum = decl_type >> 8; /* XXX: macros */
76125 decl_type = decl_type & 0xff;
76126 duk_pop(thr);
76127
76128 if (decl_type != DUK_DECL_TYPE_FUNC) {
76129 continue;
76130 }
76131
76132 duk_get_prop_index(thr, comp_ctx->curr_func.decls_idx, i); /* decl name */
76133
76134 /* XXX: spilling */
76135 if (comp_ctx->curr_func.is_function) {
76136 duk_regconst_t reg_bind;
76137 duk_dup_top(thr);
76138 if (duk_has_prop(thr, comp_ctx->curr_func.varmap_idx)) {
76139 /* shadowed; update value */
76140 duk_dup_top(thr);
76141 duk_get_prop(thr, comp_ctx->curr_func.varmap_idx);
76142 reg_bind = duk_to_int(thr, -1); /* [ ... name reg_bind ] */
76143 duk__emit_a_bc(comp_ctx, DUK_OP_CLOSURE, reg_bind, (duk_regconst_t) fnum);
76144 } else {
76145 /* function: always register bound */
76146 reg_bind = DUK__ALLOCTEMP(comp_ctx);
76147 duk__emit_a_bc(comp_ctx, DUK_OP_CLOSURE, reg_bind, (duk_regconst_t) fnum);
76148 duk_push_int(thr, (duk_int_t) reg_bind);
76149 }
76150 } else {
76151 /* Function declaration for global/eval code is emitted even
76152 * for duplicates, because of E5 Section 10.5, step 5.e of
76153 * E5.1 (special behavior for variable bound to global object).
76154 *
76155 * DECLVAR will not re-declare a variable as such, but will
76156 * update the binding value.
76157 */
76158
76159 duk_regconst_t reg_temp = DUK__ALLOCTEMP(comp_ctx);
76160 duk_dup_top(thr);
76161 rc_name = duk__getconst(comp_ctx);
76162 duk_push_null(thr);
76163
76164 duk__emit_a_bc(comp_ctx, DUK_OP_CLOSURE, reg_temp, (duk_regconst_t) fnum);
76165
76167
76168 if (configurable_bindings) {
76169 declvar_flags |= DUK_PROPDESC_FLAG_CONFIGURABLE;
76170 }
76171
76172 duk__emit_a_b_c(comp_ctx,
76174 (duk_regconst_t) declvar_flags /*flags*/,
76175 rc_name /*name*/,
76176 reg_temp /*value*/);
76177
76178 DUK__SETTEMP(comp_ctx, reg_temp); /* forget temp */
76179 }
76180
76181 DUK_DDD(DUK_DDDPRINT("function declaration to varmap: %!T -> %!T",
76182 (duk_tval *) duk_get_tval(thr, -2),
76183 (duk_tval *) duk_get_tval(thr, -1)));
76184
76185#if defined(DUK_USE_FASTINT)
76187#endif
76188 duk_put_prop(thr, comp_ctx->curr_func.varmap_idx); /* [ ... name reg/null ] -> [ ... ] */
76189 }
76190
76191 /*
76192 * 'arguments' binding is special; if a shadowing argument or
76193 * function declaration exists, an arguments object will
76194 * definitely not be needed, regardless of whether the identifier
76195 * 'arguments' is referenced inside the function body.
76196 */
76197
76199 DUK_DDD(DUK_DDDPRINT("'arguments' is shadowed by argument or function declaration "
76200 "-> arguments object creation can be skipped"));
76201 comp_ctx->curr_func.is_arguments_shadowed = 1;
76202 }
76203
76204 /*
76205 * Variable declarations.
76206 *
76207 * Unlike function declarations, variable declaration values don't get
76208 * assigned on entry. If a binding of the same name already exists, just
76209 * ignore it silently.
76210 */
76211
76212 for (i = 0; i < num_decls; i += 2) {
76213 duk_int_t decl_type;
76214
76215 duk_get_prop_index(thr, comp_ctx->curr_func.decls_idx, i + 1); /* decl type */
76216 decl_type = duk_to_int(thr, -1);
76217 decl_type = decl_type & 0xff;
76218 duk_pop(thr);
76219
76220 if (decl_type != DUK_DECL_TYPE_VAR) {
76221 continue;
76222 }
76223
76224 duk_get_prop_index(thr, comp_ctx->curr_func.decls_idx, i); /* decl name */
76225
76226 if (duk_has_prop(thr, comp_ctx->curr_func.varmap_idx)) {
76227 /* shadowed, ignore */
76228 } else {
76229 duk_get_prop_index(thr, comp_ctx->curr_func.decls_idx, i); /* decl name */
76230 h_name = duk_known_hstring(thr, -1);
76231
76232 if (h_name == DUK_HTHREAD_STRING_LC_ARGUMENTS(thr) && !comp_ctx->curr_func.is_arguments_shadowed) {
76233 /* E5 Section steps 7-8 */
76234 DUK_DDD(DUK_DDDPRINT("'arguments' not shadowed by a function declaration, "
76235 "but appears as a variable declaration -> treat as "
76236 "a no-op for variable declaration purposes"));
76237 duk_pop(thr);
76238 continue;
76239 }
76240
76241 /* XXX: spilling */
76242 if (comp_ctx->curr_func.is_function) {
76243 duk_regconst_t reg_bind = DUK__ALLOCTEMP(comp_ctx);
76244 /* no need to init reg, it will be undefined on entry */
76245 duk_push_int(thr, (duk_int_t) reg_bind);
76246 } else {
76247 duk_dup_top(thr);
76248 rc_name = duk__getconst(comp_ctx);
76249 duk_push_null(thr);
76250
76252 if (configurable_bindings) {
76253 declvar_flags |= DUK_PROPDESC_FLAG_CONFIGURABLE;
76254 }
76255
76256 duk__emit_a_b_c(comp_ctx,
76258 (duk_regconst_t) declvar_flags /*flags*/,
76259 rc_name /*name*/,
76260 0 /*value*/);
76261 }
76262
76263 duk_put_prop(thr, comp_ctx->curr_func.varmap_idx); /* [ ... name reg/null ] -> [ ... ] */
76264 }
76265 }
76266
76267 /*
76268 * Wrap up
76269 */
76270
76271 DUK_DDD(DUK_DDDPRINT("varmap: %!T, is_arguments_shadowed=%ld",
76272 (duk_tval *) duk_get_tval(thr, comp_ctx->curr_func.varmap_idx),
76273 (long) comp_ctx->curr_func.is_arguments_shadowed));
76274
76275 DUK_ASSERT_TOP(thr, entry_top);
76276 return;
76277
76278error_outofregs:
76280 DUK_WO_NORETURN(return;);
76281
76282error_argname:
76284 DUK_WO_NORETURN(return;);
76285}
76286
76287/*
76288 * Parse a function-body-like expression (FunctionBody or Program
76289 * in E5 grammar) using a two-pass parse. The productions appear
76290 * in the following contexts:
76291 *
76292 * - function expression
76293 * - function statement
76294 * - function declaration
76295 * - getter in object literal
76296 * - setter in object literal
76297 * - global code
76298 * - eval code
76299 * - Function constructor body
76301 * This function only parses the statement list of the body; the argument
76302 * list and possible function name must be initialized by the caller.
76303 * For instance, for Function constructor, the argument names are originally
76304 * on the value stack. The parsing of statements ends either at an EOF or
76305 * a closing brace; this is controlled by an input flag.
76306 *
76307 * Note that there are many differences affecting parsing and even code
76308 * generation:
76309 *
76310 * - Global and eval code have an implicit return value generated
76311 * by the last statement; function code does not
76312 *
76313 * - Global code, eval code, and Function constructor body end in
76314 * an EOF, other bodies in a closing brace ('}')
76315 *
76316 * Upon entry, 'curr_tok' is ignored and the function will pull in the
76317 * first token on its own. Upon exit, 'curr_tok' is the terminating
76318 * token (EOF or closing brace).
76319 */
76320
76322 duk_bool_t expect_eof,
76323 duk_bool_t implicit_return_value,
76324 duk_bool_t regexp_after,
76325 duk_small_int_t expect_token) {
76326 duk_compiler_func *func;
76327 duk_hthread *thr;
76328 duk_regconst_t reg_stmt_value = -1;
76329 duk_lexer_point lex_pt;
76330 duk_regconst_t temp_first;
76331 duk_small_int_t compile_round = 1;
76332
76333 DUK_ASSERT(comp_ctx != NULL);
76334
76335 thr = comp_ctx->thr;
76336 DUK_ASSERT(thr != NULL);
76337
76338 func = &comp_ctx->curr_func;
76339 DUK_ASSERT(func != NULL);
76340
76341 DUK__RECURSION_INCREASE(comp_ctx, thr);
76342
76344
76345 /*
76346 * Store lexer position for a later rewind
76347 */
76348
76349 DUK_LEXER_GETPOINT(&comp_ctx->lex, &lex_pt);
76350
76351 /*
76352 * Program code (global and eval code) has an implicit return value
76353 * from the last statement value (e.g. eval("1; 2+3;") returns 3).
76354 * This is not the case with functions. If implicit statement return
76355 * value is requested, all statements are coerced to a register
76356 * allocated here, and used in the implicit return statement below.
76357 */
76358
76359 /* XXX: this is pointless here because pass 1 is throw-away */
76360 if (implicit_return_value) {
76361 reg_stmt_value = DUK__ALLOCTEMP(comp_ctx);
76362
76363 /* If an implicit return value is needed by caller, it must be
76364 * initialized to 'undefined' because we don't know whether any
76365 * non-empty (where "empty" is a continuation type, and different
76366 * from an empty statement) statements will be executed.
76367 *
76368 * However, since 1st pass is a throwaway one, no need to emit
76369 * it here.
76370 */
76371#if 0
76372 duk__emit_bc(comp_ctx,
76374 0);
76375#endif
76376 }
76377
76378 /*
76379 * First pass.
76380 *
76381 * Gather variable/function declarations needed for second pass.
76382 * Code generated is dummy and discarded.
76383 */
76384
76385 func->in_directive_prologue = 1;
76386 func->in_scanning = 1;
76387 func->may_direct_eval = 0;
76388 func->id_access_arguments = 0;
76389 func->id_access_slow = 0;
76390 func->id_access_slow_own = 0;
76391 func->reg_stmt_value = reg_stmt_value;
76392#if defined(DUK_USE_DEBUGGER_SUPPORT)
76393 func->min_line = DUK_INT_MAX;
76394 func->max_line = 0;
76395#endif
76396
76397 /* duk__parse_stmts() expects curr_tok to be set; parse in "allow
76398 * regexp literal" mode with current strictness.
76399 */
76400 if (expect_token >= 0) {
76401 /* Eating a left curly; regexp mode is allowed by left curly
76402 * based on duk__token_lbp[] automatically.
76403 */
76404 DUK_ASSERT(expect_token == DUK_TOK_LCURLY);
76406 duk__advance_expect(comp_ctx, expect_token);
76407 } else {
76408 /* Need to set curr_token.t because lexing regexp mode depends on current
76409 * token type. Zero value causes "allow regexp" mode.
76410 */
76411 comp_ctx->curr_token.t = 0;
76412 duk__advance(comp_ctx);
76413 }
76414
76415 DUK_DDD(DUK_DDDPRINT("begin 1st pass"));
76416 duk__parse_stmts(comp_ctx,
76417 1, /* allow source elements */
76418 expect_eof, /* expect EOF instead of } */
76419 regexp_after); /* regexp after */
76420 DUK_DDD(DUK_DDDPRINT("end 1st pass"));
76421
76422 /*
76423 * Second (and possibly third) pass.
76424 *
76425 * Generate actual code. In most cases the need for shuffle
76426 * registers is detected during pass 1, but in some corner cases
76427 * we'll only detect it during pass 2 and a third pass is then
76428 * needed (see GH-115).
76429 */
76430
76431 for (;;) {
76432 duk_bool_t needs_shuffle_before = comp_ctx->curr_func.needs_shuffle;
76433 compile_round++;
76434
76435 /*
76436 * Rewind lexer.
76437 *
76438 * duk__parse_stmts() expects curr_tok to be set; parse in "allow regexp
76439 * literal" mode with current strictness.
76440 *
76441 * curr_token line number info should be initialized for pass 2 before
76442 * generating prologue, to ensure prologue bytecode gets nice line numbers.
76443 */
76444
76445 DUK_DDD(DUK_DDDPRINT("rewind lexer"));
76446 DUK_LEXER_SETPOINT(&comp_ctx->lex, &lex_pt);
76447 comp_ctx->curr_token.t = 0; /* this is needed for regexp mode */
76448 comp_ctx->curr_token.start_line = 0; /* needed for line number tracking (becomes prev_token.start_line) */
76449 duk__advance(comp_ctx);
76450
76451 /*
76452 * Reset function state and perform register allocation, which creates
76453 * 'varmap' for second pass. Function prologue for variable declarations,
76454 * binding value initializations etc is emitted as a by-product.
76455 *
76456 * Strict mode restrictions for duplicate and invalid argument
76457 * names are checked here now that we know whether the function
76458 * is actually strict. See: test-dev-strict-mode-boundary.js.
76459 *
76460 * Inner functions are compiled during pass 1 and are not reset.
76461 */
76462
76463 duk__reset_func_for_pass2(comp_ctx);
76464 func->in_directive_prologue = 1;
76465 func->in_scanning = 0;
76466
76467 /* must be able to emit code, alloc consts, etc. */
76468
76469 duk__init_varmap_and_prologue_for_pass2(comp_ctx, (implicit_return_value ? &reg_stmt_value : NULL));
76470 func->reg_stmt_value = reg_stmt_value;
76471
76472 temp_first = DUK__GETTEMP(comp_ctx);
76473
76474 func->temp_first = temp_first;
76475 func->temp_next = temp_first;
76476 func->stmt_next = 0;
76477 func->label_next = 0;
76478
76479 /* XXX: init or assert catch depth etc -- all values */
76480 func->id_access_arguments = 0;
76481 func->id_access_slow = 0;
76482 func->id_access_slow_own = 0;
76483
76484 /*
76485 * Check function name validity now that we know strictness.
76486 * This only applies to function declarations and expressions,
76487 * not setter/getter name.
76488 *
76489 * See: test-dev-strict-mode-boundary.js
76490 */
76491
76492 if (func->is_function && !func->is_setget && func->h_name != NULL) {
76493 if (func->is_strict) {
76494 if (duk__hstring_is_eval_or_arguments(comp_ctx, func->h_name)) {
76495 DUK_DDD(DUK_DDDPRINT("func name is 'eval' or 'arguments' in strict mode"));
76496 goto error_funcname;
76497 }
76499 DUK_DDD(DUK_DDDPRINT("func name is a reserved word in strict mode"));
76500 goto error_funcname;
76501 }
76502 } else {
76505 DUK_DDD(DUK_DDDPRINT("func name is a reserved word in non-strict mode"));
76506 goto error_funcname;
76507 }
76508 }
76509 }
76510
76511 /*
76512 * Second pass parsing.
76513 */
76514
76515 if (implicit_return_value) {
76516 /* Default implicit return value. */
76517 duk__emit_bc(comp_ctx, DUK_OP_LDUNDEF, 0);
76518 }
76519
76520 DUK_DDD(DUK_DDDPRINT("begin 2nd pass"));
76521 duk__parse_stmts(comp_ctx,
76522 1, /* allow source elements */
76523 expect_eof, /* expect EOF instead of } */
76524 regexp_after); /* regexp after */
76525 DUK_DDD(DUK_DDDPRINT("end 2nd pass"));
76526
76528
76529 if (needs_shuffle_before == comp_ctx->curr_func.needs_shuffle) {
76530 /* Shuffle decision not changed. */
76531 break;
76532 }
76533 if (compile_round >= 3) {
76534 /* Should never happen but avoid infinite loop just in case. */
76535 DUK_D(DUK_DPRINT("more than 3 compile passes needed, should never happen"));
76536 DUK_ERROR_INTERNAL(thr);
76537 DUK_WO_NORETURN(return;);
76538 }
76539 DUK_D(DUK_DPRINT("need additional round to compile function, round now %d", (int) compile_round));
76540 }
76541
76542 /*
76543 * Emit a final RETURN.
76544 *
76545 * It would be nice to avoid emitting an unnecessary "return" opcode
76546 * if the current PC is not reachable. However, this cannot be reliably
76547 * detected; even if the previous instruction is an unconditional jump,
76548 * there may be a previous jump which jumps to current PC (which is the
76549 * case for iteration and conditional statements, for instance).
76550 */
76551
76552 /* XXX: request a "last statement is terminal" from duk__parse_stmt() and duk__parse_stmts();
76553 * we could avoid the last RETURN if we could ensure there is no way to get here
76554 * (directly or via a jump)
76555 */
76556
76557 DUK_ASSERT(comp_ctx->curr_func.catch_depth == 0);
76558 if (reg_stmt_value >= 0) {
76559 DUK_ASSERT(DUK__ISREG(reg_stmt_value));
76560 duk__emit_bc(comp_ctx, DUK_OP_RETREG, reg_stmt_value /*reg*/);
76561 } else {
76563 }
76564
76565 /*
76566 * Peephole optimize JUMP chains.
76567 */
76568
76570
76571 /*
76572 * comp_ctx->curr_func is now ready to be converted into an actual
76573 * function template.
76574 */
76575
76576 DUK__RECURSION_DECREASE(comp_ctx, thr);
76577 return;
76578
76579error_funcname:
76582}
76583
76584/*
76585 * Parse a function-like expression:
76586 *
76587 * - function expression
76588 * - function declaration
76589 * - function statement (non-standard)
76590 * - setter/getter
76591 *
76592 * Adds the function to comp_ctx->curr_func function table and returns the
76593 * function number.
76594 *
76595 * On entry, curr_token points to:
76596 *
76597 * - the token after 'function' for function expression/declaration/statement
76598 * - the token after 'set' or 'get' for setter/getter
76599 */
76600
76601/* Parse formals. */
76603 duk_hthread *thr = comp_ctx->thr;
76604 duk_bool_t first = 1;
76605 duk_uarridx_t n;
76606
76607 for (;;) {
76608 if (comp_ctx->curr_token.t == DUK_TOK_RPAREN) {
76609 break;
76610 }
76611
76612 if (first) {
76613 /* no comma */
76614 first = 0;
76615 } else {
76617 }
76618
76619 /* Note: when parsing a formal list in non-strict context, e.g.
76620 * "implements" is parsed as an identifier. When the function is
76621 * later detected to be strict, the argument list must be rechecked
76622 * against a larger set of reserved words (that of strict mode).
76623 * This is handled by duk__parse_func_body(). Here we recognize
76624 * whatever tokens are considered reserved in current strictness
76625 * (which is not always enough).
76626 */
76627
76628 if (comp_ctx->curr_token.t != DUK_TOK_IDENTIFIER) {
76630 DUK_WO_NORETURN(return;);
76631 }
76633 DUK_ASSERT(comp_ctx->curr_token.str1 != NULL);
76634 DUK_DDD(DUK_DDDPRINT("formal argument: %!O", (duk_heaphdr *) comp_ctx->curr_token.str1));
76635
76636 /* XXX: append primitive */
76637 duk_push_hstring(thr, comp_ctx->curr_token.str1);
76638 n = (duk_uarridx_t) duk_get_length(thr, comp_ctx->curr_func.argnames_idx);
76639 duk_put_prop_index(thr, comp_ctx->curr_func.argnames_idx, n);
76640
76641 duk__advance(comp_ctx); /* eat identifier */
76642 }
76643}
76644
76645/* Parse a function-like expression, assuming that 'comp_ctx->curr_func' is
76646 * correctly set up. Assumes that curr_token is just after 'function' (or
76647 * 'set'/'get' etc).
76648 */
76650 duk_hthread *thr = comp_ctx->thr;
76651 duk_token *tok;
76652 duk_bool_t no_advance;
76653
76654 DUK_ASSERT(comp_ctx->curr_func.num_formals == 0);
76655 DUK_ASSERT(comp_ctx->curr_func.is_function == 1);
76656 DUK_ASSERT(comp_ctx->curr_func.is_eval == 0);
76657 DUK_ASSERT(comp_ctx->curr_func.is_global == 0);
76658 DUK_ASSERT(comp_ctx->curr_func.is_setget == ((flags & DUK__FUNC_FLAG_GETSET) != 0));
76659
76661
76662 /*
76663 * Function name (if any)
76664 *
76665 * We don't check for prohibited names here, because we don't
76666 * yet know whether the function will be strict. Function body
76667 * parsing handles this retroactively.
76668 *
76669 * For function expressions and declarations function name must
76670 * be an Identifer (excludes reserved words). For setter/getter
76671 * it is a PropertyName which allows reserved words and also
76672 * strings and numbers (e.g. "{ get 1() { ... } }").
76673 *
76674 * Function parsing may start either from prev_token or curr_token
76675 * (object literal method definition uses prev_token for example).
76676 * This is dealt with for the initial token.
76677 */
76678
76679 no_advance = (flags & DUK__FUNC_FLAG_USE_PREVTOKEN);
76680 if (no_advance) {
76681 tok = &comp_ctx->prev_token;
76682 } else {
76683 tok = &comp_ctx->curr_token;
76684 }
76685
76686 if (flags & DUK__FUNC_FLAG_GETSET) {
76687 /* PropertyName -> IdentifierName | StringLiteral | NumericLiteral */
76688 if (tok->t_nores == DUK_TOK_IDENTIFIER || tok->t == DUK_TOK_STRING) {
76689 duk_push_hstring(thr, tok->str1); /* keep in valstack */
76690 } else if (tok->t == DUK_TOK_NUMBER) {
76691 duk_push_number(thr, tok->num);
76692 duk_to_string(thr, -1);
76693 } else {
76695 DUK_WO_NORETURN(return;);
76696 }
76697 comp_ctx->curr_func.h_name = duk_known_hstring(thr, -1); /* borrowed reference */
76698 } else {
76699 /* Function name is an Identifier (not IdentifierName), but we get
76700 * the raw name (not recognizing keywords) here and perform the name
76701 * checks only after pass 1.
76702 */
76703 if (tok->t_nores == DUK_TOK_IDENTIFIER) {
76704 duk_push_hstring(thr, tok->str1); /* keep in valstack */
76705 comp_ctx->curr_func.h_name = duk_known_hstring(thr, -1); /* borrowed reference */
76706 } else {
76707 /* valstack will be unbalanced, which is OK */
76708 DUK_ASSERT((flags & DUK__FUNC_FLAG_GETSET) == 0);
76709 DUK_ASSERT(comp_ctx->curr_func.h_name == NULL);
76710 no_advance = 1;
76711 if (flags & DUK__FUNC_FLAG_DECL) {
76713 DUK_WO_NORETURN(return;);
76714 }
76715 }
76716 }
76717
76718 DUK_DD(DUK_DDPRINT("function name: %!O", (duk_heaphdr *) comp_ctx->curr_func.h_name));
76719
76720 if (!no_advance) {
76721 duk__advance(comp_ctx);
76722 }
76723
76724 /*
76725 * Formal argument list
76726 *
76727 * We don't check for prohibited names or for duplicate argument
76728 * names here, becase we don't yet know whether the function will
76729 * be strict. Function body parsing handles this retroactively.
76730 */
76731
76733
76734 duk__parse_func_formals(comp_ctx);
76735
76736 DUK_ASSERT(comp_ctx->curr_token.t == DUK_TOK_RPAREN);
76737 duk__advance(comp_ctx);
76738
76739 /*
76740 * Parse function body
76741 */
76742
76743 duk__parse_func_body(comp_ctx,
76744 0, /* expect_eof */
76745 0, /* implicit_return_value */
76746 flags & DUK__FUNC_FLAG_DECL, /* regexp_after */
76747 DUK_TOK_LCURLY); /* expect_token */
76748
76749 /*
76750 * Convert duk_compiler_func to a function template and add it
76751 * to the parent function table.
76752 */
76753
76754 duk__convert_to_func_template(comp_ctx); /* -> [ ... func ] */
76755}
76756
76757/* Parse an inner function, adding the function template to the current function's
76758 * function table. Return a function number to be used by the outer function.
76759 *
76760 * Avoiding O(depth^2) inner function parsing is handled here. On the first pass,
76761 * compile and register the function normally into the 'funcs' array, also recording
76762 * a lexer point (offset/line) to the closing brace of the function. On the second
76763 * pass, skip the function and return the same 'fnum' as on the first pass by using
76764 * a running counter.
76765 *
76766 * An unfortunate side effect of this is that when parsing the inner function, almost
76767 * nothing is known of the outer function, i.e. the inner function's scope. We don't
76768 * need that information at the moment, but it would allow some optimizations if it
76769 * were used.
76770 */
76772 duk_hthread *thr = comp_ctx->thr;
76773 duk_compiler_func old_func;
76774 duk_idx_t entry_top;
76775 duk_int_t fnum;
76776
76777 /*
76778 * On second pass, skip the function.
76779 */
76780
76781 if (!comp_ctx->curr_func.in_scanning) {
76782 duk_lexer_point lex_pt;
76783
76784 fnum = comp_ctx->curr_func.fnum_next++;
76785 duk_get_prop_index(thr, comp_ctx->curr_func.funcs_idx, (duk_uarridx_t) (fnum * 3 + 1));
76786 lex_pt.offset = (duk_size_t) duk_to_uint(thr, -1);
76787 duk_pop(thr);
76788 duk_get_prop_index(thr, comp_ctx->curr_func.funcs_idx, (duk_uarridx_t) (fnum * 3 + 2));
76789 lex_pt.line = duk_to_int(thr, -1);
76790 duk_pop(thr);
76791
76792 DUK_DDD(
76793 DUK_DDDPRINT("second pass of an inner func, skip the function, reparse closing brace; lex offset=%ld, line=%ld",
76794 (long) lex_pt.offset,
76795 (long) lex_pt.line));
76796
76797 DUK_LEXER_SETPOINT(&comp_ctx->lex, &lex_pt);
76798 comp_ctx->curr_token.t = 0; /* this is needed for regexp mode */
76799 comp_ctx->curr_token.start_line = 0; /* needed for line number tracking (becomes prev_token.start_line) */
76800 duk__advance(comp_ctx);
76801
76802 /* RegExp is not allowed after a function expression, e.g. in
76803 * (function () {} / 123). A RegExp *is* allowed after a
76804 * function declaration!
76805 */
76806 if (flags & DUK__FUNC_FLAG_DECL) {
76807 comp_ctx->curr_func.allow_regexp_in_adv = 1;
76808 }
76810
76811 return fnum;
76812 }
76813
76814 /*
76815 * On first pass, perform actual parsing. Remember valstack top on entry
76816 * to restore it later, and switch to using a new function in comp_ctx.
76817 */
76818
76819 entry_top = duk_get_top(thr);
76820 DUK_DDD(DUK_DDDPRINT("before func: entry_top=%ld, curr_tok.start_offset=%ld",
76821 (long) entry_top,
76822 (long) comp_ctx->curr_token.start_offset));
76823
76824 duk_memcpy(&old_func, &comp_ctx->curr_func, sizeof(duk_compiler_func));
76825
76826 duk_memzero(&comp_ctx->curr_func, sizeof(duk_compiler_func));
76828 DUK_ASSERT(comp_ctx->curr_func.num_formals == 0);
76829
76830 /* inherit initial strictness from parent */
76831 comp_ctx->curr_func.is_strict = old_func.is_strict;
76832
76833 /* XXX: It might be better to just store the flags into the curr_func
76834 * struct and use them as is without this flag interpretation step
76835 * here.
76836 */
76837 DUK_ASSERT(comp_ctx->curr_func.is_notail == 0);
76838 comp_ctx->curr_func.is_function = 1;
76839 DUK_ASSERT(comp_ctx->curr_func.is_eval == 0);
76840 DUK_ASSERT(comp_ctx->curr_func.is_global == 0);
76841 comp_ctx->curr_func.is_setget = ((flags & DUK__FUNC_FLAG_GETSET) != 0);
76842 comp_ctx->curr_func.is_namebinding =
76844 DUK__FUNC_FLAG_DECL)); /* no name binding for: declarations, objlit getset, objlit method def */
76845 comp_ctx->curr_func.is_constructable =
76846 !(flags & (DUK__FUNC_FLAG_GETSET | DUK__FUNC_FLAG_METDEF)); /* not constructable: objlit getset, objlit method def */
76847
76848 /*
76849 * Parse inner function
76850 */
76851
76852 duk__parse_func_like_raw(comp_ctx, flags); /* pushes function template */
76853
76854 /* prev_token.start_offset points to the closing brace here; when skipping
76855 * we're going to reparse the closing brace to ensure semicolon insertion
76856 * etc work as expected.
76857 */
76858 DUK_DDD(DUK_DDDPRINT("after func: prev_tok.start_offset=%ld, curr_tok.start_offset=%ld",
76859 (long) comp_ctx->prev_token.start_offset,
76860 (long) comp_ctx->curr_token.start_offset));
76861 DUK_ASSERT(comp_ctx->lex.input[comp_ctx->prev_token.start_offset] == (duk_uint8_t) DUK_ASC_RCURLY);
76862
76863 /* XXX: append primitive */
76864 DUK_ASSERT(duk_get_length(thr, old_func.funcs_idx) == (duk_size_t) (old_func.fnum_next * 3));
76865 fnum = old_func.fnum_next++;
76866
76867 if (fnum > DUK__MAX_FUNCS) {
76869 DUK_WO_NORETURN(return 0;);
76870 }
76871
76872 /* array writes autoincrement length */
76873 (void) duk_put_prop_index(thr, old_func.funcs_idx, (duk_uarridx_t) (fnum * 3));
76874 duk_push_size_t(thr, comp_ctx->prev_token.start_offset);
76875 (void) duk_put_prop_index(thr, old_func.funcs_idx, (duk_uarridx_t) (fnum * 3 + 1));
76876 duk_push_int(thr, comp_ctx->prev_token.start_line);
76877 (void) duk_put_prop_index(thr, old_func.funcs_idx, (duk_uarridx_t) (fnum * 3 + 2));
76878
76879 /*
76880 * Cleanup: restore original function, restore valstack state.
76881 *
76882 * Function declaration handling needs the function name to be pushed
76883 * on the value stack.
76884 */
76885
76886 if (flags & DUK__FUNC_FLAG_PUSHNAME_PASS1) {
76887 DUK_ASSERT(comp_ctx->curr_func.h_name != NULL);
76888 duk_push_hstring(thr, comp_ctx->curr_func.h_name);
76889 duk_replace(thr, entry_top);
76890 duk_set_top(thr, entry_top + 1);
76891 } else {
76892 duk_set_top(thr, entry_top);
76893 }
76894 duk_memcpy((void *) &comp_ctx->curr_func, (void *) &old_func, sizeof(duk_compiler_func));
76895
76896 return fnum;
76897}
76898
76899/*
76900 * Compile input string into an executable function template without
76901 * arguments.
76902 *
76903 * The string is parsed as the "Program" production of ECMAScript E5.
76904 * Compilation context can be either global code or eval code (see E5
76905 * Sections 14 and 15.1.2.1).
76906 *
76907 * Input stack: [ ... filename ]
76908 * Output stack: [ ... func_template ]
76909 */
76910
76911/* XXX: source code property */
76912
76914 duk_hstring *h_filename;
76915 duk__compiler_stkstate *comp_stk;
76916 duk_compiler_ctx *comp_ctx;
76917 duk_lexer_point *lex_pt;
76918 duk_compiler_func *func;
76919 duk_idx_t entry_top;
76920 duk_bool_t is_strict;
76921 duk_bool_t is_eval;
76922 duk_bool_t is_funcexpr;
76923 duk_small_uint_t flags;
76924
76925 DUK_ASSERT(thr != NULL);
76926 DUK_ASSERT(udata != NULL);
76927
76928 /*
76929 * Arguments check
76930 */
76931
76932 entry_top = duk_get_top(thr);
76933 DUK_ASSERT(entry_top >= 1);
76934
76935 comp_stk = (duk__compiler_stkstate *) udata;
76936 comp_ctx = &comp_stk->comp_ctx_alloc;
76937 lex_pt = &comp_stk->lex_pt_alloc;
76938 DUK_ASSERT(comp_ctx != NULL);
76939 DUK_ASSERT(lex_pt != NULL);
76940
76941 flags = comp_stk->flags;
76942 is_eval = (flags & DUK_COMPILE_EVAL ? 1 : 0);
76943 is_strict = (flags & DUK_COMPILE_STRICT ? 1 : 0);
76944 is_funcexpr = (flags & DUK_COMPILE_FUNCEXPR ? 1 : 0);
76945
76946 h_filename = duk_get_hstring(thr, -1); /* may be undefined */
76947
76948 /*
76949 * Init compiler and lexer contexts
76950 */
76951
76952 func = &comp_ctx->curr_func;
76953#if defined(DUK_USE_EXPLICIT_NULL_INIT)
76954 comp_ctx->thr = NULL;
76955 comp_ctx->h_filename = NULL;
76956 comp_ctx->prev_token.str1 = NULL;
76957 comp_ctx->prev_token.str2 = NULL;
76958 comp_ctx->curr_token.str1 = NULL;
76959 comp_ctx->curr_token.str2 = NULL;
76960#endif
76961
76963
76964 duk_push_dynamic_buffer(thr, 0); /* entry_top + 0 */
76965 duk_push_undefined(thr); /* entry_top + 1 */
76966 duk_push_undefined(thr); /* entry_top + 2 */
76967 duk_push_undefined(thr); /* entry_top + 3 */
76968 duk_push_undefined(thr); /* entry_top + 4 */
76969
76970 comp_ctx->thr = thr;
76971 comp_ctx->h_filename = h_filename;
76972 comp_ctx->tok11_idx = entry_top + 1;
76973 comp_ctx->tok12_idx = entry_top + 2;
76974 comp_ctx->tok21_idx = entry_top + 3;
76975 comp_ctx->tok22_idx = entry_top + 4;
76977
76978 /* comp_ctx->lex has been pre-initialized by caller: it has been
76979 * zeroed and input/input_length has been set.
76980 */
76981 comp_ctx->lex.thr = thr;
76982 /* comp_ctx->lex.input and comp_ctx->lex.input_length filled by caller */
76983 comp_ctx->lex.slot1_idx = comp_ctx->tok11_idx;
76984 comp_ctx->lex.slot2_idx = comp_ctx->tok12_idx;
76985 comp_ctx->lex.buf_idx = entry_top + 0;
76986 comp_ctx->lex.buf = (duk_hbuffer_dynamic *) duk_known_hbuffer(thr, entry_top + 0);
76989
76990 lex_pt->offset = 0;
76991 lex_pt->line = 1;
76992 DUK_LEXER_SETPOINT(&comp_ctx->lex, lex_pt); /* fills window */
76993 comp_ctx->curr_token.start_line = 0; /* needed for line number tracking (becomes prev_token.start_line) */
76994
76995 /*
76996 * Initialize function state for a zero-argument function
76997 */
76998
77000 DUK_ASSERT(func->num_formals == 0);
77001
77002 if (is_funcexpr) {
77003 /* Name will be filled from function expression, not by caller.
77004 * This case is used by Function constructor and duk_compile()
77005 * API with the DUK_COMPILE_FUNCTION option.
77006 */
77007 DUK_ASSERT(func->h_name == NULL);
77008 } else {
77010 func->h_name = duk_get_hstring(thr, -1);
77011 }
77012
77013 /*
77014 * Parse a function body or a function-like expression, depending
77015 * on flags.
77016 */
77017
77018 DUK_ASSERT(func->is_setget == 0);
77019 func->is_strict = (duk_uint8_t) is_strict;
77020 DUK_ASSERT(func->is_notail == 0);
77021
77022 if (is_funcexpr) {
77023 func->is_function = 1;
77024 DUK_ASSERT(func->is_eval == 0);
77025 DUK_ASSERT(func->is_global == 0);
77026 func->is_namebinding = 1;
77027 func->is_constructable = 1;
77028
77029 duk__advance(comp_ctx); /* init 'curr_token' */
77031 (void) duk__parse_func_like_raw(comp_ctx, 0 /*flags*/);
77032 } else {
77033 DUK_ASSERT(func->is_function == 0);
77034 DUK_ASSERT(is_eval == 0 || is_eval == 1);
77035 func->is_eval = (duk_uint8_t) is_eval;
77036 func->is_global = (duk_uint8_t) !is_eval;
77037 DUK_ASSERT(func->is_namebinding == 0);
77038 DUK_ASSERT(func->is_constructable == 0);
77039
77040 duk__parse_func_body(comp_ctx,
77041 1, /* expect_eof */
77042 1, /* implicit_return_value */
77043 1, /* regexp_after (does not matter) */
77044 -1); /* expect_token */
77045 }
77046
77047 /*
77048 * Convert duk_compiler_func to a function template
77049 */
77050
77052
77053 /*
77054 * Wrapping duk_safe_call() will mangle the stack, just return stack top
77055 */
77056
77057 /* [ ... filename (temps) func ] */
77058
77059 return 1;
77060}
77061
77062DUK_INTERNAL void duk_js_compile(duk_hthread *thr, const duk_uint8_t *src_buffer, duk_size_t src_length, duk_small_uint_t flags) {
77063 duk__compiler_stkstate comp_stk;
77064 duk_compiler_ctx *prev_ctx;
77065 duk_ret_t safe_rc;
77066
77067 DUK_ASSERT(thr != NULL);
77068 DUK_ASSERT(src_buffer != NULL);
77069
77070 /* preinitialize lexer state partially */
77071 duk_memzero(&comp_stk, sizeof(comp_stk));
77072 comp_stk.flags = flags;
77074 comp_stk.comp_ctx_alloc.lex.input = src_buffer;
77075 comp_stk.comp_ctx_alloc.lex.input_length = src_length;
77076 comp_stk.comp_ctx_alloc.lex.flags = flags; /* Forward flags directly for now. */
77077
77078 /* [ ... filename ] */
77079
77080 prev_ctx = thr->compile_ctx;
77081 thr->compile_ctx = &comp_stk.comp_ctx_alloc; /* for duk_error_augment.c */
77082 safe_rc = duk_safe_call(thr, duk__js_compile_raw, (void *) &comp_stk /*udata*/, 1 /*nargs*/, 1 /*nrets*/);
77083 thr->compile_ctx = prev_ctx; /* must restore reliably before returning */
77084
77085 if (safe_rc != DUK_EXEC_SUCCESS) {
77086 DUK_D(DUK_DPRINT("compilation failed: %!T", duk_get_tval(thr, -1)));
77087 (void) duk_throw(thr);
77088 DUK_WO_NORETURN(return;);
77089 }
77090
77091 /* [ ... template ] */
77092}
77093
77094/* automatic undefs */
77095#undef DUK__ALLOCTEMP
77096#undef DUK__ALLOCTEMPS
77097#undef DUK__ALLOW_AUTO_SEMI_ALWAYS
77098#undef DUK__BC_INITIAL_INSTS
77099#undef DUK__BP_ADDITIVE
77100#undef DUK__BP_ASSIGNMENT
77101#undef DUK__BP_BAND
77102#undef DUK__BP_BOR
77103#undef DUK__BP_BXOR
77104#undef DUK__BP_CALL
77105#undef DUK__BP_CLOSING
77106#undef DUK__BP_COMMA
77107#undef DUK__BP_CONDITIONAL
77108#undef DUK__BP_EOF
77109#undef DUK__BP_EQUALITY
77110#undef DUK__BP_EXPONENTIATION
77111#undef DUK__BP_FOR_EXPR
77112#undef DUK__BP_INVALID
77113#undef DUK__BP_LAND
77114#undef DUK__BP_LOR
77115#undef DUK__BP_MEMBER
77116#undef DUK__BP_MULTIPLICATIVE
77117#undef DUK__BP_POSTFIX
77118#undef DUK__BP_RELATIONAL
77119#undef DUK__BP_SHIFT
77120#undef DUK__COMPILE_ENTRY_SLOTS
77121#undef DUK__CONST_MARKER
77122#undef DUK__DUMP_ISPEC
77123#undef DUK__DUMP_IVALUE
77124#undef DUK__EMIT_FLAG_A_IS_SOURCE
77125#undef DUK__EMIT_FLAG_BC_REGCONST
77126#undef DUK__EMIT_FLAG_B_IS_TARGET
77127#undef DUK__EMIT_FLAG_C_IS_TARGET
77128#undef DUK__EMIT_FLAG_NO_SHUFFLE_A
77129#undef DUK__EMIT_FLAG_NO_SHUFFLE_B
77130#undef DUK__EMIT_FLAG_NO_SHUFFLE_C
77131#undef DUK__EMIT_FLAG_RESERVE_JUMPSLOT
77132#undef DUK__EXPR_FLAG_ALLOW_EMPTY
77133#undef DUK__EXPR_FLAG_REJECT_IN
77134#undef DUK__EXPR_FLAG_REQUIRE_INIT
77135#undef DUK__EXPR_RBP_MASK
77136#undef DUK__FUNCTION_BODY_REQUIRE_SLOTS
77137#undef DUK__FUNCTION_INIT_REQUIRE_SLOTS
77138#undef DUK__FUNC_FLAG_DECL
77139#undef DUK__FUNC_FLAG_GETSET
77140#undef DUK__FUNC_FLAG_METDEF
77141#undef DUK__FUNC_FLAG_PUSHNAME_PASS1
77142#undef DUK__FUNC_FLAG_USE_PREVTOKEN
77143#undef DUK__GETCONST_MAX_CONSTS_CHECK
77144#undef DUK__GETTEMP
77145#undef DUK__HAS_TERM
77146#undef DUK__HAS_VAL
77147#undef DUK__ISCONST
77148#undef DUK__ISREG
77149#undef DUK__ISREG_NOTTEMP
77150#undef DUK__ISREG_TEMP
77151#undef DUK__IS_TERMINAL
77152#undef DUK__IVAL_FLAG_ALLOW_CONST
77153#undef DUK__IVAL_FLAG_REQUIRE_SHORT
77154#undef DUK__IVAL_FLAG_REQUIRE_TEMP
77155#undef DUK__MAX_ARRAY_INIT_VALUES
77156#undef DUK__MAX_CONSTS
77157#undef DUK__MAX_FUNCS
77158#undef DUK__MAX_OBJECT_INIT_PAIRS
77159#undef DUK__MAX_TEMPS
77160#undef DUK__MK_LBP
77161#undef DUK__MK_LBP_FLAGS
77162#undef DUK__OBJ_LIT_KEY_GET
77163#undef DUK__OBJ_LIT_KEY_PLAIN
77164#undef DUK__OBJ_LIT_KEY_SET
77165#undef DUK__PARSE_EXPR_SLOTS
77166#undef DUK__PARSE_STATEMENTS_SLOTS
77167#undef DUK__RECURSION_DECREASE
77168#undef DUK__RECURSION_INCREASE
77169#undef DUK__REMOVECONST
77170#undef DUK__SETTEMP
77171#undef DUK__SETTEMP_CHECKMAX
77172#undef DUK__STILL_PROLOGUE
77173#undef DUK__TOKEN_LBP_BP_MASK
77174#undef DUK__TOKEN_LBP_FLAG_NO_REGEXP
77175#undef DUK__TOKEN_LBP_FLAG_TERMINATES
77176#undef DUK__TOKEN_LBP_FLAG_UNUSED
77177#undef DUK__TOKEN_LBP_GET_BP
77178/*
77179 * ECMAScript bytecode executor.
77180 */
77181
77182/* #include duk_internal.h -> already included */
77183
77184/*
77185 * Local declarations.
77186 */
77187
77189
77190/*
77191 * Misc helpers.
77192 */
77193
77194/* Replace value stack top to value at 'tv_ptr'. Optimize for
77195 * performance by only applying the net refcount change.
77196 */
77197#define DUK__REPLACE_TO_TVPTR(thr, tv_ptr) \
77198 do { \
77199 duk_hthread *duk__thr; \
77200 duk_tval *duk__tvsrc; \
77201 duk_tval *duk__tvdst; \
77202 duk_tval duk__tvtmp; \
77203 duk__thr = (thr); \
77204 duk__tvsrc = DUK_GET_TVAL_NEGIDX(duk__thr, -1); \
77205 duk__tvdst = (tv_ptr); \
77206 DUK_TVAL_SET_TVAL(&duk__tvtmp, duk__tvdst); \
77207 DUK_TVAL_SET_TVAL(duk__tvdst, duk__tvsrc); \
77208 DUK_TVAL_SET_UNDEFINED(duk__tvsrc); /* value stack init policy */ \
77209 duk__thr->valstack_top = duk__tvsrc; \
77210 DUK_TVAL_DECREF(duk__thr, &duk__tvtmp); \
77211 } while (0)
77212
77213/* XXX: candidate of being an internal shared API call */
77214#if 0 /* unused */
77215DUK_LOCAL void duk__push_tvals_incref_only(duk_hthread *thr, duk_tval *tv_src, duk_small_uint_fast_t count) {
77216 duk_tval *tv_dst;
77217 duk_size_t copy_size;
77218 duk_size_t i;
77219
77220 tv_dst = thr->valstack_top;
77221 copy_size = sizeof(duk_tval) * count;
77222 duk_memcpy((void *) tv_dst, (const void *) tv_src, copy_size);
77223 for (i = 0; i < count; i++) {
77224 DUK_TVAL_INCREF(thr, tv_dst);
77225 tv_dst++;
77226 }
77227 thr->valstack_top = tv_dst;
77228}
77229#endif
77231/*
77232 * Arithmetic, binary, and logical helpers.
77233 *
77234 * Note: there is no opcode for logical AND or logical OR; this is on
77235 * purpose, because the evalution order semantics for them make such
77236 * opcodes pretty pointless: short circuiting means they are most
77237 * comfortably implemented as jumps. However, a logical NOT opcode
77238 * is useful.
77239 *
77240 * Note: careful with duk_tval pointers here: they are potentially
77241 * invalidated by any DECREF and almost any API call. It's still
77242 * preferable to work without making a copy but that's not always
77243 * possible.
77244 */
77245
77247 return (duk_double_t) duk_js_arith_mod((double) d1, (double) d2);
77248}
77249
77250#if defined(DUK_USE_ES7_EXP_OPERATOR)
77252 return (duk_double_t) duk_js_arith_pow((double) d1, (double) d2);
77253}
77254#endif
77255
77257 duk_tval *tv_x,
77258 duk_tval *tv_y,
77259 duk_small_uint_fast_t idx_z) {
77260 /*
77261 * Addition operator is different from other arithmetic
77262 * operations in that it also provides string concatenation.
77263 * Hence it is implemented separately.
77264 *
77265 * There is a fast path for number addition. Other cases go
77266 * through potentially multiple coercions as described in the
77267 * E5 specification. It may be possible to reduce the number
77268 * of coercions, but this must be done carefully to preserve
77269 * the exact semantics.
77270 *
77271 * E5 Section 11.6.1.
77272 *
77273 * Custom types also have special behavior implemented here.
77274 */
77275
77277
77278 DUK_ASSERT(thr != NULL);
77279 DUK_ASSERT(tv_x != NULL); /* may be reg or const */
77280 DUK_ASSERT(tv_y != NULL); /* may be reg or const */
77281 DUK_ASSERT_DISABLE(idx_z >= 0); /* unsigned */
77282 DUK_ASSERT((duk_uint_t) idx_z < (duk_uint_t) duk_get_top(thr));
77283
77284 /*
77285 * Fast paths
77286 */
77287
77288#if defined(DUK_USE_FASTINT)
77289 if (DUK_TVAL_IS_FASTINT(tv_x) && DUK_TVAL_IS_FASTINT(tv_y)) {
77290 duk_int64_t v1, v2, v3;
77291 duk_int32_t v3_hi;
77292 duk_tval *tv_z;
77293
77294 /* Input values are signed 48-bit so we can detect overflow
77295 * reliably from high bits or just a comparison.
77296 */
77297
77298 v1 = DUK_TVAL_GET_FASTINT(tv_x);
77299 v2 = DUK_TVAL_GET_FASTINT(tv_y);
77300 v3 = v1 + v2;
77301 v3_hi = (duk_int32_t) (v3 >> 32);
77302 if (DUK_LIKELY(v3_hi >= DUK_I64_CONSTANT(-0x8000) && v3_hi <= DUK_I64_CONSTANT(0x7fff))) {
77303 tv_z = thr->valstack_bottom + idx_z;
77304 DUK_TVAL_SET_FASTINT_UPDREF(thr, tv_z, v3); /* side effects */
77305 return;
77306 } else {
77307 /* overflow, fall through */
77308 ;
77309 }
77310 }
77311#endif /* DUK_USE_FASTINT */
77312
77313 if (DUK_TVAL_IS_NUMBER(tv_x) && DUK_TVAL_IS_NUMBER(tv_y)) {
77314#if !defined(DUK_USE_EXEC_PREFER_SIZE)
77315 duk_tval *tv_z;
77316#endif
77317
77318 du.d = DUK_TVAL_GET_NUMBER(tv_x) + DUK_TVAL_GET_NUMBER(tv_y);
77319#if defined(DUK_USE_EXEC_PREFER_SIZE)
77320 duk_push_number(thr, du.d); /* will NaN normalize result */
77321 duk_replace(thr, (duk_idx_t) idx_z);
77322#else /* DUK_USE_EXEC_PREFER_SIZE */
77325 tv_z = thr->valstack_bottom + idx_z;
77326 DUK_TVAL_SET_NUMBER_UPDREF(thr, tv_z, du.d); /* side effects */
77327#endif /* DUK_USE_EXEC_PREFER_SIZE */
77328 return;
77329 }
77330
77331 /*
77332 * Slow path: potentially requires function calls for coercion
77333 */
77334
77335 duk_push_tval(thr, tv_x);
77336 duk_push_tval(thr, tv_y);
77337 duk_to_primitive(thr, -2, DUK_HINT_NONE); /* side effects -> don't use tv_x, tv_y after */
77339
77340 /* Since Duktape 2.x plain buffers are treated like ArrayBuffer. */
77341 if (duk_is_string(thr, -2) || duk_is_string(thr, -1)) {
77342 /* Symbols shouldn't technically be handled here, but should
77343 * go into the default ToNumber() coercion path instead and
77344 * fail there with a TypeError. However, there's a ToString()
77345 * in duk_concat_2() which also fails with TypeError so no
77346 * explicit check is needed.
77347 */
77348 duk_concat_2(thr); /* [... s1 s2] -> [... s1+s2] */
77349 } else {
77350 duk_double_t d1, d2;
77351
77352 d1 = duk_to_number_m2(thr);
77353 d2 = duk_to_number_m1(thr);
77354 DUK_ASSERT(duk_is_number(thr, -2));
77355 DUK_ASSERT(duk_is_number(thr, -1));
77358
77359 du.d = d1 + d2;
77360 duk_pop_2_unsafe(thr);
77361 duk_push_number(thr, du.d); /* will NaN normalize result */
77362 }
77363 duk_replace(thr, (duk_idx_t) idx_z); /* side effects */
77364}
77365
77367 duk_tval *tv_x,
77368 duk_tval *tv_y,
77369 duk_uint_fast_t idx_z,
77370 duk_small_uint_fast_t opcode) {
77371 /*
77372 * Arithmetic operations other than '+' have number-only semantics
77373 * and are implemented here. The separate switch-case here means a
77374 * "double dispatch" of the arithmetic opcode, but saves code space.
77375 *
77376 * E5 Sections 11.5, 11.5.1, 11.5.2, 11.5.3, 11.6, 11.6.1, 11.6.2, 11.6.3.
77377 */
77378
77379 duk_double_t d1, d2;
77381 duk_small_uint_fast_t opcode_shifted;
77382#if defined(DUK_USE_FASTINT) || !defined(DUK_USE_EXEC_PREFER_SIZE)
77383 duk_tval *tv_z;
77384#endif
77385
77386 DUK_ASSERT(thr != NULL);
77387 DUK_ASSERT(tv_x != NULL); /* may be reg or const */
77388 DUK_ASSERT(tv_y != NULL); /* may be reg or const */
77389 DUK_ASSERT_DISABLE(idx_z >= 0); /* unsigned */
77390 DUK_ASSERT((duk_uint_t) idx_z < (duk_uint_t) duk_get_top(thr));
77391
77392 opcode_shifted = opcode >> 2; /* Get base opcode without reg/const modifiers. */
77393
77394#if defined(DUK_USE_FASTINT)
77395 if (DUK_TVAL_IS_FASTINT(tv_x) && DUK_TVAL_IS_FASTINT(tv_y)) {
77396 duk_int64_t v1, v2, v3;
77397 duk_int32_t v3_hi;
77398
77399 v1 = DUK_TVAL_GET_FASTINT(tv_x);
77400 v2 = DUK_TVAL_GET_FASTINT(tv_y);
77401
77402 switch (opcode_shifted) {
77403 case DUK_OP_SUB >> 2: {
77404 v3 = v1 - v2;
77405 break;
77406 }
77407 case DUK_OP_MUL >> 2: {
77408 /* Must ensure result is 64-bit (no overflow); a
77409 * simple and sufficient fast path is to allow only
77410 * 32-bit inputs. Avoid zero inputs to avoid
77411 * negative zero issues (-1 * 0 = -0, for instance).
77412 */
77413 if (v1 >= DUK_I64_CONSTANT(-0x80000000) && v1 <= DUK_I64_CONSTANT(0x7fffffff) && v1 != 0 &&
77414 v2 >= DUK_I64_CONSTANT(-0x80000000) && v2 <= DUK_I64_CONSTANT(0x7fffffff) && v2 != 0) {
77415 v3 = v1 * v2;
77416 } else {
77417 goto skip_fastint;
77418 }
77419 break;
77420 }
77421 case DUK_OP_DIV >> 2: {
77422 /* Don't allow a zero divisor. Fast path check by
77423 * "verifying" with multiplication. Also avoid zero
77424 * dividend to avoid negative zero issues (0 / -1 = -0
77425 * for instance).
77426 */
77427 if (v1 == 0 || v2 == 0) {
77428 goto skip_fastint;
77429 }
77430 v3 = v1 / v2;
77431 if (v3 * v2 != v1) {
77432 goto skip_fastint;
77433 }
77434 break;
77435 }
77436 case DUK_OP_MOD >> 2: {
77437 /* Don't allow a zero divisor. Restrict both v1 and
77438 * v2 to positive values to avoid compiler specific
77439 * behavior.
77440 */
77441 if (v1 < 1 || v2 < 1) {
77442 goto skip_fastint;
77443 }
77444 v3 = v1 % v2;
77445 DUK_ASSERT(v3 >= 0);
77446 DUK_ASSERT(v3 < v2);
77447 DUK_ASSERT(v1 - (v1 / v2) * v2 == v3);
77448 break;
77449 }
77450 default: {
77451 /* Possible with DUK_OP_EXP. */
77452 goto skip_fastint;
77453 }
77454 }
77455
77456 v3_hi = (duk_int32_t) (v3 >> 32);
77457 if (DUK_LIKELY(v3_hi >= DUK_I64_CONSTANT(-0x8000) && v3_hi <= DUK_I64_CONSTANT(0x7fff))) {
77458 tv_z = thr->valstack_bottom + idx_z;
77459 DUK_TVAL_SET_FASTINT_UPDREF(thr, tv_z, v3); /* side effects */
77460 return;
77461 }
77462 /* fall through if overflow etc */
77463 }
77464skip_fastint:
77465#endif /* DUK_USE_FASTINT */
77466
77467 if (DUK_TVAL_IS_NUMBER(tv_x) && DUK_TVAL_IS_NUMBER(tv_y)) {
77468 /* fast path */
77469 d1 = DUK_TVAL_GET_NUMBER(tv_x);
77470 d2 = DUK_TVAL_GET_NUMBER(tv_y);
77471 } else {
77472 duk_push_tval(thr, tv_x);
77473 duk_push_tval(thr, tv_y);
77474 d1 = duk_to_number_m2(thr); /* side effects */
77475 d2 = duk_to_number_m1(thr);
77476 DUK_ASSERT(duk_is_number(thr, -2));
77477 DUK_ASSERT(duk_is_number(thr, -1));
77480 duk_pop_2_unsafe(thr);
77481 }
77482
77483 switch (opcode_shifted) {
77484 case DUK_OP_SUB >> 2: {
77485 du.d = d1 - d2;
77486 break;
77487 }
77488 case DUK_OP_MUL >> 2: {
77489 du.d = d1 * d2;
77490 break;
77491 }
77492 case DUK_OP_DIV >> 2: {
77493 /* Division-by-zero is undefined behavior, so
77494 * rely on a helper.
77495 */
77496 du.d = duk_double_div(d1, d2);
77497 break;
77498 }
77499 case DUK_OP_MOD >> 2: {
77500 du.d = duk__compute_mod(d1, d2);
77501 break;
77502 }
77503#if defined(DUK_USE_ES7_EXP_OPERATOR)
77504 case DUK_OP_EXP >> 2: {
77505 du.d = duk__compute_exp(d1, d2);
77506 break;
77508#endif
77509 default: {
77511 du.d = DUK_DOUBLE_NAN; /* should not happen */
77512 break;
77513 }
77514 }
77515
77516#if defined(DUK_USE_EXEC_PREFER_SIZE)
77517 duk_push_number(thr, du.d); /* will NaN normalize result */
77518 duk_replace(thr, (duk_idx_t) idx_z);
77519#else /* DUK_USE_EXEC_PREFER_SIZE */
77520 /* important to use normalized NaN with 8-byte tagged types */
77523 tv_z = thr->valstack_bottom + idx_z;
77524 DUK_TVAL_SET_NUMBER_UPDREF(thr, tv_z, du.d); /* side effects */
77525#endif /* DUK_USE_EXEC_PREFER_SIZE */
77526}
77527
77529 duk_tval *tv_x,
77530 duk_tval *tv_y,
77532 duk_small_uint_fast_t opcode) {
77533 /*
77534 * Binary bitwise operations use different coercions (ToInt32, ToUint32)
77535 * depending on the operation. We coerce the arguments first using
77536 * ToInt32(), and then cast to an 32-bit value if necessary. Note that
77537 * such casts must be correct even if there is no native 32-bit type
77538 * (e.g., duk_int32_t and duk_uint32_t are 64-bit).
77539 *
77540 * E5 Sections 11.10, 11.7.1, 11.7.2, 11.7.3
77541 */
77542
77543 duk_int32_t i1, i2, i3;
77544 duk_uint32_t u1, u2, u3;
77545#if defined(DUK_USE_FASTINT)
77546 duk_int64_t fi3;
77547#else
77548 duk_double_t d3;
77549#endif
77550 duk_small_uint_fast_t opcode_shifted;
77551#if defined(DUK_USE_FASTINT) || !defined(DUK_USE_EXEC_PREFER_SIZE)
77552 duk_tval *tv_z;
77553#endif
77554
77555 DUK_ASSERT(thr != NULL);
77556 DUK_ASSERT(tv_x != NULL); /* may be reg or const */
77557 DUK_ASSERT(tv_y != NULL); /* may be reg or const */
77558 DUK_ASSERT_DISABLE(idx_z >= 0); /* unsigned */
77559 DUK_ASSERT((duk_uint_t) idx_z < (duk_uint_t) duk_get_top(thr));
77560
77561 opcode_shifted = opcode >> 2; /* Get base opcode without reg/const modifiers. */
77562
77563#if defined(DUK_USE_FASTINT)
77564 if (DUK_TVAL_IS_FASTINT(tv_x) && DUK_TVAL_IS_FASTINT(tv_y)) {
77565 i1 = (duk_int32_t) DUK_TVAL_GET_FASTINT_I32(tv_x);
77566 i2 = (duk_int32_t) DUK_TVAL_GET_FASTINT_I32(tv_y);
77567 } else
77568#endif /* DUK_USE_FASTINT */
77569 {
77570 duk_push_tval(thr, tv_x);
77571 duk_push_tval(thr, tv_y);
77572 i1 = duk_to_int32(thr, -2);
77573 i2 = duk_to_int32(thr, -1);
77574 duk_pop_2_unsafe(thr);
77575 }
77576
77577 switch (opcode_shifted) {
77578 case DUK_OP_BAND >> 2: {
77579 i3 = i1 & i2;
77580 break;
77581 }
77582 case DUK_OP_BOR >> 2: {
77583 i3 = i1 | i2;
77584 break;
77585 }
77586 case DUK_OP_BXOR >> 2: {
77587 i3 = i1 ^ i2;
77588 break;
77589 }
77590 case DUK_OP_BASL >> 2: {
77591 /* Signed shift, named "arithmetic" (asl) because the result
77592 * is signed, e.g. 4294967295 << 1 -> -2. Note that result
77593 * must be masked.
77594 */
77595
77596 u2 = ((duk_uint32_t) i2) & 0xffffffffUL;
77597 i3 = (duk_int32_t) (((duk_uint32_t) i1) << (u2 & 0x1fUL)); /* E5 Section 11.7.1, steps 7 and 8 */
77598 i3 = i3 & ((duk_int32_t) 0xffffffffUL); /* Note: left shift, should mask */
77599 break;
77600 }
77601 case DUK_OP_BASR >> 2: {
77602 /* signed shift */
77603
77604 u2 = ((duk_uint32_t) i2) & 0xffffffffUL;
77605 i3 = i1 >> (u2 & 0x1fUL); /* E5 Section 11.7.2, steps 7 and 8 */
77606 break;
77607 }
77608 case DUK_OP_BLSR >> 2: {
77609 /* unsigned shift */
77610
77611 u1 = ((duk_uint32_t) i1) & 0xffffffffUL;
77612 u2 = ((duk_uint32_t) i2) & 0xffffffffUL;
77613
77614 /* special result value handling */
77615 u3 = u1 >> (u2 & 0x1fUL); /* E5 Section 11.7.2, steps 7 and 8 */
77616#if defined(DUK_USE_FASTINT)
77617 fi3 = (duk_int64_t) u3;
77618 goto fastint_result_set;
77619#else
77620 d3 = (duk_double_t) u3;
77621 goto result_set;
77622#endif
77623 }
77624 default: {
77626 i3 = 0; /* should not happen */
77627 break;
77628 }
77629 }
77630
77631#if defined(DUK_USE_FASTINT)
77632 /* Result is always fastint compatible. */
77633 /* XXX: Set 32-bit result (but must then handle signed and
77634 * unsigned results separately).
77635 */
77636 fi3 = (duk_int64_t) i3;
77637
77638fastint_result_set:
77639 tv_z = thr->valstack_bottom + idx_z;
77640 DUK_TVAL_SET_FASTINT_UPDREF(thr, tv_z, fi3); /* side effects */
77641#else /* DUK_USE_FASTINT */
77642 d3 = (duk_double_t) i3;
77643
77644result_set:
77645 DUK_ASSERT(!DUK_ISNAN(d3)); /* 'd3' is never NaN, so no need to normalize */
77646 DUK_ASSERT_DOUBLE_IS_NORMALIZED(d3); /* always normalized */
77647
77648#if defined(DUK_USE_EXEC_PREFER_SIZE)
77649 duk_push_number(thr, d3); /* would NaN normalize result, but unnecessary */
77650 duk_replace(thr, (duk_idx_t) idx_z);
77651#else /* DUK_USE_EXEC_PREFER_SIZE */
77652 tv_z = thr->valstack_bottom + idx_z;
77653 DUK_TVAL_SET_NUMBER_UPDREF(thr, tv_z, d3); /* side effects */
77654#endif /* DUK_USE_EXEC_PREFER_SIZE */
77655#endif /* DUK_USE_FASTINT */
77656}
77657
77658/* In-place unary operation. */
77660 duk_uint_fast_t idx_src,
77661 duk_uint_fast_t idx_dst,
77662 duk_small_uint_fast_t opcode) {
77663 /*
77664 * Arithmetic operations other than '+' have number-only semantics
77665 * and are implemented here. The separate switch-case here means a
77666 * "double dispatch" of the arithmetic opcode, but saves code space.
77667 *
77668 * E5 Sections 11.5, 11.5.1, 11.5.2, 11.5.3, 11.6, 11.6.1, 11.6.2, 11.6.3.
77669 */
77670
77671 duk_tval *tv;
77672 duk_double_t d1;
77674
77675 DUK_ASSERT(thr != NULL);
77676 DUK_ASSERT(opcode == DUK_OP_UNM || opcode == DUK_OP_UNP);
77677 DUK_ASSERT_DISABLE(idx_src >= 0);
77678 DUK_ASSERT_DISABLE(idx_dst >= 0);
77679
77680 tv = DUK_GET_TVAL_POSIDX(thr, (duk_idx_t) idx_src);
77681
77682#if defined(DUK_USE_FASTINT)
77683 if (DUK_TVAL_IS_FASTINT(tv)) {
77684 duk_int64_t v1, v2;
77685
77686 v1 = DUK_TVAL_GET_FASTINT(tv);
77687 if (opcode == DUK_OP_UNM) {
77688 /* The smallest fastint is no longer 48-bit when
77689 * negated. Positive zero becames negative zero
77690 * (cannot be represented) when negated.
77691 */
77692 if (DUK_LIKELY(v1 != DUK_FASTINT_MIN && v1 != 0)) {
77693 v2 = -v1;
77694 tv = DUK_GET_TVAL_POSIDX(thr, (duk_idx_t) idx_dst);
77695 DUK_TVAL_SET_FASTINT_UPDREF(thr, tv, v2);
77696 return;
77697 }
77698 } else {
77699 /* ToNumber() for a fastint is a no-op. */
77700 DUK_ASSERT(opcode == DUK_OP_UNP);
77701 v2 = v1;
77702 tv = DUK_GET_TVAL_POSIDX(thr, (duk_idx_t) idx_dst);
77703 DUK_TVAL_SET_FASTINT_UPDREF(thr, tv, v2);
77704 return;
77705 }
77706 /* fall through if overflow etc */
77707 }
77708#endif /* DUK_USE_FASTINT */
77709
77710 if (DUK_TVAL_IS_NUMBER(tv)) {
77711 d1 = DUK_TVAL_GET_NUMBER(tv);
77712 } else {
77713 d1 = duk_to_number_tval(thr, tv); /* side effects */
77714 }
77715
77716 if (opcode == DUK_OP_UNP) {
77717 /* ToNumber() for a double is a no-op, but unary plus is
77718 * used to force a fastint check so do that here.
77719 */
77720 du.d = d1;
77722#if defined(DUK_USE_FASTINT)
77723 tv = DUK_GET_TVAL_POSIDX(thr, (duk_idx_t) idx_dst);
77724 DUK_TVAL_SET_NUMBER_CHKFAST_UPDREF(thr, tv, du.d); /* always 'fast', i.e. inlined */
77725 return;
77726#endif
77727 } else {
77728 DUK_ASSERT(opcode == DUK_OP_UNM);
77729 du.d = -d1;
77730 DUK_DBLUNION_NORMALIZE_NAN_CHECK(&du); /* mandatory if du.d is a NaN */
77732 }
77733
77734 /* XXX: size optimize: push+replace? */
77735 tv = DUK_GET_TVAL_POSIDX(thr, (duk_idx_t) idx_dst);
77736 DUK_TVAL_SET_NUMBER_UPDREF(thr, tv, du.d);
77737}
77738
77740 /*
77741 * E5 Section 11.4.8
77742 */
77743
77744 duk_tval *tv;
77745 duk_int32_t i1, i2;
77746
77747 DUK_ASSERT(thr != NULL);
77748 DUK_ASSERT_DISABLE(idx_src >= 0);
77749 DUK_ASSERT_DISABLE(idx_dst >= 0);
77750 DUK_ASSERT((duk_uint_t) idx_src < (duk_uint_t) duk_get_top(thr));
77752
77753 tv = DUK_GET_TVAL_POSIDX(thr, (duk_idx_t) idx_src);
77754
77755#if defined(DUK_USE_FASTINT)
77756 if (DUK_TVAL_IS_FASTINT(tv)) {
77757 i1 = (duk_int32_t) DUK_TVAL_GET_FASTINT_I32(tv);
77758 } else
77759#endif /* DUK_USE_FASTINT */
77760 {
77761 duk_push_tval(thr, tv);
77762 i1 = duk_to_int32(thr, -1); /* side effects */
77763 duk_pop_unsafe(thr);
77764 }
77765
77766 /* Result is always fastint compatible. */
77767 i2 = ~i1;
77768 tv = DUK_GET_TVAL_POSIDX(thr, (duk_idx_t) idx_dst);
77769 DUK_TVAL_SET_I32_UPDREF(thr, tv, i2); /* side effects */
77770}
77771
77773 /*
77774 * E5 Section 11.4.9
77775 */
77776
77777 duk_tval *tv;
77778 duk_bool_t res;
77780 DUK_ASSERT(thr != NULL);
77781 DUK_ASSERT_DISABLE(idx_src >= 0);
77782 DUK_ASSERT_DISABLE(idx_dst >= 0);
77783 DUK_ASSERT((duk_uint_t) idx_src < (duk_uint_t) duk_get_top(thr));
77784 DUK_ASSERT((duk_uint_t) idx_dst < (duk_uint_t) duk_get_top(thr));
77785
77786 /* ToBoolean() does not require any operations with side effects so
77787 * we can do it efficiently. For footprint it would be better to use
77788 * duk_js_toboolean() and then push+replace to the result slot.
77789 */
77790 tv = DUK_GET_TVAL_POSIDX(thr, (duk_idx_t) idx_src);
77791 res = duk_js_toboolean(tv); /* does not modify 'tv' */
77792 DUK_ASSERT(res == 0 || res == 1);
77793 res ^= 1;
77794 tv = DUK_GET_TVAL_POSIDX(thr, (duk_idx_t) idx_dst);
77795 /* XXX: size optimize: push+replace? */
77796 DUK_TVAL_SET_BOOLEAN_UPDREF(thr, tv, res); /* side effects */
77797}
77798
77799/* XXX: size optimized variant */
77801 duk_tval *tv_dst,
77802 duk_tval *tv_src,
77803 duk_small_uint_t op) {
77804 duk_double_t x, y, z;
77805
77806 /* Two lowest bits of opcode are used to distinguish
77807 * variants. Bit 0 = inc(0)/dec(1), bit 1 = pre(0)/post(1).
77808 */
77809 DUK_ASSERT((DUK_OP_PREINCR & 0x03) == 0x00);
77810 DUK_ASSERT((DUK_OP_PREDECR & 0x03) == 0x01);
77811 DUK_ASSERT((DUK_OP_POSTINCR & 0x03) == 0x02);
77812 DUK_ASSERT((DUK_OP_POSTDECR & 0x03) == 0x03);
77813
77814#if defined(DUK_USE_FASTINT)
77815 if (DUK_TVAL_IS_FASTINT(tv_src)) {
77816 duk_int64_t x_fi, y_fi, z_fi;
77817 x_fi = DUK_TVAL_GET_FASTINT(tv_src);
77818 if (op & 0x01) {
77819 if (DUK_UNLIKELY(x_fi == DUK_FASTINT_MIN)) {
77820 goto skip_fastint;
77821 }
77822 y_fi = x_fi - 1;
77823 } else {
77824 if (DUK_UNLIKELY(x_fi == DUK_FASTINT_MAX)) {
77825 goto skip_fastint;
77826 }
77827 y_fi = x_fi + 1;
77828 }
77829
77830 DUK_TVAL_SET_FASTINT(tv_src, y_fi); /* no need for refcount update */
77831
77832 z_fi = (op & 0x02) ? x_fi : y_fi;
77833 DUK_TVAL_SET_FASTINT_UPDREF(thr, tv_dst, z_fi); /* side effects */
77834 return;
77835 }
77836skip_fastint:
77837#endif
77838 if (DUK_TVAL_IS_NUMBER(tv_src)) {
77839 /* Fast path for the case where the register
77840 * is a number (e.g. loop counter).
77841 */
77842
77843 x = DUK_TVAL_GET_NUMBER(tv_src);
77844 if (op & 0x01) {
77845 y = x - 1.0;
77846 } else {
77847 y = x + 1.0;
77848 }
77849
77850 DUK_TVAL_SET_NUMBER(tv_src, y); /* no need for refcount update */
77851 } else {
77852 /* Preserve duk_tval pointer(s) across a potential valstack
77853 * resize by converting them into offsets temporarily.
77854 */
77855 duk_idx_t bc;
77856 duk_size_t off_dst;
77857
77858 off_dst = (duk_size_t) ((duk_uint8_t *) tv_dst - (duk_uint8_t *) thr->valstack_bottom);
77859 bc = (duk_idx_t) (tv_src - thr->valstack_bottom); /* XXX: pass index explicitly? */
77860 tv_src = NULL; /* no longer referenced */
77861
77862 x = duk_to_number(thr, bc);
77863 if (op & 0x01) {
77864 y = x - 1.0;
77865 } else {
77866 y = x + 1.0;
77867 }
77868
77869 duk_push_number(thr, y);
77870 duk_replace(thr, bc);
77871
77872 tv_dst = (duk_tval *) (void *) (((duk_uint8_t *) thr->valstack_bottom) + off_dst);
77873 }
77874
77875 z = (op & 0x02) ? x : y;
77876 DUK_TVAL_SET_NUMBER_UPDREF(thr, tv_dst, z); /* side effects */
77877}
77878
77880 duk_small_uint_t idx_dst,
77881 duk_tval *tv_id,
77883 duk_small_uint_t is_strict) {
77884 duk_activation *act;
77885 duk_double_t x, y;
77886 duk_hstring *name;
77887
77888 /* XXX: The pre/post inc/dec for an identifier lookup is
77889 * missing the important fast path where the identifier
77890 * has a storage location e.g. in a scope object so that
77891 * it can be updated in-place. In particular, the case
77892 * where the identifier has a storage location AND the
77893 * previous value is a number should be optimized because
77894 * it's side effect free.
77895 */
77896
77897 /* Two lowest bits of opcode are used to distinguish
77898 * variants. Bit 0 = inc(0)/dec(1), bit 1 = pre(0)/post(1).
77899 */
77900 DUK_ASSERT((DUK_OP_PREINCV & 0x03) == 0x00);
77901 DUK_ASSERT((DUK_OP_PREDECV & 0x03) == 0x01);
77902 DUK_ASSERT((DUK_OP_POSTINCV & 0x03) == 0x02);
77903 DUK_ASSERT((DUK_OP_POSTDECV & 0x03) == 0x03);
77904
77906 name = DUK_TVAL_GET_STRING(tv_id);
77907 DUK_ASSERT(name != NULL);
77908 act = thr->callstack_curr;
77909 (void) duk_js_getvar_activation(thr, act, name, 1 /*throw*/); /* -> [ ... val this ] */
77910
77911 /* XXX: Fastint fast path would be useful here. Also fastints
77912 * now lose their fastint status in current handling which is
77913 * not intuitive.
77914 */
77915
77916 x = duk_to_number_m2(thr);
77917 if (op & 0x01) {
77918 y = x - 1.0;
77919 } else {
77920 y = x + 1.0;
77921 }
77922
77923 /* [... x this] */
77924
77925 if (op & 0x02) {
77926 duk_push_number(thr, y); /* -> [ ... x this y ] */
77927 DUK_ASSERT(act == thr->callstack_curr);
77928 duk_js_putvar_activation(thr, act, name, DUK_GET_TVAL_NEGIDX(thr, -1), is_strict);
77929 duk_pop_2_unsafe(thr); /* -> [ ... x ] */
77930 } else {
77931 duk_pop_2_unsafe(thr); /* -> [ ... ] */
77932 duk_push_number(thr, y); /* -> [ ... y ] */
77933 DUK_ASSERT(act == thr->callstack_curr);
77934 duk_js_putvar_activation(thr, act, name, DUK_GET_TVAL_NEGIDX(thr, -1), is_strict);
77936
77937#if defined(DUK_USE_EXEC_PREFER_SIZE)
77938 duk_replace(thr, (duk_idx_t) idx_dst);
77939#else /* DUK_USE_EXEC_PREFER_SIZE */
77941#endif /* DUK_USE_EXEC_PREFER_SIZE */
77942}
77943
77944/*
77945 * Longjmp and other control flow transfer for the bytecode executor.
77946 *
77947 * The longjmp handler can handle all longjmp types: error, yield, and
77948 * resume (pseudotypes are never actually thrown).
77949 *
77950 * Error policy for longjmp: should not ordinarily throw errors; if errors
77951 * occur (e.g. due to out-of-memory) they bubble outwards rather than being
77952 * handled recursively.
77953 */
77954
77955#define DUK__LONGJMP_RESTART 0 /* state updated, restart bytecode execution */
77956#define DUK__LONGJMP_RETHROW 1 /* exit bytecode executor by rethrowing an error to caller */
77957
77958#define DUK__RETHAND_RESTART 0 /* state updated, restart bytecode execution */
77959#define DUK__RETHAND_FINISHED 1 /* exit bytecode execution with return value */
77960
77961/* XXX: optimize reconfig valstack operations so that resize, clamp, and setting
77962 * top are combined into one pass.
77963 */
77964
77965/* Reconfigure value stack for return to an ECMAScript function at
77966 * callstack top (caller unwinds).
77967 */
77969 duk_activation *act;
77970 duk_hcompfunc *h_func;
77971 duk_idx_t clamp_top;
77972
77973 DUK_ASSERT(thr != NULL);
77974 act = thr->callstack_curr;
77975 DUK_ASSERT(act != NULL);
77976 DUK_ASSERT(DUK_ACT_GET_FUNC(act) != NULL);
77978
77979 /* Clamp so that values at 'clamp_top' and above are wiped and won't
77980 * retain reachable garbage. Then extend to 'nregs' because we're
77981 * returning to an ECMAScript function.
77982 */
77983
77984 h_func = (duk_hcompfunc *) DUK_ACT_GET_FUNC(act);
77985
77986 thr->valstack_bottom = (duk_tval *) (void *) ((duk_uint8_t *) thr->valstack + act->bottom_byteoff);
77988 clamp_top =
77989 (duk_idx_t) ((act->retval_byteoff - act->bottom_byteoff + sizeof(duk_tval)) / sizeof(duk_tval)); /* +1 = one retval */
77990 duk_set_top_and_wipe(thr, h_func->nregs, clamp_top);
77991
77992 DUK_ASSERT((duk_uint8_t *) thr->valstack_end >= (duk_uint8_t *) thr->valstack + act->reserve_byteoff);
77993 thr->valstack_end = (duk_tval *) (void *) ((duk_uint8_t *) thr->valstack + act->reserve_byteoff);
77994
77995 /* XXX: a best effort shrink check would be OK here */
77996}
77997
77998/* Reconfigure value stack for an ECMAScript catcher. Use topmost catcher
77999 * in 'act'.
78000 */
78002 duk_catcher *cat;
78003 duk_hcompfunc *h_func;
78004 duk_size_t idx_bottom;
78005 duk_idx_t clamp_top;
78006
78007 DUK_ASSERT(thr != NULL);
78008 DUK_ASSERT(act != NULL);
78009 DUK_ASSERT(DUK_ACT_GET_FUNC(act) != NULL);
78011 cat = act->cat;
78012 DUK_ASSERT(cat != NULL);
78013
78014 h_func = (duk_hcompfunc *) DUK_ACT_GET_FUNC(act);
78015
78016 thr->valstack_bottom = (duk_tval *) (void *) ((duk_uint8_t *) thr->valstack + act->bottom_byteoff);
78017 idx_bottom = (duk_size_t) (thr->valstack_bottom - thr->valstack);
78018 DUK_ASSERT(cat->idx_base >= idx_bottom);
78019 clamp_top = (duk_idx_t) (cat->idx_base - idx_bottom + 2); /* +2 = catcher value, catcher lj_type */
78020 duk_set_top_and_wipe(thr, h_func->nregs, clamp_top);
78021
78022 DUK_ASSERT((duk_uint8_t *) thr->valstack_end >= (duk_uint8_t *) thr->valstack + act->reserve_byteoff);
78023 thr->valstack_end = (duk_tval *) (void *) ((duk_uint8_t *) thr->valstack + act->reserve_byteoff);
78024
78025 /* XXX: a best effort shrink check would be OK here */
78027
78028/* Set catcher regs: idx_base+0 = value, idx_base+1 = lj_type.
78029 * No side effects.
78030 */
78031DUK_LOCAL void duk__set_catcher_regs_norz(duk_hthread *thr, duk_catcher *cat, duk_tval *tv_val_unstable, duk_small_uint_t lj_type) {
78032 duk_tval *tv1;
78033
78034 DUK_ASSERT(thr != NULL);
78035 DUK_ASSERT(tv_val_unstable != NULL);
78036
78037 tv1 = thr->valstack + cat->idx_base;
78038 DUK_ASSERT(tv1 < thr->valstack_top);
78039 DUK_TVAL_SET_TVAL_UPDREF_NORZ(thr, tv1, tv_val_unstable);
78040
78041 tv1++;
78042 DUK_ASSERT(tv1 == thr->valstack + cat->idx_base + 1);
78043 DUK_ASSERT(tv1 < thr->valstack_top);
78044 DUK_TVAL_SET_U32_UPDREF_NORZ(thr, tv1, (duk_uint32_t) lj_type);
78045}
78046
78048 duk_tval *tv_val_unstable,
78049 duk_small_uint_t lj_type,
78050 volatile duk_bool_t *out_delayed_catch_setup) {
78051 duk_activation *act;
78052 duk_catcher *cat;
78053
78054 DUK_ASSERT(thr != NULL);
78055 DUK_ASSERT(tv_val_unstable != NULL);
78056
78057 act = thr->callstack_curr;
78058 DUK_ASSERT(act != NULL);
78059 DUK_DD(DUK_DDPRINT("handle catch, part 1; act=%!A, cat=%!C", act, act->cat));
78060
78061 DUK_ASSERT(act->cat != NULL);
78063
78064 /* The part1/part2 split could also be made here at the very top
78065 * of catch handling. Value stack would be reconfigured inside
78066 * part2's protection. Value stack reconfiguration should be free
78067 * of allocs, however.
78068 */
78069
78070 duk__set_catcher_regs_norz(thr, act->cat, tv_val_unstable, lj_type);
78071
78072 DUK_ASSERT(thr->callstack_top >= 1);
78073 DUK_ASSERT(thr->callstack_curr != NULL);
78076
78077 DUK_ASSERT(thr->callstack_top >= 1);
78078 DUK_ASSERT(act == thr->callstack_curr);
78079 DUK_ASSERT(act != NULL);
78081
78082 DUK_ASSERT(thr->callstack_top >= 1);
78083 DUK_ASSERT(act == thr->callstack_curr);
78084 DUK_ASSERT(act != NULL);
78085 cat = act->cat;
78086 DUK_ASSERT(cat != NULL);
78088 act->curr_pc = cat->pc_base + 0; /* +0 = catch */
78089
78090 /*
78091 * If the catch block has an automatic catch variable binding,
78092 * we need to create a lexical environment for it which requires
78093 * allocations. Move out of "error handling state" before the
78094 * allocations to avoid e.g. out-of-memory errors (leading to
78095 * GH-2022 or similar).
78096 */
78097
78099 DUK_DDD(DUK_DDDPRINT("catcher has an automatic catch binding, handle in part 2"));
78100 *out_delayed_catch_setup = 1;
78101 } else {
78102 DUK_DDD(DUK_DDDPRINT("catcher has no catch binding"));
78103 }
78104
78106}
78107
78109 duk_activation *act;
78110 duk_catcher *cat;
78111 duk_hdecenv *new_env;
78112
78113 DUK_ASSERT(thr != NULL);
78114
78115 act = thr->callstack_curr;
78116 DUK_ASSERT(act != NULL);
78117 DUK_DD(DUK_DDPRINT("handle catch, part 2; act=%!A, cat=%!C", act, act->cat));
78118
78119 DUK_ASSERT(act->cat != NULL);
78120 cat = act->cat;
78121 DUK_ASSERT(cat != NULL);
78124 DUK_ASSERT(thr->valstack + cat->idx_base < thr->valstack_top);
78125
78126 /*
78127 * Create lexical environment for the catch clause, containing
78128 * a binding for the caught value.
78129 *
78130 * The binding is mutable (= writable) but not deletable.
78131 * Step 4 for the catch production in E5 Section 12.14;
78132 * no value is given for CreateMutableBinding 'D' argument,
78133 * which implies the binding is not deletable.
78134 */
78135
78136 if (act->lex_env == NULL) {
78137 DUK_ASSERT(act->var_env == NULL);
78138 DUK_DDD(DUK_DDDPRINT("delayed environment initialization"));
78139
78141 DUK_ASSERT(act == thr->callstack_curr);
78142 DUK_ASSERT(act != NULL);
78143 }
78144 DUK_ASSERT(act->lex_env != NULL);
78145 DUK_ASSERT(act->var_env != NULL);
78146 DUK_ASSERT(DUK_ACT_GET_FUNC(act) != NULL);
78147
78149 DUK_ASSERT(new_env != NULL);
78150 duk_push_hobject(thr, (duk_hobject *) new_env);
78151 DUK_ASSERT(DUK_HOBJECT_GET_PROTOTYPE(thr->heap, (duk_hobject *) new_env) == NULL);
78152 DUK_DDD(DUK_DDDPRINT("new_env allocated: %!iO", (duk_heaphdr *) new_env));
78153
78154 /* Note: currently the catch binding is handled without a register
78155 * binding because we don't support dynamic register bindings (they
78156 * must be fixed for an entire function). So, there is no need to
78157 * record regbases etc.
78158 */
78159
78160 /* [ ...env ] */
78161
78162 DUK_ASSERT(cat->h_varname != NULL);
78163 duk_push_hstring(thr, cat->h_varname);
78164 DUK_ASSERT(thr->valstack + cat->idx_base < thr->valstack_top);
78166 duk_xdef_prop(thr, -3, DUK_PROPDESC_FLAGS_W); /* writable, not configurable */
78167
78168 /* [ ... env ] */
78169
78170 DUK_ASSERT(act == thr->callstack_curr);
78171 DUK_ASSERT(act != NULL);
78172 DUK_HOBJECT_SET_PROTOTYPE(thr->heap, (duk_hobject *) new_env, act->lex_env);
78173 act->lex_env = (duk_hobject *) new_env;
78174 DUK_HOBJECT_INCREF(thr, (duk_hobject *) new_env); /* reachable through activation */
78175 /* Net refcount change to act->lex_env is 0: incref for new_env's
78176 * prototype, decref for act->lex_env overwrite.
78177 */
78178
78180
78181 duk_pop_unsafe(thr);
78182
78183 DUK_DDD(DUK_DDDPRINT("new_env finished: %!iO", (duk_heaphdr *) new_env));
78184}
78185
78186DUK_LOCAL void duk__handle_finally(duk_hthread *thr, duk_tval *tv_val_unstable, duk_small_uint_t lj_type) {
78187 duk_activation *act;
78188 duk_catcher *cat;
78189
78190 DUK_ASSERT(thr != NULL);
78191 DUK_ASSERT(tv_val_unstable != NULL);
78192
78193 act = thr->callstack_curr;
78194 DUK_ASSERT(act != NULL);
78195 DUK_ASSERT(act->cat != NULL);
78197
78198 duk__set_catcher_regs_norz(thr, act->cat, tv_val_unstable, lj_type);
78199
78201 DUK_ASSERT(thr->callstack_curr != NULL);
78204
78205 DUK_ASSERT(thr->callstack_top >= 1);
78206 DUK_ASSERT(act == thr->callstack_curr);
78207 DUK_ASSERT(act != NULL);
78209
78210 DUK_ASSERT(thr->callstack_top >= 1);
78211 DUK_ASSERT(act == thr->callstack_curr);
78212 DUK_ASSERT(act != NULL);
78213 cat = act->cat;
78214 DUK_ASSERT(cat != NULL);
78215
78216 act->curr_pc = cat->pc_base + 1; /* +1 = finally */
78217
78219}
78220
78222 duk_activation *act;
78223 duk_catcher *cat;
78224
78225 DUK_ASSERT(thr != NULL);
78226
78227 DUK_ASSERT(thr->callstack_top >= 1);
78228 act = thr->callstack_curr;
78229 DUK_ASSERT(act != NULL);
78230 DUK_ASSERT(DUK_ACT_GET_FUNC(act) != NULL);
78232
78233 /* +0 = break, +1 = continue */
78234 cat = act->cat;
78235 DUK_ASSERT(cat != NULL);
78237
78238 act->curr_pc = cat->pc_base + (lj_type == DUK_LJ_TYPE_CONTINUE ? 1 : 0);
78239
78240 /* valstack should not need changes */
78241#if defined(DUK_USE_ASSERTIONS)
78242 DUK_ASSERT(thr->callstack_top >= 1);
78243 DUK_ASSERT(act == thr->callstack_curr);
78244 DUK_ASSERT(act != NULL);
78246 (duk_size_t) ((duk_hcompfunc *) DUK_ACT_GET_FUNC(act))->nregs);
78247#endif
78248}
78249
78250/* Called for handling both a longjmp() with type DUK_LJ_TYPE_YIELD and
78251 * when a RETURN opcode terminates a thread and yields to the resumer.
78252 * Caller unwinds so that top of callstack is the activation we return to.
78253 */
78254#if defined(DUK_USE_COROUTINE_SUPPORT)
78255DUK_LOCAL void duk__handle_yield(duk_hthread *thr, duk_hthread *resumer, duk_tval *tv_val_unstable) {
78256 duk_activation *act_resumer;
78257 duk_tval *tv1;
78258
78259 DUK_ASSERT(thr != NULL);
78260 DUK_ASSERT(resumer != NULL);
78261 DUK_ASSERT(tv_val_unstable != NULL);
78262 act_resumer = resumer->callstack_curr;
78263 DUK_ASSERT(act_resumer != NULL);
78264 DUK_ASSERT(DUK_ACT_GET_FUNC(act_resumer) != NULL);
78265 DUK_ASSERT(DUK_HOBJECT_IS_COMPFUNC(DUK_ACT_GET_FUNC(act_resumer))); /* resume caller must be an ECMAScript func */
78266
78267 tv1 = (duk_tval *) (void *) ((duk_uint8_t *) resumer->valstack +
78268 act_resumer->retval_byteoff); /* return value from Duktape.Thread.resume() */
78269 DUK_TVAL_SET_TVAL_UPDREF(thr, tv1, tv_val_unstable); /* side effects */ /* XXX: avoid side effects */
78270
78272
78273 /* caller must change active thread, and set thr->resumer to NULL */
78274}
78275#endif /* DUK_USE_COROUTINE_SUPPORT */
78276
78278 duk_activation *entry_act,
78279 volatile duk_bool_t *out_delayed_catch_setup) {
78281
78282 DUK_ASSERT(thr != NULL);
78283 DUK_ASSERT(entry_act != NULL);
78284
78285 /* 'thr' is the current thread, as no-one resumes except us and we
78286 * switch 'thr' in that case.
78287 */
78288 DUK_ASSERT(thr == thr->heap->curr_thread);
78289
78290 /*
78291 * (Re)try handling the longjmp.
78292 *
78293 * A longjmp handler may convert the longjmp to a different type and
78294 * "virtually" rethrow by goto'ing to 'check_longjmp'. Before the goto,
78295 * the following must be updated:
78296 * - the heap 'lj' state
78297 * - 'thr' must reflect the "throwing" thread
78298 */
78299
78300check_longjmp:
78301
78302 DUK_DD(DUK_DDPRINT("handling longjmp: type=%ld, value1=%!T, value2=%!T, iserror=%ld, top=%ld",
78303 (long) thr->heap->lj.type,
78304 (duk_tval *) &thr->heap->lj.value1,
78305 (duk_tval *) &thr->heap->lj.value2,
78306 (long) thr->heap->lj.iserror,
78307 (long) duk_get_top(thr)));
78308
78309 switch (thr->heap->lj.type) {
78310#if defined(DUK_USE_COROUTINE_SUPPORT)
78311 case DUK_LJ_TYPE_RESUME: {
78312 /*
78313 * Note: lj.value1 is 'value', lj.value2 is 'resumee'.
78314 * This differs from YIELD.
78315 */
78316
78317 duk_tval *tv;
78318 duk_tval *tv2;
78319 duk_hthread *resumee;
78320
78321 /* duk_bi_duk_object_yield() and duk_bi_duk_object_resume() ensure all of these are met */
78322
78323 DUK_ASSERT(thr->state == DUK_HTHREAD_STATE_RUNNING); /* unchanged by Duktape.Thread.resume() */
78324 DUK_ASSERT(thr->callstack_top >= 2); /* ECMAScript activation + Duktape.Thread.resume() activation */
78325 DUK_ASSERT(thr->callstack_curr != NULL);
78326 DUK_ASSERT(thr->callstack_curr->parent != NULL);
78330
78331 tv = &thr->heap->lj.value2; /* resumee */
78333 DUK_ASSERT(DUK_TVAL_GET_OBJECT(tv) != NULL);
78335 resumee = (duk_hthread *) DUK_TVAL_GET_OBJECT(tv);
78336
78337 DUK_ASSERT(resumee != NULL);
78338 DUK_ASSERT(resumee->resumer == NULL);
78340 resumee->state == DUK_HTHREAD_STATE_YIELDED); /* checked by Duktape.Thread.resume() */
78342 resumee->callstack_top >= 2); /* YIELDED: ECMAScript activation + Duktape.Thread.yield() activation */
78344 (DUK_ACT_GET_FUNC(resumee->callstack_curr) != NULL &&
78348 resumee->callstack_top == 0); /* INACTIVE: no activation, single function value on valstack */
78349
78350 if (thr->heap->lj.iserror) {
78351 /*
78352 * Throw the error in the resumed thread's context; the
78353 * error value is pushed onto the resumee valstack.
78354 *
78355 * Note: the callstack of the target may empty in this case
78356 * too (i.e. the target thread has never been resumed). The
78357 * value stack will contain the initial function in that case,
78358 * which we simply ignore.
78359 */
78360
78361 DUK_ASSERT(resumee->resumer == NULL);
78362 resumee->resumer = thr;
78363 DUK_HTHREAD_INCREF(thr, thr);
78366 DUK_HEAP_SWITCH_THREAD(thr->heap, resumee);
78367 thr = resumee;
78368
78369 thr->heap->lj.type = DUK_LJ_TYPE_THROW;
78370
78371 /* thr->heap->lj.value1 is already the value to throw */
78372 /* thr->heap->lj.value2 is 'thread', will be wiped out at the end */
78373
78374 DUK_ASSERT(thr->heap->lj.iserror); /* already set */
78375
78376 DUK_DD(DUK_DDPRINT("-> resume with an error, converted to a throw in the resumee, propagate"));
78377 goto check_longjmp;
78378 } else if (resumee->state == DUK_HTHREAD_STATE_YIELDED) {
78379 /* Unwind previous Duktape.Thread.yield() call. The
78380 * activation remaining must always be an ECMAScript
78381 * call now (yield() accepts calls from ECMAScript
78382 * only).
78383 */
78384 duk_activation *act_resumee;
78385
78386 DUK_ASSERT(resumee->callstack_top >= 2);
78387 act_resumee = resumee->callstack_curr; /* Duktape.Thread.yield() */
78388 DUK_ASSERT(act_resumee != NULL);
78389 act_resumee = act_resumee->parent; /* ECMAScript call site for yield() */
78390 DUK_ASSERT(act_resumee != NULL);
78391
78392 tv = (duk_tval *) (void *) ((duk_uint8_t *) resumee->valstack +
78393 act_resumee->retval_byteoff); /* return value from Duktape.Thread.yield() */
78394 DUK_ASSERT(tv >= resumee->valstack && tv < resumee->valstack_top);
78395 tv2 = &thr->heap->lj.value1;
78396 DUK_TVAL_SET_TVAL_UPDREF(thr, tv, tv2); /* side effects */ /* XXX: avoid side effects */
78397
78398 duk_hthread_activation_unwind_norz(resumee); /* unwind to 'yield' caller */
78399 /* no need to unwind catch stack */
78400
78402
78403 DUK_ASSERT(resumee->resumer == NULL);
78404 resumee->resumer = thr;
78405 DUK_HTHREAD_INCREF(thr, thr);
78408 DUK_HEAP_SWITCH_THREAD(thr->heap, resumee);
78409#if 0
78410 thr = resumee; /* not needed, as we exit right away */
78411#endif
78412 DUK_DD(DUK_DDPRINT("-> resume with a value, restart execution in resumee"));
78413 retval = DUK__LONGJMP_RESTART;
78414 goto wipe_and_return;
78415 } else {
78416 /* Initial resume call. */
78417 duk_small_uint_t call_flags;
78418 duk_int_t setup_rc;
78419
78420 /* resumee: [... initial_func] (currently actually: [initial_func]) */
78421
78422 duk_push_undefined(resumee);
78423 tv = &thr->heap->lj.value1;
78424 duk_push_tval(resumee, tv);
78425
78426 /* resumee: [... initial_func undefined(= this) resume_value ] */
78427
78428 call_flags = DUK_CALL_FLAG_ALLOW_ECMATOECMA; /* not tailcall, ecma-to-ecma (assumed to succeed) */
78429
78430 setup_rc = duk_handle_call_unprotected_nargs(resumee, 1 /*nargs*/, call_flags);
78431 if (setup_rc == 0) {
78432 /* This shouldn't happen; Duktape.Thread.resume()
78433 * should make sure of that. If it does happen
78434 * this internal error will propagate out of the
78435 * executor which can be quite misleading.
78436 */
78437 DUK_ERROR_INTERNAL(thr);
78438 DUK_WO_NORETURN(return 0;);
78439 }
78440
78441 DUK_ASSERT(resumee->resumer == NULL);
78442 resumee->resumer = thr;
78443 DUK_HTHREAD_INCREF(thr, thr);
78446 DUK_HEAP_SWITCH_THREAD(thr->heap, resumee);
78447#if 0
78448 thr = resumee; /* not needed, as we exit right away */
78449#endif
78450 DUK_DD(DUK_DDPRINT("-> resume with a value, restart execution in resumee"));
78451 retval = DUK__LONGJMP_RESTART;
78452 goto wipe_and_return;
78453 }
78455 break; /* never here */
78456 }
78457
78458 case DUK_LJ_TYPE_YIELD: {
78459 /*
78460 * Currently only allowed only if yielding thread has only
78461 * ECMAScript activations (except for the Duktape.Thread.yield()
78462 * call at the callstack top) and none of them constructor
78463 * calls.
78464 *
78465 * This excludes the 'entry' thread which will always have
78466 * a preventcount > 0.
78467 */
78468
78469 duk_hthread *resumer;
78470
78471 /* duk_bi_duk_object_yield() and duk_bi_duk_object_resume() ensure all of these are met */
78472
78473#if 0 /* entry_thread not available for assert */
78474 DUK_ASSERT(thr != entry_thread); /* Duktape.Thread.yield() should prevent */
78475#endif
78476 DUK_ASSERT(thr->state == DUK_HTHREAD_STATE_RUNNING); /* unchanged from Duktape.Thread.yield() */
78477 DUK_ASSERT(thr->callstack_top >= 2); /* ECMAScript activation + Duktape.Thread.yield() activation */
78478 DUK_ASSERT(thr->callstack_curr != NULL);
78479 DUK_ASSERT(thr->callstack_curr->parent != NULL);
78484 DUK_HOBJECT_IS_COMPFUNC(DUK_ACT_GET_FUNC(thr->callstack_curr->parent))); /* an ECMAScript function */
78485
78486 resumer = thr->resumer;
78487
78488 DUK_ASSERT(resumer != NULL);
78489 DUK_ASSERT(resumer->state == DUK_HTHREAD_STATE_RESUMED); /* written by a previous RESUME handling */
78490 DUK_ASSERT(resumer->callstack_top >= 2); /* ECMAScript activation + Duktape.Thread.resume() activation */
78491 DUK_ASSERT(resumer->callstack_curr != NULL);
78492 DUK_ASSERT(resumer->callstack_curr->parent != NULL);
78493 DUK_ASSERT(DUK_ACT_GET_FUNC(resumer->callstack_curr) != NULL &&
78496 DUK_ASSERT(DUK_ACT_GET_FUNC(resumer->callstack_curr->parent) != NULL &&
78497 DUK_HOBJECT_IS_COMPFUNC(DUK_ACT_GET_FUNC(resumer->callstack_curr->parent))); /* an ECMAScript function */
78498
78499 if (thr->heap->lj.iserror) {
78501 thr->resumer = NULL;
78502 DUK_HTHREAD_DECREF_NORZ(thr, resumer);
78504 DUK_HEAP_SWITCH_THREAD(thr->heap, resumer);
78505 thr = resumer;
78506
78507 thr->heap->lj.type = DUK_LJ_TYPE_THROW;
78508 /* lj.value1 is already set */
78509 DUK_ASSERT(thr->heap->lj.iserror); /* already set */
78510
78511 DUK_DD(DUK_DDPRINT("-> yield an error, converted to a throw in the resumer, propagate"));
78512 goto check_longjmp;
78513 } else {
78514 /* When handling the yield, the last reference to
78515 * 'thr' may disappear.
78516 */
78517
78518 DUK_GC_TORTURE(resumer->heap);
78520 DUK_GC_TORTURE(resumer->heap);
78522 thr->resumer = NULL;
78523 DUK_HTHREAD_DECREF_NORZ(thr, resumer);
78525 DUK_HEAP_SWITCH_THREAD(thr->heap, resumer);
78526 duk__handle_yield(thr, resumer, &thr->heap->lj.value1);
78527 thr = resumer;
78528 DUK_GC_TORTURE(resumer->heap);
78529
78530 DUK_DD(DUK_DDPRINT("-> yield a value, restart execution in resumer"));
78531 retval = DUK__LONGJMP_RESTART;
78532 goto wipe_and_return;
78533 }
78535 break; /* never here */
78536 }
78537#endif /* DUK_USE_COROUTINE_SUPPORT */
78538
78539 case DUK_LJ_TYPE_THROW: {
78540 /*
78541 * Three possible outcomes:
78542 * * A try or finally catcher is found => resume there.
78543 * (or)
78544 * * The error propagates to the bytecode executor entry
78545 * level (and we're in the entry thread) => rethrow
78546 * with a new longjmp(), after restoring the previous
78547 * catchpoint.
78548 * * The error is not caught in the current thread, so
78549 * the thread finishes with an error. This works like
78550 * a yielded error, except that the thread is finished
78551 * and can no longer be resumed. (There is always a
78552 * resumer in this case.)
78553 *
78554 * Note: until we hit the entry level, there can only be
78555 * ECMAScript activations.
78556 */
78557
78558 duk_activation *act;
78559 duk_catcher *cat;
78560 duk_hthread *resumer;
78561
78562 for (;;) {
78563 act = thr->callstack_curr;
78564 if (act == NULL) {
78565 break;
78566 }
78567
78568 for (;;) {
78569 cat = act->cat;
78570 if (cat == NULL) {
78571 break;
78572 }
78573
78574 if (DUK_CAT_HAS_CATCH_ENABLED(cat)) {
78576
78577 DUK_DDD(DUK_DDDPRINT("before catch part 1: thr=%p, act=%p, cat=%p",
78578 (void *) thr,
78579 (void *) act,
78580 (void *) act->cat));
78582 &thr->heap->lj.value1,
78584 out_delayed_catch_setup);
78585
78586 DUK_DD(DUK_DDPRINT("-> throw caught by a 'catch' clause, restart execution"));
78587 retval = DUK__LONGJMP_RESTART;
78588 goto wipe_and_return;
78589 }
78590
78591 if (DUK_CAT_HAS_FINALLY_ENABLED(cat)) {
78594
78595 duk__handle_finally(thr, &thr->heap->lj.value1, DUK_LJ_TYPE_THROW);
78596
78597 DUK_DD(DUK_DDPRINT("-> throw caught by a 'finally' clause, restart execution"));
78598 retval = DUK__LONGJMP_RESTART;
78599 goto wipe_and_return;
78600 }
78601
78603 }
78604
78605 if (act == entry_act) {
78606 /* Not caught by anything before entry level; rethrow and let the
78607 * final catcher finish unwinding (esp. value stack).
78608 */
78609 DUK_D(DUK_DPRINT("-> throw propagated up to entry level, rethrow and exit bytecode executor"));
78610 retval = DUK__LONGJMP_RETHROW;
78611 goto just_return;
78612 }
78613
78615 }
78616
78617 DUK_DD(DUK_DDPRINT("-> throw not caught by current thread, yield error to resumer and recheck longjmp"));
78618
78619 /* Not caught by current thread, thread terminates (yield error to resumer);
78620 * note that this may cause a cascade if the resumer terminates with an uncaught
78621 * exception etc (this is OK, but needs careful testing).
78622 */
78623
78624 DUK_ASSERT(thr->resumer != NULL);
78625 DUK_ASSERT(thr->resumer->callstack_top >= 2); /* ECMAScript activation + Duktape.Thread.resume() activation */
78626 DUK_ASSERT(thr->resumer->callstack_curr != NULL);
78627 DUK_ASSERT(thr->resumer->callstack_curr->parent != NULL);
78628 DUK_ASSERT(
78629 DUK_ACT_GET_FUNC(thr->resumer->callstack_curr->parent) != NULL &&
78630 DUK_HOBJECT_IS_COMPFUNC(DUK_ACT_GET_FUNC(thr->resumer->callstack_curr->parent))); /* an ECMAScript function */
78631
78632 resumer = thr->resumer;
78633
78634 /* reset longjmp */
78635
78636 DUK_ASSERT(thr->heap->lj.type == DUK_LJ_TYPE_THROW); /* already set */
78637 /* lj.value1 already set */
78638
78639 duk_hthread_terminate(thr); /* updates thread state, minimizes its allocations */
78641
78642 thr->resumer = NULL;
78643 DUK_HTHREAD_DECREF_NORZ(thr, resumer);
78645 DUK_HEAP_SWITCH_THREAD(thr->heap, resumer);
78646 thr = resumer;
78647 goto check_longjmp;
78648 }
78649
78650 case DUK_LJ_TYPE_BREAK: /* pseudotypes, not used in actual longjmps */
78652 case DUK_LJ_TYPE_RETURN:
78653 case DUK_LJ_TYPE_NORMAL:
78654 default: {
78655 /* should never happen, but be robust */
78656 DUK_D(DUK_DPRINT("caught unknown longjmp type %ld, treat as internal error", (long) thr->heap->lj.type));
78657 goto convert_to_internal_error;
78658 }
78659
78660 } /* end switch */
78661
78663
78664wipe_and_return:
78665 DUK_DD(DUK_DDPRINT("handling longjmp done, wipe-and-return, top=%ld", (long) duk_get_top(thr)));
78666 thr->heap->lj.type = DUK_LJ_TYPE_UNKNOWN;
78667 thr->heap->lj.iserror = 0;
78668
78669 DUK_TVAL_SET_UNDEFINED_UPDREF(thr, &thr->heap->lj.value1); /* side effects */
78670 DUK_TVAL_SET_UNDEFINED_UPDREF(thr, &thr->heap->lj.value2); /* side effects */
78671
78672 DUK_GC_TORTURE(thr->heap);
78673
78674just_return:
78675 return retval;
78676
78677convert_to_internal_error:
78678 /* This could also be thrown internally (set the error, goto check_longjmp),
78679 * but it's better for internal errors to bubble outwards so that we won't
78680 * infinite loop in this catchpoint.
78681 */
78682 DUK_ERROR_INTERNAL(thr);
78683 DUK_WO_NORETURN(return 0;);
78684}
78685
78686/* Handle a BREAK/CONTINUE opcode. Avoid using longjmp() for BREAK/CONTINUE
78687 * handling because it has a measurable performance impact in ordinary
78688 * environments and an extreme impact in Emscripten (GH-342).
78689 */
78691 duk_uint_t label_id,
78692 duk_small_uint_t lj_type) {
78693 duk_activation *act;
78694 duk_catcher *cat;
78695
78696 DUK_ASSERT(thr != NULL);
78697
78698 /* Find a matching label catcher or 'finally' catcher in
78699 * the same function, unwinding catchers as we go.
78700 *
78701 * A label catcher must always exist and will match unless
78702 * a 'finally' captures the break/continue first. It is the
78703 * compiler's responsibility to ensure that labels are used
78704 * correctly.
78705 */
78706
78707 act = thr->callstack_curr;
78708 DUK_ASSERT(act != NULL);
78709
78710 for (;;) {
78711 cat = act->cat;
78712 if (cat == NULL) {
78713 break;
78714 }
78715
78716 DUK_DDD(DUK_DDDPRINT("considering catcher %p: type=%ld label=%ld",
78717 (void *) cat,
78718 (long) DUK_CAT_GET_TYPE(cat),
78719 (long) DUK_CAT_GET_LABEL(cat)));
78720
78721 /* XXX: bit mask test; FINALLY <-> TCF, single bit mask would suffice? */
78722
78724 duk_tval tv_tmp;
78725
78726 DUK_TVAL_SET_U32(&tv_tmp, (duk_uint32_t) label_id);
78727 duk__handle_finally(thr, &tv_tmp, lj_type);
78728
78729 DUK_DD(DUK_DDPRINT("-> break/continue caught by 'finally', restart execution"));
78730 return;
78731 }
78732 if (DUK_CAT_GET_TYPE(cat) == DUK_CAT_TYPE_LABEL && (duk_uint_t) DUK_CAT_GET_LABEL(cat) == label_id) {
78733 duk__handle_label(thr, lj_type);
78734
78735 DUK_DD(
78736 DUK_DDPRINT("-> break/continue caught by a label catcher (in the same function), restart execution"));
78737 return;
78738 }
78739
78741 }
78742
78743 /* Should never happen, but be robust. */
78745 "-> break/continue not caught by anything in the current function (should never happen), throw internal error"));
78746 DUK_ERROR_INTERNAL(thr);
78747 DUK_WO_NORETURN(return;);
78748}
78749
78750/* Handle a RETURN opcode. Avoid using longjmp() for return handling because
78751 * it has a measurable performance impact in ordinary environments and an extreme
78752 * impact in Emscripten (GH-342). Return value is on value stack top.
78753 */
78755 duk_tval *tv1;
78756 duk_tval *tv2;
78757#if defined(DUK_USE_COROUTINE_SUPPORT)
78758 duk_hthread *resumer;
78759#endif
78760 duk_activation *act;
78761 duk_catcher *cat;
78762
78763 /* We can directly access value stack here. */
78764
78765 DUK_ASSERT(thr != NULL);
78766 DUK_ASSERT(entry_act != NULL);
78767 DUK_ASSERT(thr->valstack_top - 1 >= thr->valstack_bottom);
78768 tv1 = thr->valstack_top - 1;
78769 DUK_TVAL_CHKFAST_INPLACE_FAST(tv1); /* fastint downgrade check for return values */
78770
78771 /*
78772 * Four possible outcomes:
78773 *
78774 * 1. A 'finally' in the same function catches the 'return'.
78775 * It may continue to propagate when 'finally' is finished,
78776 * or it may be neutralized by 'finally' (both handled by
78777 * ENDFIN).
78778 *
78779 * 2. The return happens at the entry level of the bytecode
78780 * executor, so return from the executor (in C stack).
78781 *
78782 * 3. There is a calling (ECMAScript) activation in the call
78783 * stack => return to it, in the same executor instance.
78784 *
78785 * 4. There is no calling activation, and the thread is
78786 * terminated. There is always a resumer in this case,
78787 * which gets the return value similarly to a 'yield'
78788 * (except that the current thread can no longer be
78789 * resumed).
78790 */
78791
78792 DUK_ASSERT(thr != NULL);
78793 DUK_ASSERT(thr->callstack_top >= 1);
78794
78795 act = thr->callstack_curr;
78796 DUK_ASSERT(act != NULL);
78797
78798 for (;;) {
78799 cat = act->cat;
78800 if (cat == NULL) {
78801 break;
78802 }
78803
78805 DUK_ASSERT(thr->valstack_top - 1 >= thr->valstack_bottom);
78807
78808 DUK_DD(DUK_DDPRINT("-> return caught by 'finally', restart execution"));
78809 return DUK__RETHAND_RESTART;
78810 }
78811
78813 }
78814
78815 if (act == entry_act) {
78816 /* Return to the bytecode executor caller who will unwind stacks
78817 * and handle constructor post-processing.
78818 * Return value is already on the stack top: [ ... retval ].
78819 */
78820
78821 DUK_DDD(DUK_DDDPRINT("-> return propagated up to entry level, exit bytecode executor"));
78822 return DUK__RETHAND_FINISHED;
78823 }
78824
78825 if (thr->callstack_top >= 2) {
78826 /* There is a caller; it MUST be an ECMAScript caller (otherwise it would
78827 * match entry_act check).
78828 */
78829 DUK_DDD(DUK_DDDPRINT("return to ECMAScript caller, retval_byteoff=%ld, lj_value1=%!T",
78830 (long) (thr->callstack_curr->parent->retval_byteoff),
78831 (duk_tval *) &thr->heap->lj.value1));
78832
78833 DUK_ASSERT(thr->callstack_curr != NULL);
78834 DUK_ASSERT(thr->callstack_curr->parent != NULL);
78836
78837#if defined(DUK_USE_ES6_PROXY)
78840 thr->callstack_curr->flags &
78841 DUK_ACT_FLAG_CONSTRUCT_PROXY); /* side effects */
78842 }
78843#else
78845 duk_call_construct_postprocess(thr, 0); /* side effects */
78846 }
78847#endif
78848
78849 tv1 = (duk_tval *) (void *) ((duk_uint8_t *) thr->valstack + thr->callstack_curr->parent->retval_byteoff);
78850 DUK_ASSERT(thr->valstack_top - 1 >= thr->valstack_bottom);
78851 tv2 = thr->valstack_top - 1;
78852 DUK_TVAL_SET_TVAL_UPDREF(thr, tv1, tv2); /* side effects */
78853
78854 /* Catch stack unwind happens inline in callstack unwind. */
78856
78858
78859 DUK_DD(DUK_DDPRINT("-> return not intercepted, restart execution in caller"));
78860 return DUK__RETHAND_RESTART;
78861 }
78862
78863#if defined(DUK_USE_COROUTINE_SUPPORT)
78864 DUK_DD(DUK_DDPRINT("no calling activation, thread finishes (similar to yield)"));
78865
78866 DUK_ASSERT(thr->resumer != NULL);
78867 DUK_ASSERT(thr->resumer->callstack_top >= 2); /* ECMAScript activation + Duktape.Thread.resume() activation */
78868 DUK_ASSERT(thr->resumer->callstack_curr != NULL);
78869 DUK_ASSERT(thr->resumer->callstack_curr->parent != NULL);
78873 duk_bi_thread_resume); /* Duktape.Thread.resume() */
78875 DUK_HOBJECT_IS_COMPFUNC(DUK_ACT_GET_FUNC(thr->resumer->callstack_curr->parent))); /* an ECMAScript function */
78878
78879 resumer = thr->resumer;
78880
78881 /* Share yield longjmp handler.
78882 *
78883 * This sequence of steps is a bit fragile (see GH-1845):
78884 * - We need the return value from 'thr' (resumed thread) value stack.
78885 * The termination unwinds its value stack, losing the value.
78886 * - We need a refcounted reference for 'thr', which may only exist
78887 * in the caller value stack. We can't unwind or reconfigure the
78888 * caller's value stack without potentially freeing 'thr'.
78889 *
78890 * Current approach is to capture the 'thr' return value and store
78891 * a reference to 'thr' in the caller value stack temporarily. This
78892 * keeps 'thr' reachable until final yield/return handling which
78893 * removes the references atomatically.
78894 */
78895
78896 DUK_ASSERT(thr->valstack_top - 1 >= thr->valstack_bottom);
78897 duk_hthread_activation_unwind_norz(resumer); /* May remove last reference to 'thr', but is NORZ. */
78898 duk_push_tval(resumer, thr->valstack_top - 1); /* Capture return value, side effect free. */
78899 duk_push_hthread(resumer, thr); /* Make 'thr' reachable again, before side effects. */
78900
78901 duk_hthread_terminate(thr); /* Updates thread state, minimizes its allocations. */
78902 thr->resumer = NULL;
78903 DUK_HTHREAD_DECREF(thr, resumer);
78905
78907 DUK_HEAP_SWITCH_THREAD(thr->heap, resumer);
78908
78909 DUK_ASSERT(resumer->valstack_top - 2 >= resumer->valstack_bottom);
78910 duk__handle_yield(thr, resumer, resumer->valstack_top - 2);
78911 thr = NULL; /* 'thr' invalidated by call */
78912
78913#if 0
78914 thr = resumer; /* not needed */
78915#endif
78916
78917 DUK_DD(DUK_DDPRINT("-> return not caught, thread terminated; handle like yield, restart execution in resumer"));
78918 return DUK__RETHAND_RESTART;
78919#else
78920 /* Without coroutine support this case should never happen. */
78921 DUK_ERROR_INTERNAL(thr);
78922 DUK_WO_NORETURN(return 0;);
78923#endif
78924}
78925
78926/*
78927 * Executor interrupt handling
78928 *
78929 * The handler is called whenever the interrupt countdown reaches zero
78930 * (or below). The handler must perform whatever checks are activated,
78931 * e.g. check for cumulative step count to impose an execution step
78932 * limit or check for breakpoints or other debugger interaction.
78934 * When the actions are done, the handler must reinit the interrupt
78935 * init and counter values. The 'init' value must indicate how many
78936 * bytecode instructions are executed before the next interrupt. The
78937 * counter must interface with the bytecode executor loop. Concretely,
78938 * the new init value is normally one higher than the new counter value.
78939 * For instance, to execute exactly one bytecode instruction the init
78940 * value is set to 1 and the counter to 0. If an error is thrown by the
78941 * interrupt handler, the counters are set to the same value (e.g. both
78942 * to 0 to cause an interrupt when the next bytecode instruction is about
78943 * to be executed after error handling).
78944 *
78945 * Maintaining the init/counter value properly is important for accurate
78946 * behavior. For instance, executor step limit needs a cumulative step
78947 * count which is simply computed as a sum of 'init' values. This must
78948 * work accurately even when single stepping.
78949 */
78950
78951#if defined(DUK_USE_INTERRUPT_COUNTER)
78952
78953#define DUK__INT_NOACTION 0 /* no specific action, resume normal execution */
78954#define DUK__INT_RESTART 1 /* must "goto restart_execution", e.g. breakpoints changed */
78955
78956#if defined(DUK_USE_DEBUGGER_SUPPORT)
78957DUK_LOCAL void duk__interrupt_handle_debugger(duk_hthread *thr, duk_bool_t *out_immediate, duk_small_uint_t *out_interrupt_retval) {
78958 duk_activation *act;
78959 duk_breakpoint *bp;
78960 duk_breakpoint **bp_active;
78962 duk_bool_t process_messages;
78963 duk_bool_t processed_messages = 0;
78964
78965 DUK_ASSERT(thr->heap->dbg_processing == 0); /* don't re-enter e.g. during Eval */
78966
78967 act = thr->callstack_curr;
78968 DUK_ASSERT(act != NULL);
78969
78970 /* It might seem that replacing 'thr->heap' with just 'heap' below
78971 * might be a good idea, but it increases code size slightly
78972 * (probably due to unnecessary spilling) at least on x64.
78973 */
78974
78975 /*
78976 * Single opcode step check
78977 */
78978
78979 if (thr->heap->dbg_pause_flags & DUK_PAUSE_FLAG_ONE_OPCODE_ACTIVE) {
78980 DUK_D(DUK_DPRINT("PAUSE TRIGGERED by one opcode step"));
78981 duk_debug_set_paused(thr->heap);
78982 }
78983
78984 /*
78985 * Breakpoint and step state checks
78986 */
78987
78988 if (act->flags & DUK_ACT_FLAG_BREAKPOINT_ACTIVE || (thr->heap->dbg_pause_act == thr->callstack_curr)) {
78989 line = duk_debug_curr_line(thr);
78990
78991 if (act->prev_line != line) {
78992 /* Stepped? Step out is handled by callstack unwind. */
78993 if ((thr->heap->dbg_pause_flags & DUK_PAUSE_FLAG_LINE_CHANGE) &&
78994 (thr->heap->dbg_pause_act == thr->callstack_curr) && (line != thr->heap->dbg_pause_startline)) {
78995 DUK_D(DUK_DPRINT("PAUSE TRIGGERED by line change, at line %ld", (long) line));
78996 duk_debug_set_paused(thr->heap);
78997 }
78998
78999 /* Check for breakpoints only on line transition.
79000 * Breakpoint is triggered when we enter the target
79001 * line from a different line, and the previous line
79002 * was within the same function.
79003 *
79004 * This condition is tricky: the condition used to be
79005 * that transition to -or across- the breakpoint line
79006 * triggered the breakpoint. This seems intuitively
79007 * better because it handles breakpoints on lines with
79008 * no emitted opcodes; but this leads to the issue
79009 * described in: https://github.com/svaarala/duktape/issues/263.
79010 */
79011 bp_active = thr->heap->dbg_breakpoints_active;
79012 for (;;) {
79013 bp = *bp_active++;
79014 if (bp == NULL) {
79015 break;
79016 }
79017
79018 DUK_ASSERT(bp->filename != NULL);
79019 if (act->prev_line != bp->line && line == bp->line) {
79020 DUK_D(DUK_DPRINT("PAUSE TRIGGERED by breakpoint at %!O:%ld",
79021 (duk_heaphdr *) bp->filename,
79022 (long) bp->line));
79023 duk_debug_set_paused(thr->heap);
79024 }
79025 }
79026 } else {
79027 ;
79028 }
79029
79030 act->prev_line = (duk_uint32_t) line;
79031 }
79032
79033 /*
79034 * Rate limit check for sending status update or peeking into
79035 * the debug transport. Both can be expensive operations that
79036 * we don't want to do on every opcode.
79037 *
79038 * Making sure the interval remains reasonable on a wide variety
79039 * of targets and bytecode is difficult without a timestamp, so
79040 * we use a Date-provided timestamp for the rate limit check.
79041 * But since it's also expensive to get a timestamp, a bytecode
79042 * counter is used to rate limit getting timestamps.
79043 */
79044
79045 process_messages = 0;
79046 if (thr->heap->dbg_state_dirty || DUK_HEAP_HAS_DEBUGGER_PAUSED(thr->heap) || thr->heap->dbg_detaching) {
79047 /* Enter message processing loop for sending Status notifys and
79048 * to finish a pending detach.
79049 */
79050 process_messages = 1;
79051 }
79052
79053 /* XXX: remove heap->dbg_exec_counter, use heap->inst_count_interrupt instead? */
79054 DUK_ASSERT(thr->interrupt_init >= 0);
79055 thr->heap->dbg_exec_counter += (duk_uint_t) thr->interrupt_init;
79056 if (thr->heap->dbg_exec_counter - thr->heap->dbg_last_counter >= DUK_HEAP_DBG_RATELIMIT_OPCODES) {
79057 /* Overflow of the execution counter is fine and doesn't break
79058 * anything here.
79059 */
79060
79061 duk_double_t now, diff_last;
79062
79063 thr->heap->dbg_last_counter = thr->heap->dbg_exec_counter;
79064 now = duk_time_get_monotonic_time(thr);
79065
79066 diff_last = now - thr->heap->dbg_last_time;
79067 if (diff_last < 0.0 || diff_last >= (duk_double_t) DUK_HEAP_DBG_RATELIMIT_MILLISECS) {
79068 /* Monotonic time should not experience time jumps,
79069 * but the provider may be missing and we're actually
79070 * using ECMAScript time. So, tolerate negative values
79071 * so that a time jump works reasonably.
79072 *
79073 * Same interval is now used for status sending and
79074 * peeking.
79075 */
79076
79077 thr->heap->dbg_last_time = now;
79078 thr->heap->dbg_state_dirty = 1;
79079 process_messages = 1;
79080 }
79081 }
79082
79083 /*
79084 * Process messages and send status if necessary.
79085 *
79086 * If we're paused, we'll block for new messages. If we're not
79087 * paused, we'll process anything we can peek but won't block
79088 * for more. Detach (and re-attach) handling is all localized
79089 * to duk_debug_process_messages() too.
79090 *
79091 * Debugger writes outside the message loop may cause debugger
79092 * detach1 phase to run, after which dbg_read_cb == NULL and
79093 * dbg_detaching != 0. The message loop will finish the detach
79094 * by running detach2 phase, so enter the message loop also when
79095 * detaching.
79096 */
79097
79098 if (process_messages) {
79099 DUK_ASSERT(thr->heap->dbg_processing == 0);
79100 processed_messages = duk_debug_process_messages(thr, 0 /*no_block*/);
79101 DUK_ASSERT(thr->heap->dbg_processing == 0);
79102 }
79103
79104 /* Continue checked execution if there are breakpoints or we're stepping.
79105 * Also use checked execution if paused flag is active - it shouldn't be
79106 * because the debug message loop shouldn't terminate if it was. Step out
79107 * is handled by callstack unwind and doesn't need checked execution.
79108 * Note that debugger may have detached due to error or explicit request
79109 * above, so we must recheck attach status.
79110 */
79111
79112 if (duk_debug_is_attached(thr->heap)) {
79113 DUK_ASSERT(act == thr->callstack_curr);
79114 DUK_ASSERT(act != NULL);
79115 if (act->flags & DUK_ACT_FLAG_BREAKPOINT_ACTIVE || (thr->heap->dbg_pause_flags & DUK_PAUSE_FLAG_ONE_OPCODE) ||
79116 ((thr->heap->dbg_pause_flags & DUK_PAUSE_FLAG_LINE_CHANGE) &&
79117 thr->heap->dbg_pause_act == thr->callstack_curr) ||
79119 *out_immediate = 1;
79120 }
79122 /* If we processed any debug messages breakpoints may have
79123 * changed; restart execution to re-check active breakpoints.
79124 */
79125 if (processed_messages) {
79126 DUK_D(DUK_DPRINT("processed debug messages, restart execution to recheck possibly changed breakpoints"));
79127 *out_interrupt_retval = DUK__INT_RESTART;
79128 } else {
79129 if (thr->heap->dbg_pause_flags & DUK_PAUSE_FLAG_ONE_OPCODE) {
79130 /* Set 'pause after one opcode' active only when we're
79131 * actually just about to execute code.
79132 */
79133 thr->heap->dbg_pause_flags |= DUK_PAUSE_FLAG_ONE_OPCODE_ACTIVE;
79134 }
79135 }
79136 } else {
79137 DUK_D(DUK_DPRINT("debugger became detached, resume normal execution"));
79138 }
79139}
79140#endif /* DUK_USE_DEBUGGER_SUPPORT */
79141
79143 duk_int_t ctr;
79144 duk_activation *act;
79145 duk_hcompfunc *fun;
79146 duk_bool_t immediate = 0;
79147 duk_small_uint_t retval;
79148
79149 DUK_ASSERT(thr != NULL);
79150 DUK_ASSERT(thr->heap != NULL);
79151 DUK_ASSERT(thr->callstack_top > 0);
79152
79153#if defined(DUK_USE_DEBUG)
79154 thr->heap->inst_count_interrupt += thr->interrupt_init;
79155 DUK_DD(DUK_DDPRINT("execution interrupt, counter=%ld, init=%ld, "
79156 "instruction counts: executor=%ld, interrupt=%ld",
79157 (long) thr->interrupt_counter,
79158 (long) thr->interrupt_init,
79159 (long) thr->heap->inst_count_exec,
79160 (long) thr->heap->inst_count_interrupt));
79161#endif
79162
79163 retval = DUK__INT_NOACTION;
79165
79166 /*
79167 * Avoid nested calls. Concretely this happens during debugging, e.g.
79168 * when we eval() an expression.
79169 *
79170 * Also don't interrupt if we're currently doing debug processing
79171 * (which can be initiated outside the bytecode executor) as this
79172 * may cause the debugger to be called recursively. Check required
79173 * for correct operation of throw intercept and other "exotic" halting
79174 * scenarios.
79175 */
79176
79177#if defined(DUK_USE_DEBUGGER_SUPPORT)
79178 if (DUK_HEAP_HAS_INTERRUPT_RUNNING(thr->heap) || thr->heap->dbg_processing) {
79179#else
79181#endif
79182 DUK_DD(DUK_DDPRINT("nested executor interrupt, ignoring"));
79183
79184 /* Set a high interrupt counter; the original executor
79185 * interrupt invocation will rewrite before exiting.
79186 */
79187 thr->interrupt_init = ctr;
79188 thr->interrupt_counter = ctr - 1;
79189 return DUK__INT_NOACTION;
79190 }
79192
79193 act = thr->callstack_curr;
79194 DUK_ASSERT(act != NULL);
79195
79196 fun = (duk_hcompfunc *) DUK_ACT_GET_FUNC(act);
79198
79199 DUK_UNREF(fun);
79200
79201#if defined(DUK_USE_EXEC_TIMEOUT_CHECK)
79202 /*
79203 * Execution timeout check
79204 */
79205
79207 /* Keep throwing an error whenever we get here. The unusual values
79208 * are set this way because no instruction is ever executed, we just
79209 * throw an error until all try/catch/finally and other catchpoints
79210 * have been exhausted. Duktape/C code gets control at each protected
79211 * call but whenever it enters back into Duktape the RangeError gets
79212 * raised. User exec timeout check must consistently indicate a timeout
79213 * until we've fully bubbled out of Duktape.
79214 */
79215 DUK_D(DUK_DPRINT("execution timeout, throwing a RangeError"));
79216 thr->interrupt_init = 0;
79217 thr->interrupt_counter = 0;
79219 DUK_ERROR_RANGE(thr, "execution timeout");
79220 DUK_WO_NORETURN(return 0;);
79221 }
79222#endif /* DUK_USE_EXEC_TIMEOUT_CHECK */
79223
79224#if defined(DUK_USE_DEBUGGER_SUPPORT)
79225 if (!thr->heap->dbg_processing && (thr->heap->dbg_read_cb != NULL || thr->heap->dbg_detaching)) {
79226 /* Avoid recursive re-entry; enter when we're attached or
79227 * detaching (to finish off the pending detach).
79228 */
79229 duk__interrupt_handle_debugger(thr, &immediate, &retval);
79230 DUK_ASSERT(act == thr->callstack_curr);
79231 }
79232#endif /* DUK_USE_DEBUGGER_SUPPORT */
79233
79234 /*
79235 * Update the interrupt counter
79236 */
79237
79238 if (immediate) {
79239 /* Cause an interrupt after executing one instruction. */
79240 ctr = 1;
79241 }
79242
79243 /* The counter value is one less than the init value: init value should
79244 * indicate how many instructions are executed before interrupt. To
79245 * execute 1 instruction (after interrupt handler return), counter must
79246 * be 0.
79247 */
79248 DUK_ASSERT(ctr >= 1);
79249 thr->interrupt_init = ctr;
79250 thr->interrupt_counter = ctr - 1;
79252
79253 return retval;
79254}
79255#endif /* DUK_USE_INTERRUPT_COUNTER */
79256
79257/*
79258 * Debugger handling for executor restart
79259 *
79260 * Check for breakpoints, stepping, etc, and figure out if we should execute
79261 * in checked or normal mode. Note that we can't do this when an activation
79262 * is created, because breakpoint status (and stepping status) may change
79263 * later, so we must recheck every time we're executing an activation.
79264 * This primitive should be side effect free to avoid changes during check.
79265 */
79266
79267#if defined(DUK_USE_DEBUGGER_SUPPORT)
79268DUK_LOCAL void duk__executor_recheck_debugger(duk_hthread *thr, duk_activation *act, duk_hcompfunc *fun) {
79269 duk_heap *heap;
79270 duk_tval *tv_tmp;
79271 duk_hstring *filename;
79272 duk_small_uint_t bp_idx;
79273 duk_breakpoint **bp_active;
79274
79275 DUK_ASSERT(thr != NULL);
79276 DUK_ASSERT(act != NULL);
79277 DUK_ASSERT(fun != NULL);
79278
79279 heap = thr->heap;
79280 bp_active = heap->dbg_breakpoints_active;
79281 act->flags &= ~DUK_ACT_FLAG_BREAKPOINT_ACTIVE;
79282
79284 if (tv_tmp && DUK_TVAL_IS_STRING(tv_tmp)) {
79285 filename = DUK_TVAL_GET_STRING(tv_tmp);
79286
79287 /* Figure out all active breakpoints. A breakpoint is
79288 * considered active if the current function's fileName
79289 * matches the breakpoint's fileName, AND there is no
79290 * inner function that has matching line numbers
79291 * (otherwise a breakpoint would be triggered both
79292 * inside and outside of the inner function which would
79293 * be confusing). Example:
79294 *
79295 * function foo() {
79296 * print('foo');
79297 * function bar() { <-. breakpoints in these
79298 * print('bar'); | lines should not affect
79299 * } <-' foo() execution
79300 * bar();
79301 * }
79302 *
79303 * We need a few things that are only available when
79304 * debugger support is enabled: (1) a line range for
79305 * each function, and (2) access to the function
79306 * template to access the inner functions (and their
79307 * line ranges).
79308 *
79309 * It's important to have a narrow match for active
79310 * breakpoints so that we don't enter checked execution
79311 * when that's not necessary. For instance, if we're
79312 * running inside a certain function and there's
79313 * breakpoint outside in (after the call site), we
79314 * don't want to slow down execution of the function.
79315 */
79316
79317 for (bp_idx = 0; bp_idx < heap->dbg_breakpoint_count; bp_idx++) {
79318 duk_breakpoint *bp = heap->dbg_breakpoints + bp_idx;
79319 duk_hobject **funcs, **funcs_end;
79320 duk_hcompfunc *inner_fun;
79321 duk_bool_t bp_match;
79322
79323 if (bp->filename == filename && bp->line >= fun->start_line && bp->line <= fun->end_line) {
79324 bp_match = 1;
79325 DUK_DD(DUK_DDPRINT("breakpoint filename and line match: "
79326 "%s:%ld vs. %s (line %ld vs. %ld-%ld)",
79328 (long) bp->line,
79329 DUK_HSTRING_GET_DATA(filename),
79330 (long) bp->line,
79331 (long) fun->start_line,
79332 (long) fun->end_line));
79333
79334 funcs = DUK_HCOMPFUNC_GET_FUNCS_BASE(thr->heap, fun);
79335 funcs_end = DUK_HCOMPFUNC_GET_FUNCS_END(thr->heap, fun);
79336 while (funcs != funcs_end) {
79337 inner_fun = (duk_hcompfunc *) *funcs;
79339 if (bp->line >= inner_fun->start_line && bp->line <= inner_fun->end_line) {
79340 DUK_DD(DUK_DDPRINT("inner function masks ('captures') breakpoint"));
79341 bp_match = 0;
79342 break;
79343 }
79344 funcs++;
79345 }
79346
79347 if (bp_match) {
79348 /* No need to check for size of bp_active list,
79349 * it's always larger than maximum number of
79350 * breakpoints.
79351 */
79353 *bp_active = heap->dbg_breakpoints + bp_idx;
79354 bp_active++;
79355 }
79356 }
79357 }
79358 }
79359
79360 *bp_active = NULL; /* terminate */
79361
79362 DUK_DD(DUK_DDPRINT("ACTIVE BREAKPOINTS: %ld", (long) (bp_active - thr->heap->dbg_breakpoints_active)));
79363
79364 /* Force pause if we were doing "step into" in another activation. */
79365 if ((thr->heap->dbg_pause_flags & DUK_PAUSE_FLAG_FUNC_ENTRY) && thr->heap->dbg_pause_act != thr->callstack_curr) {
79366 DUK_D(DUK_DPRINT("PAUSE TRIGGERED by function entry"));
79367 duk_debug_set_paused(thr->heap);
79368 }
79369
79370 /* Force interrupt right away if we're paused or in "checked mode".
79371 * Step out is handled by callstack unwind.
79372 */
79374 ((thr->heap->dbg_pause_flags & DUK_PAUSE_FLAG_LINE_CHANGE) && thr->heap->dbg_pause_act == thr->callstack_curr)) {
79375 /* We'll need to interrupt early so recompute the init
79376 * counter to reflect the number of bytecode instructions
79377 * executed so that step counts for e.g. debugger rate
79378 * limiting are accurate.
79379 */
79382 thr->interrupt_counter = 0;
79383 }
79384}
79385#endif /* DUK_USE_DEBUGGER_SUPPORT */
79386
79387/*
79388 * Opcode handlers for opcodes with a lot of code and which are relatively
79389 * rare; NOINLINE to reduce amount of code in main bytecode dispatcher.
79390 */
79391
79393 duk_bool_t is_set = (DUK_DEC_OP(ins) == DUK_OP_INITSET);
79394 duk_uint_fast_t idx;
79395 duk_uint_t defprop_flags;
79396
79397 /* A -> object register (acts as a source)
79398 * BC -> BC+0 contains key, BC+1 closure (value)
79399 */
79401 /* INITSET/INITGET are only used to initialize object literal keys.
79402 * There may be a previous propery in ES2015 because duplicate property
79403 * names are allowed.
79404 */
79405
79406 /* This could be made more optimal by accessing internals directly. */
79407
79408 idx = (duk_uint_fast_t) DUK_DEC_BC(ins);
79409 duk_dup(thr, (duk_idx_t) (idx + 0)); /* key */
79410 duk_dup(thr, (duk_idx_t) (idx + 1)); /* getter/setter */
79411 if (is_set) {
79412 defprop_flags =
79414 } else {
79415 defprop_flags =
79417 }
79418 duk_def_prop(thr, (duk_idx_t) DUK_DEC_A(ins), defprop_flags);
79419}
79420
79422 duk_activation *act;
79423 duk_catcher *cat;
79424 duk_tval *tv1;
79427
79428 /* A -> flags
79429 * BC -> reg_catch; base register for two registers used both during
79430 * trycatch setup and when catch is triggered
79431 *
79432 * If DUK_BC_TRYCATCH_FLAG_CATCH_BINDING set:
79433 * reg_catch + 0: catch binding variable name (string).
79434 * Automatic declarative environment is established for
79435 * the duration of the 'catch' clause.
79436 *
79437 * If DUK_BC_TRYCATCH_FLAG_WITH_BINDING set:
79438 * reg_catch + 0: with 'target value', which is coerced to
79439 * an object and then used as a bindind object for an
79440 * environment record. The binding is initialized here, for
79441 * the 'try' clause.
79442 *
79443 * Note that a TRYCATCH generated for a 'with' statement has no
79444 * catch or finally parts.
79445 */
79446
79447 /* XXX: TRYCATCH handling should be reworked to avoid creating
79448 * an explicit scope unless it is actually needed (e.g. function
79449 * instances or eval is executed inside the catch block). This
79450 * rework is not trivial because the compiler doesn't have an
79451 * intermediate representation. When the rework is done, the
79452 * opcode format can also be made more straightforward.
79453 */
79454
79455 /* XXX: side effect handling is quite awkward here */
79456
79457 DUK_DDD(DUK_DDDPRINT("TRYCATCH: reg_catch=%ld, have_catch=%ld, "
79458 "have_finally=%ld, catch_binding=%ld, with_binding=%ld (flags=0x%02lx)",
79459 (long) DUK_DEC_BC(ins),
79460 (long) (DUK_DEC_A(ins) & DUK_BC_TRYCATCH_FLAG_HAVE_CATCH ? 1 : 0),
79461 (long) (DUK_DEC_A(ins) & DUK_BC_TRYCATCH_FLAG_HAVE_FINALLY ? 1 : 0),
79462 (long) (DUK_DEC_A(ins) & DUK_BC_TRYCATCH_FLAG_CATCH_BINDING ? 1 : 0),
79463 (long) (DUK_DEC_A(ins) & DUK_BC_TRYCATCH_FLAG_WITH_BINDING ? 1 : 0),
79464 (unsigned long) DUK_DEC_A(ins)));
79465
79466 a = DUK_DEC_A(ins);
79467 bc = DUK_DEC_BC(ins);
79468
79469 /* Registers 'bc' and 'bc + 1' are written in longjmp handling
79470 * and if their previous values (which are temporaries) become
79471 * unreachable -and- have a finalizer, there'll be a function
79472 * call during error handling which is not supported now (GH-287).
79473 * Ensure that both 'bc' and 'bc + 1' have primitive values to
79474 * guarantee no finalizer calls in error handling. Scrubbing also
79475 * ensures finalizers for the previous values run here rather than
79476 * later. Error handling related values are also written to 'bc'
79477 * and 'bc + 1' but those values never become unreachable during
79478 * error handling, so there's no side effect problem even if the
79479 * error value has a finalizer.
79480 */
79481 duk_dup(thr, (duk_idx_t) bc); /* Stabilize value. */
79482 duk_to_undefined(thr, (duk_idx_t) bc);
79483 duk_to_undefined(thr, (duk_idx_t) (bc + 1));
79484
79485 /* Allocate catcher and populate it. Doesn't have to
79486 * be fully atomic, but the catcher must be in a
79487 * consistent state if side effects (such as finalizer
79488 * calls) occur.
79489 */
79490
79491 cat = duk_hthread_catcher_alloc(thr);
79492 DUK_ASSERT(cat != NULL);
79493
79494 cat->flags = DUK_CAT_TYPE_TCF;
79495 cat->h_varname = NULL;
79496 cat->pc_base = (duk_instr_t *) curr_pc; /* pre-incremented, points to first jump slot */
79497 cat->idx_base = (duk_size_t) (thr->valstack_bottom - thr->valstack) + bc;
79498
79499 act = thr->callstack_curr;
79500 DUK_ASSERT(act != NULL);
79501 cat->parent = act->cat;
79502 act->cat = cat;
79503
79506 }
79509 }
79511 DUK_DDD(DUK_DDDPRINT("catch binding flag set to catcher"));
79513 tv1 = DUK_GET_TVAL_NEGIDX(thr, -1);
79515
79516 /* borrowed reference; although 'tv1' comes from a register,
79517 * its value was loaded using LDCONST so the constant will
79518 * also exist and be reachable.
79519 */
79520 cat->h_varname = DUK_TVAL_GET_STRING(tv1);
79521 } else if (a & DUK_BC_TRYCATCH_FLAG_WITH_BINDING) {
79522 duk_hobjenv *env;
79523 duk_hobject *target;
79524
79525 /* Delayed env initialization for activation (if needed). */
79526 DUK_ASSERT(thr->callstack_top >= 1);
79527 DUK_ASSERT(act == thr->callstack_curr);
79528 DUK_ASSERT(act != NULL);
79529 if (act->lex_env == NULL) {
79530 DUK_DDD(DUK_DDDPRINT("delayed environment initialization"));
79531 DUK_ASSERT(act->var_env == NULL);
79532
79534 DUK_ASSERT(act == thr->callstack_curr);
79535 DUK_UNREF(act); /* 'act' is no longer accessed, scanbuild fix */
79536 }
79537 DUK_ASSERT(act->lex_env != NULL);
79538 DUK_ASSERT(act->var_env != NULL);
79539
79540 /* Coerce 'with' target. */
79541 target = duk_to_hobject(thr, -1);
79542 DUK_ASSERT(target != NULL);
79543
79544 /* Create an object environment; it is not pushed
79545 * so avoid side effects very carefully until it is
79546 * referenced.
79547 */
79549 DUK_ASSERT(env != NULL);
79550 DUK_ASSERT(DUK_HOBJECT_GET_PROTOTYPE(thr->heap, (duk_hobject *) env) == NULL);
79551 env->target = target; /* always provideThis=true */
79552 DUK_HOBJECT_INCREF(thr, target);
79553 env->has_this = 1;
79555 DUK_DDD(DUK_DDDPRINT("environment for with binding: %!iO", env));
79556
79557 DUK_ASSERT(act == thr->callstack_curr);
79558 DUK_ASSERT(DUK_HOBJECT_GET_PROTOTYPE(thr->heap, (duk_hobject *) env) == NULL);
79559 DUK_ASSERT(act->lex_env != NULL);
79561 act->lex_env = (duk_hobject *) env; /* Now reachable. */
79562 DUK_HOBJECT_INCREF(thr, (duk_hobject *) env);
79563 /* Net refcount change to act->lex_env is 0: incref for env's
79564 * prototype, decref for act->lex_env overwrite.
79566
79567 /* Set catcher lex_env active (affects unwind)
79568 * only when the whole setup is complete.
79569 */
79570 cat = act->cat; /* XXX: better to relookup? not mandatory because 'cat' is stable */
79572 } else {
79573 ;
79574 }
79575
79576 DUK_DDD(DUK_DDDPRINT("TRYCATCH catcher: flags=0x%08lx, pc_base=%ld, "
79577 "idx_base=%ld, h_varname=%!O",
79578 (unsigned long) cat->flags,
79579 (long) cat->pc_base,
79580 (long) cat->idx_base,
79581 (duk_heaphdr *) cat->h_varname));
79582
79583 duk_pop_unsafe(thr);
79584}
79585
79587 duk_activation *act;
79588 duk_catcher *cat;
79589 duk_tval *tv1;
79590 duk_instr_t *pc_base;
79591
79592 DUK_UNREF(ins);
79593
79594 DUK_ASSERT(thr->callstack_top >= 1);
79595 act = thr->callstack_curr;
79596 DUK_ASSERT(act != NULL);
79597 cat = act->cat;
79598 DUK_ASSERT(cat != NULL);
79600
79601 DUK_DDD(DUK_DDDPRINT("ENDTRY: clearing catch active flag (regardless of whether it was set or not)"));
79603
79604 pc_base = cat->pc_base;
79605
79606 if (DUK_CAT_HAS_FINALLY_ENABLED(cat)) {
79607 DUK_DDD(DUK_DDDPRINT("ENDTRY: finally part is active, jump through 2nd jump slot with 'normal continuation'"));
79608
79609 tv1 = thr->valstack + cat->idx_base;
79610 DUK_ASSERT(tv1 >= thr->valstack && tv1 < thr->valstack_top);
79611 DUK_TVAL_SET_UNDEFINED_UPDREF(thr, tv1); /* side effects */
79612 tv1 = NULL;
79613
79614 tv1 = thr->valstack + cat->idx_base + 1;
79615 DUK_ASSERT(tv1 >= thr->valstack && tv1 < thr->valstack_top);
79616 DUK_TVAL_SET_U32_UPDREF(thr, tv1, (duk_uint32_t) DUK_LJ_TYPE_NORMAL); /* side effects */
79617 tv1 = NULL;
79618
79620 } else {
79621 DUK_DDD(
79622 DUK_DDDPRINT("ENDTRY: no finally part, dismantle catcher, jump through 2nd jump slot (to end of statement)"));
79623
79624 duk_hthread_catcher_unwind_norz(thr, act); /* lexenv may be set for 'with' binding */
79625 /* no need to unwind callstack */
79626 }
79627
79628 return pc_base + 1; /* new curr_pc value */
79629}
79630
79632 duk_activation *act;
79633 duk_catcher *cat;
79634 duk_tval *tv1;
79635 duk_instr_t *pc_base;
79636
79637 DUK_UNREF(ins);
79638
79639 DUK_ASSERT(thr->callstack_top >= 1);
79640 act = thr->callstack_curr;
79641 DUK_ASSERT(act != NULL);
79642 cat = act->cat;
79643 DUK_ASSERT(cat != NULL);
79644 DUK_ASSERT(!DUK_CAT_HAS_CATCH_ENABLED(cat)); /* cleared before entering catch part */
79645
79646 if (DUK_CAT_HAS_LEXENV_ACTIVE(cat)) {
79647 duk_hobject *prev_env;
79648
79649 /* 'with' binding has no catch clause, so can't be here unless a normal try-catch */
79651 DUK_ASSERT(act->lex_env != NULL);
79652
79653 DUK_DDD(DUK_DDDPRINT("ENDCATCH: popping catcher part lexical environment"));
79654
79655 prev_env = act->lex_env;
79656 DUK_ASSERT(prev_env != NULL);
79657 act->lex_env = DUK_HOBJECT_GET_PROTOTYPE(thr->heap, prev_env);
79659 DUK_HOBJECT_INCREF(thr, act->lex_env);
79660 DUK_HOBJECT_DECREF(thr, prev_env); /* side effects */
79661
79662 DUK_ASSERT(act == thr->callstack_curr);
79663 DUK_ASSERT(act != NULL);
79664 }
79665
79666 pc_base = cat->pc_base;
79667
79668 if (DUK_CAT_HAS_FINALLY_ENABLED(cat)) {
79669 DUK_DDD(DUK_DDDPRINT("ENDCATCH: finally part is active, jump through 2nd jump slot with 'normal continuation'"));
79670
79671 tv1 = thr->valstack + cat->idx_base;
79672 DUK_ASSERT(tv1 >= thr->valstack && tv1 < thr->valstack_top);
79673 DUK_TVAL_SET_UNDEFINED_UPDREF(thr, tv1); /* side effects */
79674 tv1 = NULL;
79675
79676 tv1 = thr->valstack + cat->idx_base + 1;
79677 DUK_ASSERT(tv1 >= thr->valstack && tv1 < thr->valstack_top);
79678 DUK_TVAL_SET_U32_UPDREF(thr, tv1, (duk_uint32_t) DUK_LJ_TYPE_NORMAL); /* side effects */
79679 tv1 = NULL;
79680
79682 } else {
79683 DUK_DDD(
79684 DUK_DDDPRINT("ENDCATCH: no finally part, dismantle catcher, jump through 2nd jump slot (to end of statement)"));
79685
79687 /* no need to unwind callstack */
79688 }
79689
79690 return pc_base + 1; /* new curr_pc value */
79691}
79692
79695 duk_activation *entry_act) {
79696 duk_activation *act;
79697 duk_tval *tv1;
79698 duk_uint_t reg_catch;
79699 duk_small_uint_t cont_type;
79700 duk_small_uint_t ret_result;
79701
79702 DUK_ASSERT(thr->ptr_curr_pc == NULL);
79703 DUK_ASSERT(thr->callstack_top >= 1);
79704 act = thr->callstack_curr;
79705 DUK_ASSERT(act != NULL);
79706 reg_catch = DUK_DEC_ABC(ins);
79707
79708 /* CATCH flag may be enabled or disabled here; it may be enabled if
79709 * the statement has a catch block but the try block does not throw
79710 * an error.
79711 */
79712
79713 DUK_DDD(DUK_DDDPRINT("ENDFIN: completion value=%!T, type=%!T",
79714 (duk_tval *) (thr->valstack_bottom + reg_catch + 0),
79715 (duk_tval *) (thr->valstack_bottom + reg_catch + 1)));
79716
79717 tv1 = thr->valstack_bottom + reg_catch + 1; /* type */
79719#if defined(DUK_USE_FASTINT)
79721 cont_type = (duk_small_uint_t) DUK_TVAL_GET_FASTINT_U32(tv1);
79722#else
79723 cont_type = (duk_small_uint_t) DUK_TVAL_GET_NUMBER(tv1);
79724#endif
79725
79726 tv1--; /* value */
79727
79728 switch (cont_type) {
79729 case DUK_LJ_TYPE_NORMAL: {
79730 DUK_DDD(DUK_DDDPRINT("ENDFIN: finally part finishing with 'normal' (non-abrupt) completion -> "
79731 "dismantle catcher, resume execution after ENDFIN"));
79732
79734 /* no need to unwind callstack */
79735 return 0; /* restart execution */
79736 }
79737 case DUK_LJ_TYPE_RETURN: {
79738 DUK_DDD(DUK_DDDPRINT("ENDFIN: finally part finishing with 'return' complation -> dismantle "
79739 "catcher, handle return, lj.value1=%!T",
79740 tv1));
79741
79742 /* Not necessary to unwind catch stack: return handling will
79743 * do it. The finally flag of 'cat' is no longer set. The
79744 * catch flag may be set, but it's not checked by return handling.
79745 */
79746
79747 duk_push_tval(thr, tv1);
79748 ret_result = duk__handle_return(thr, entry_act);
79749 if (ret_result == DUK__RETHAND_RESTART) {
79750 return 0; /* restart execution */
79751 }
79752 DUK_ASSERT(ret_result == DUK__RETHAND_FINISHED);
79753
79754 DUK_DDD(DUK_DDDPRINT("exiting executor after ENDFIN and RETURN (pseudo) longjmp type"));
79755 return 1; /* exit executor */
79756 }
79757 case DUK_LJ_TYPE_BREAK:
79758 case DUK_LJ_TYPE_CONTINUE: {
79759 duk_uint_t label_id;
79760 duk_small_uint_t lj_type;
79761
79762 /* Not necessary to unwind catch stack: break/continue
79763 * handling will do it. The finally flag of 'cat' is
79764 * no longer set. The catch flag may be set, but it's
79765 * not checked by break/continue handling.
79766 */
79767
79769#if defined(DUK_USE_FASTINT)
79772#else
79773 label_id = (duk_small_uint_t) DUK_TVAL_GET_NUMBER(tv1);
79774#endif
79775 lj_type = cont_type;
79776 duk__handle_break_or_continue(thr, label_id, lj_type);
79777 return 0; /* restart execution */
79778 }
79779 default: {
79780 DUK_DDD(DUK_DDDPRINT("ENDFIN: finally part finishing with abrupt completion, lj_type=%ld -> "
79781 "dismantle catcher, re-throw error",
79782 (long) cont_type));
79783
79784 duk_err_setup_ljstate1(thr, (duk_small_uint_t) cont_type, tv1);
79785 /* No debugger Throw notify check on purpose (rethrow). */
79786
79787 DUK_ASSERT(thr->heap->lj.jmpbuf_ptr != NULL); /* always in executor */
79788 duk_err_longjmp(thr);
79790 }
79791 }
79792
79794 return 0;
79795}
79796
79800
79801 /*
79802 * Enumeration semantics come from for-in statement, E5 Section 12.6.4.
79803 * If called with 'null' or 'undefined', this opcode returns 'null' as
79804 * the enumerator, which is special cased in NEXTENUM. This simplifies
79805 * the compiler part
79806 */
79807
79808 /* B -> register for writing enumerator object
79809 * C -> value to be enumerated (register)
79810 */
79811 b = DUK_DEC_B(ins);
79812 c = DUK_DEC_C(ins);
79813
79814 if (duk_is_null_or_undefined(thr, (duk_idx_t) c)) {
79815 duk_push_null(thr);
79816 duk_replace(thr, (duk_idx_t) b);
79817 } else {
79818 duk_dup(thr, (duk_idx_t) c);
79819 duk_to_object(thr, -1);
79820 duk_hobject_enumerator_create(thr, 0 /*enum_flags*/); /* [ ... val ] --> [ ... enum ] */
79821 duk_replace(thr, (duk_idx_t) b);
79822 }
79823}
79824
79828 duk_small_uint_t pc_skip = 0;
79829
79830 /*
79831 * NEXTENUM checks whether the enumerator still has unenumerated
79832 * keys. If so, the next key is loaded to the target register
79833 * and the next instruction is skipped. Otherwise the next instruction
79834 * will be executed, jumping out of the enumeration loop.
79835 */
79836
79837 /* B -> target register for next key
79838 * C -> enum register
79839 */
79840 b = DUK_DEC_B(ins);
79841 c = DUK_DEC_C(ins);
79842
79843 DUK_DDD(DUK_DDDPRINT("NEXTENUM: b->%!T, c->%!T",
79844 (duk_tval *) duk_get_tval(thr, (duk_idx_t) b),
79845 (duk_tval *) duk_get_tval(thr, (duk_idx_t) c)));
79846
79847 if (duk_is_object(thr, (duk_idx_t) c)) {
79848 /* XXX: assert 'c' is an enumerator */
79849 duk_dup(thr, (duk_idx_t) c);
79850 if (duk_hobject_enumerator_next(thr, 0 /*get_value*/)) {
79851 /* [ ... enum ] -> [ ... next_key ] */
79852 DUK_DDD(DUK_DDDPRINT("enum active, next key is %!T, skip jump slot ", (duk_tval *) duk_get_tval(thr, -1)));
79853 pc_skip = 1;
79854 } else {
79855 /* [ ... enum ] -> [ ... ] */
79856 DUK_DDD(DUK_DDDPRINT("enum finished, execute jump slot"));
79857 DUK_ASSERT(DUK_TVAL_IS_UNDEFINED(thr->valstack_top)); /* valstack policy */
79858 thr->valstack_top++;
79859 }
79860 duk_replace(thr, (duk_idx_t) b);
79861 } else {
79862 /* 'null' enumerator case -> behave as with an empty enumerator */
79863 DUK_ASSERT(duk_is_null(thr, (duk_idx_t) c));
79864 DUK_DDD(DUK_DDDPRINT("enum is null, execute jump slot"));
79865 }
79866
79867 return pc_skip;
79868}
79869
79870/*
79871 * Call handling helpers.
79872 */
79873
79875 duk_bool_t rc;
79876
79877 duk_set_top_unsafe(thr, (duk_idx_t) (idx + nargs + 2)); /* [ ... func this arg1 ... argN ] */
79878
79879 /* Attempt an Ecma-to-Ecma call setup. If the call
79880 * target is (directly or indirectly) Reflect.construct(),
79881 * the call may change into a constructor call on the fly.
79882 */
79883 rc = (duk_bool_t) duk_handle_call_unprotected(thr, idx, call_flags);
79884 if (rc != 0) {
79885 /* Ecma-to-ecma call possible, may or may not
79886 * be a tail call. Avoid C recursion by
79887 * reusing current executor instance.
79888 */
79889 DUK_DDD(DUK_DDDPRINT("ecma-to-ecma call setup possible, restart execution"));
79890 /* curr_pc synced by duk_handle_call_unprotected() */
79891 DUK_ASSERT(thr->ptr_curr_pc == NULL);
79892 return rc;
79893 } else {
79894 /* Call was handled inline. */
79895 }
79896 DUK_ASSERT(thr->ptr_curr_pc != NULL);
79897 return rc;
79898}
79899
79900/*
79901 * ECMAScript bytecode executor.
79902 *
79903 * Resume execution for the current thread from its current activation.
79904 * Returns when execution would return from the entry level activation,
79905 * leaving a single return value on top of the stack. Function calls
79906 * and thread resumptions are handled internally. If an error occurs,
79907 * a longjmp() with type DUK_LJ_TYPE_THROW is called on the entry level
79908 * setjmp() jmpbuf.
79909 *
79910 * ECMAScript function calls and coroutine resumptions are handled
79911 * internally (by the outer executor function) without recursive C calls.
79912 * Other function calls are handled using duk_handle_call(), increasing
79913 * C recursion depth.
79914 *
79915 * Abrupt completions (= long control tranfers) are handled either
79916 * directly by reconfiguring relevant stacks and restarting execution,
79917 * or via a longjmp. Longjmp-free handling is preferable for performance
79918 * (especially Emscripten performance), and is used for: break, continue,
79919 * and return.
79920 *
79921 * For more detailed notes, see doc/execution.rst.
79923 * Also see doc/code-issues.rst for discussion of setjmp(), longjmp(),
79924 * and volatile.
79926
79927/* Presence of 'fun' is config based, there's a marginal performance
79928 * difference and the best option is architecture dependent.
79929 */
79930#if defined(DUK_USE_EXEC_FUN_LOCAL)
79931#define DUK__FUN() fun
79932#else
79933#define DUK__FUN() ((duk_hcompfunc *) DUK_ACT_GET_FUNC((thr)->callstack_curr))
79934#endif
79936/* Strict flag. */
79937#define DUK__STRICT() ((duk_small_uint_t) DUK_HOBJECT_HAS_STRICT((duk_hobject *) DUK__FUN()))
79938
79939/* Reg/const access macros: these are very footprint and performance sensitive
79940 * so modify with care. Arguments are sometimes evaluated multiple times which
79941 * is not ideal.
79943#define DUK__REG(x) (*(thr->valstack_bottom + (x)))
79944#define DUK__REGP(x) (thr->valstack_bottom + (x))
79945#define DUK__CONST(x) (*(consts + (x)))
79946#define DUK__CONSTP(x) (consts + (x))
79948/* Reg/const access macros which take the 32-bit instruction and avoid an
79949 * explicit field decoding step by using shifts and masks. These must be
79950 * kept in sync with duk_js_bytecode.h. The shift/mask values are chosen
79951 * so that 'ins' can be shifted and masked and used as a -byte- offset
79952 * instead of a duk_tval offset which needs further shifting (which is an
79953 * issue on some, but not all, CPUs).
79954 */
79955#define DUK__RCBIT_B DUK_BC_REGCONST_B
79956#define DUK__RCBIT_C DUK_BC_REGCONST_C
79957#if defined(DUK_USE_EXEC_REGCONST_OPTIMIZE)
79958#if defined(DUK_USE_PACKED_TVAL)
79959#define DUK__TVAL_SHIFT 3 /* sizeof(duk_tval) == 8 */
79960#else
79961#define DUK__TVAL_SHIFT 4 /* sizeof(duk_tval) == 16; not always the case so also asserted for */
79962#endif
79963#define DUK__SHIFT_A (DUK_BC_SHIFT_A - DUK__TVAL_SHIFT)
79964#define DUK__SHIFT_B (DUK_BC_SHIFT_B - DUK__TVAL_SHIFT)
79965#define DUK__SHIFT_C (DUK_BC_SHIFT_C - DUK__TVAL_SHIFT)
79966#define DUK__SHIFT_BC (DUK_BC_SHIFT_BC - DUK__TVAL_SHIFT)
79967#define DUK__MASK_A (DUK_BC_UNSHIFTED_MASK_A << DUK__TVAL_SHIFT)
79968#define DUK__MASK_B (DUK_BC_UNSHIFTED_MASK_B << DUK__TVAL_SHIFT)
79969#define DUK__MASK_C (DUK_BC_UNSHIFTED_MASK_C << DUK__TVAL_SHIFT)
79970#define DUK__MASK_BC (DUK_BC_UNSHIFTED_MASK_BC << DUK__TVAL_SHIFT)
79971#define DUK__BYTEOFF_A(ins) (((ins) >> DUK__SHIFT_A) & DUK__MASK_A)
79972#define DUK__BYTEOFF_B(ins) (((ins) >> DUK__SHIFT_B) & DUK__MASK_B)
79973#define DUK__BYTEOFF_C(ins) (((ins) >> DUK__SHIFT_C) & DUK__MASK_C)
79974#define DUK__BYTEOFF_BC(ins) (((ins) >> DUK__SHIFT_BC) & DUK__MASK_BC)
79975
79976#define DUK__REGP_A(ins) ((duk_tval *) (void *) ((duk_uint8_t *) thr->valstack_bottom + DUK__BYTEOFF_A((ins))))
79977#define DUK__REGP_B(ins) ((duk_tval *) (void *) ((duk_uint8_t *) thr->valstack_bottom + DUK__BYTEOFF_B((ins))))
79978#define DUK__REGP_C(ins) ((duk_tval *) (void *) ((duk_uint8_t *) thr->valstack_bottom + DUK__BYTEOFF_C((ins))))
79979#define DUK__REGP_BC(ins) ((duk_tval *) (void *) ((duk_uint8_t *) thr->valstack_bottom + DUK__BYTEOFF_BC((ins))))
79980#define DUK__CONSTP_A(ins) ((duk_tval *) (void *) ((duk_uint8_t *) consts + DUK__BYTEOFF_A((ins))))
79981#define DUK__CONSTP_B(ins) ((duk_tval *) (void *) ((duk_uint8_t *) consts + DUK__BYTEOFF_B((ins))))
79982#define DUK__CONSTP_C(ins) ((duk_tval *) (void *) ((duk_uint8_t *) consts + DUK__BYTEOFF_C((ins))))
79983#define DUK__CONSTP_BC(ins) ((duk_tval *) (void *) ((duk_uint8_t *) consts + DUK__BYTEOFF_BC((ins))))
79984#define DUK__REGCONSTP_B(ins) \
79985 ((duk_tval *) (void *) ((duk_uint8_t *) (((ins) &DUK__RCBIT_B) ? consts : thr->valstack_bottom) + DUK__BYTEOFF_B((ins))))
79986#define DUK__REGCONSTP_C(ins) \
79987 ((duk_tval *) (void *) ((duk_uint8_t *) (((ins) &DUK__RCBIT_C) ? consts : thr->valstack_bottom) + DUK__BYTEOFF_C((ins))))
79988#else /* DUK_USE_EXEC_REGCONST_OPTIMIZE */
79989/* Safe alternatives, no assumption about duk_tval size. */
79990#define DUK__REGP_A(ins) DUK__REGP(DUK_DEC_A((ins)))
79991#define DUK__REGP_B(ins) DUK__REGP(DUK_DEC_B((ins)))
79992#define DUK__REGP_C(ins) DUK__REGP(DUK_DEC_C((ins)))
79993#define DUK__REGP_BC(ins) DUK__REGP(DUK_DEC_BC((ins)))
79994#define DUK__CONSTP_A(ins) DUK__CONSTP(DUK_DEC_A((ins)))
79995#define DUK__CONSTP_B(ins) DUK__CONSTP(DUK_DEC_B((ins)))
79996#define DUK__CONSTP_C(ins) DUK__CONSTP(DUK_DEC_C((ins)))
79997#define DUK__CONSTP_BC(ins) DUK__CONSTP(DUK_DEC_BC((ins)))
79998#define DUK__REGCONSTP_B(ins) ((((ins) &DUK__RCBIT_B) ? consts : thr->valstack_bottom) + DUK_DEC_B((ins)))
79999#define DUK__REGCONSTP_C(ins) ((((ins) &DUK__RCBIT_C) ? consts : thr->valstack_bottom) + DUK_DEC_C((ins)))
80000#endif /* DUK_USE_EXEC_REGCONST_OPTIMIZE */
80001
80002#if defined(DUK_USE_VERBOSE_EXECUTOR_ERRORS)
80003#define DUK__INTERNAL_ERROR(msg) \
80004 do { \
80005 DUK_ERROR_ERROR(thr, (msg)); \
80006 DUK_WO_NORETURN(return;); \
80007 } while (0)
80008#else
80009#define DUK__INTERNAL_ERROR(msg) \
80010 do { \
80011 goto internal_error; \
80012 } while (0)
80013#endif
80015#define DUK__SYNC_CURR_PC() \
80016 do { \
80017 duk_activation *duk__act; \
80018 duk__act = thr->callstack_curr; \
80019 duk__act->curr_pc = curr_pc; \
80020 } while (0)
80021#define DUK__SYNC_AND_NULL_CURR_PC() \
80022 do { \
80023 duk_activation *duk__act; \
80024 duk__act = thr->callstack_curr; \
80025 duk__act->curr_pc = curr_pc; \
80026 thr->ptr_curr_pc = NULL; \
80027 } while (0)
80028
80029#if defined(DUK_USE_EXEC_PREFER_SIZE)
80030#define DUK__LOOKUP_INDIRECT(idx) \
80031 do { \
80032 (idx) = (duk_uint_fast_t) duk_get_uint(thr, (duk_idx_t) (idx)); \
80033 } while (0)
80034#elif defined(DUK_USE_FASTINT)
80035#define DUK__LOOKUP_INDIRECT(idx) \
80036 do { \
80037 duk_tval *tv_ind; \
80038 tv_ind = DUK__REGP((idx)); \
80039 DUK_ASSERT(DUK_TVAL_IS_NUMBER(tv_ind)); \
80040 DUK_ASSERT(DUK_TVAL_IS_FASTINT(tv_ind)); /* compiler guarantees */ \
80041 (idx) = (duk_uint_fast_t) DUK_TVAL_GET_FASTINT_U32(tv_ind); \
80042 } while (0)
80043#else
80044#define DUK__LOOKUP_INDIRECT(idx) \
80045 do { \
80046 duk_tval *tv_ind; \
80047 tv_ind = DUK__REGP(idx); \
80048 DUK_ASSERT(DUK_TVAL_IS_NUMBER(tv_ind)); \
80049 idx = (duk_uint_fast_t) DUK_TVAL_GET_NUMBER(tv_ind); \
80050 } while (0)
80051#endif
80052
80054 duk_activation *entry_act,
80055 duk_int_t entry_call_recursion_depth,
80056 duk_jmpbuf *entry_jmpbuf_ptr,
80057 volatile duk_bool_t *out_delayed_catch_setup) {
80058 duk_small_uint_t lj_ret;
80059
80060 /* Longjmp callers are required to sync-and-null thr->ptr_curr_pc
80061 * before longjmp.
80062 */
80063 DUK_ASSERT(heap->curr_thread != NULL);
80064 DUK_ASSERT(heap->curr_thread->ptr_curr_pc == NULL);
80065
80066 /* XXX: signalling the need to shrink check (only if unwound) */
80067
80068 /* Must be restored here to handle e.g. yields properly. */
80069 heap->call_recursion_depth = entry_call_recursion_depth;
80070
80071 /* Switch to caller's setjmp() catcher so that if an error occurs
80072 * during error handling, it is always propagated outwards instead
80073 * of causing an infinite loop in our own handler.
80074 */
80075 heap->lj.jmpbuf_ptr = (duk_jmpbuf *) entry_jmpbuf_ptr;
80076
80077 lj_ret = duk__handle_longjmp(heap->curr_thread, entry_act, out_delayed_catch_setup);
80078
80079 /* Error handling complete, remove side effect protections.
80080 */
80081#if defined(DUK_USE_ASSERTIONS)
80082 DUK_ASSERT(heap->error_not_allowed == 1);
80083 heap->error_not_allowed = 0;
80084#endif
80085 DUK_ASSERT(heap->pf_prevent_count > 0);
80086 heap->pf_prevent_count--;
80087 DUK_DD(DUK_DDPRINT("executor error handled, pf_prevent_count updated to %ld", (long) heap->pf_prevent_count));
80088
80089 if (lj_ret == DUK__LONGJMP_RESTART) {
80090 /* Restart bytecode execution, possibly with a changed thread. */
80092 } else {
80093 /* If an error is propagated, don't run refzero checks here.
80094 * The next catcher will deal with that. Pf_prevent_count
80095 * will be re-bumped by the longjmp.
80096 */
80097
80098 DUK_ASSERT(lj_ret == DUK__LONGJMP_RETHROW); /* Rethrow error to calling state. */
80099 DUK_ASSERT(heap->lj.jmpbuf_ptr == entry_jmpbuf_ptr); /* Longjmp handling has restored jmpbuf_ptr. */
80100
80101 /* Thread may have changed, e.g. YIELD converted to THROW. */
80104 }
80105}
80106
80107/* Outer executor with setjmp/longjmp handling. */
80109 /* Entry level info. */
80110 duk_hthread *entry_thread;
80111 duk_activation *entry_act;
80112 duk_int_t entry_call_recursion_depth;
80113 duk_jmpbuf *entry_jmpbuf_ptr;
80114 duk_jmpbuf our_jmpbuf;
80115 duk_heap *heap;
80116 volatile duk_bool_t delayed_catch_setup = 0;
80117
80118 DUK_ASSERT(exec_thr != NULL);
80119 DUK_ASSERT(exec_thr->heap != NULL);
80120 DUK_ASSERT(exec_thr->heap->curr_thread != NULL);
80122 DUK_ASSERT(exec_thr->callstack_top >= 1); /* at least one activation, ours */
80123 DUK_ASSERT(exec_thr->callstack_curr != NULL);
80124 DUK_ASSERT(DUK_ACT_GET_FUNC(exec_thr->callstack_curr) != NULL);
80126
80127 DUK_GC_TORTURE(exec_thr->heap);
80128
80129 entry_thread = exec_thr;
80130 heap = entry_thread->heap;
80131 entry_act = entry_thread->callstack_curr;
80132 DUK_ASSERT(entry_act != NULL);
80133 entry_call_recursion_depth = entry_thread->heap->call_recursion_depth;
80134 entry_jmpbuf_ptr = entry_thread->heap->lj.jmpbuf_ptr;
80135
80136 /*
80137 * Note: we currently assume that the setjmp() catchpoint is
80138 * not re-entrant (longjmp() cannot be called more than once
80139 * for a single setjmp()).
80140 *
80141 * See doc/code-issues.rst for notes on variable assignment
80142 * before and after setjmp().
80143 */
80144
80145 for (;;) {
80146 heap->lj.jmpbuf_ptr = &our_jmpbuf;
80147 DUK_ASSERT(heap->lj.jmpbuf_ptr != NULL);
80148
80149#if defined(DUK_USE_CPP_EXCEPTIONS)
80150 try {
80151#else
80152 DUK_ASSERT(heap->lj.jmpbuf_ptr == &our_jmpbuf);
80153 if (DUK_SETJMP(our_jmpbuf.jb) == 0) {
80154#endif
80155 DUK_DDD(DUK_DDDPRINT("after setjmp, delayed catch setup: %ld\n", (long) delayed_catch_setup));
80156
80157 if (DUK_UNLIKELY(delayed_catch_setup != 0)) {
80158 duk_hthread *thr = entry_thread->heap->curr_thread;
80159
80160 delayed_catch_setup = 0;
80162 DUK_ASSERT(delayed_catch_setup == 0);
80163 DUK_DDD(DUK_DDDPRINT("top after delayed catch setup: %ld", (long) duk_get_top(entry_thread)));
80164 }
80165
80166 /* Execute bytecode until returned or longjmp(). */
80167 duk__js_execute_bytecode_inner(entry_thread, entry_act);
80168
80169 /* Successful return: restore jmpbuf and return to caller. */
80170 heap->lj.jmpbuf_ptr = entry_jmpbuf_ptr;
80171
80172 return;
80173#if defined(DUK_USE_CPP_EXCEPTIONS)
80174 } catch (duk_internal_exception &exc) {
80175#else
80176 } else {
80177#endif
80178#if defined(DUK_USE_CPP_EXCEPTIONS)
80179 DUK_UNREF(exc);
80180#endif
80181 DUK_DDD(DUK_DDDPRINT("longjmp caught by bytecode executor"));
80182 DUK_STATS_INC(exec_thr->heap, stats_exec_throw);
80183
80185 entry_act,
80186 entry_call_recursion_depth,
80187 entry_jmpbuf_ptr,
80188 &delayed_catch_setup);
80189 }
80190#if defined(DUK_USE_CPP_EXCEPTIONS)
80191 catch (duk_fatal_exception &exc) {
80192 DUK_D(DUK_DPRINT("rethrow duk_fatal_exception"));
80193 DUK_UNREF(exc);
80194 throw;
80195 } catch (std::exception &exc) {
80196 const char *what = exc.what();
80197 if (!what) {
80198 what = "unknown";
80199 }
80200 DUK_D(DUK_DPRINT("unexpected c++ std::exception (perhaps thrown by user code)"));
80201 DUK_STATS_INC(exec_thr->heap, stats_exec_throw);
80202 try {
80203 DUK_ASSERT(heap->curr_thread != NULL);
80206 "caught invalid c++ std::exception '%s' (perhaps thrown by user code)",
80207 what);
80208 DUK_WO_NORETURN(return;);
80209 } catch (duk_internal_exception exc) {
80210 DUK_D(DUK_DPRINT("caught api error thrown from unexpected c++ std::exception"));
80211 DUK_UNREF(exc);
80213 entry_act,
80214 entry_call_recursion_depth,
80215 entry_jmpbuf_ptr,
80216 &delayed_catch_setup);
80217 }
80218 } catch (...) {
80219 DUK_D(DUK_DPRINT("unexpected c++ exception (perhaps thrown by user code)"));
80220 DUK_STATS_INC(exec_thr->heap, stats_exec_throw);
80221 try {
80222 DUK_ASSERT(heap->curr_thread != NULL);
80223 DUK_ERROR_TYPE(heap->curr_thread, "caught invalid c++ exception (perhaps thrown by user code)");
80224 DUK_WO_NORETURN(return;);
80225 } catch (duk_internal_exception exc) {
80226 DUK_D(DUK_DPRINT("caught api error thrown from unexpected c++ exception"));
80227 DUK_UNREF(exc);
80229 entry_act,
80230 entry_call_recursion_depth,
80231 entry_jmpbuf_ptr,
80232 &delayed_catch_setup);
80233 }
80234 }
80235#endif
80236 }
80237
80238 DUK_WO_NORETURN(return;);
80239}
80240
80241/* Inner executor, performance critical. */
80243 /* Current PC, accessed by other functions through thr->ptr_to_curr_pc.
80244 * Critical for performance. It would be safest to make this volatile,
80245 * but that eliminates performance benefits; aliasing guarantees
80246 * should be enough though.
80247 */
80248 duk_instr_t *curr_pc; /* bytecode has a stable pointer */
80249
80250 /* Hot variables for interpretation. Critical for performance,
80251 * but must add sparingly to minimize register shuffling.
80252 */
80253 duk_hthread *thr; /* stable */
80254 duk_tval *consts; /* stable */
80256 /* 'funcs' is quite rarely used, so no local for it */
80257#if defined(DUK_USE_EXEC_FUN_LOCAL)
80258 duk_hcompfunc *fun;
80259#else
80260 /* 'fun' is quite rarely used, so no local for it */
80261#endif
80262
80263#if defined(DUK_USE_INTERRUPT_COUNTER)
80264 duk_int_t int_ctr;
80265#endif
80266
80267#if defined(DUK_USE_ASSERTIONS)
80268 duk_size_t valstack_top_base; /* valstack top, should match before interpreting each op (no leftovers) */
80269#endif
80270
80271 /* Optimized reg/const access macros assume sizeof(duk_tval) to be
80272 * either 8 or 16. Heap allocation checks this even without asserts
80273 * enabled now because it can't be autodetected in duk_config.h.
80274 */
80275#if 1
80276#if defined(DUK_USE_PACKED_TVAL)
80277 DUK_ASSERT(sizeof(duk_tval) == 8);
80278#else
80279 DUK_ASSERT(sizeof(duk_tval) == 16);
80280#endif
80281#endif
80282
80283 DUK_GC_TORTURE(entry_thread->heap);
80284
80285 /*
80286 * Restart execution by reloading thread state.
80287 *
80288 * Note that 'thr' and any thread configuration may have changed,
80289 * so all local variables are suspect and we need to reinitialize.
80290 *
80291 * The number of local variables should be kept to a minimum: if
80292 * the variables are spilled, they will need to be loaded from
80293 * memory anyway.
80294 *
80295 * Any 'goto restart_execution;' code path in opcode dispatch must
80296 * ensure 'curr_pc' is synced back to act->curr_pc before the goto
80297 * takes place.
80298 *
80299 * The interpreter must be very careful with memory pointers, as
80300 * many pointers are not guaranteed to be 'stable' and may be
80301 * reallocated and relocated on-the-fly quite easily (e.g. by a
80302 * memory allocation or a property access).
80303 *
80304 * The following are assumed to have stable pointers:
80305 * - the current thread
80306 * - the current function
80307 * - the bytecode, constant table, inner function table of the
80308 * current function (as they are a part of the function allocation)
80309 *
80310 * The following are assumed to have semi-stable pointers:
80311 * - the current activation entry: stable as long as callstack
80312 * is not changed (reallocated by growing or shrinking), or
80313 * by any garbage collection invocation (through finalizers)
80314 * - Note in particular that ANY DECREF can invalidate the
80315 * activation pointer, so for the most part a fresh lookup
80316 * is required
80317 *
80318 * The following are not assumed to have stable pointers at all:
80319 * - the value stack (registers) of the current thread
80320 *
80321 * See execution.rst for discussion.
80322 */
80323
80324restart_execution:
80325
80326 /* Lookup current thread; use the stable 'entry_thread' for this to
80327 * avoid clobber warnings. Any valid, reachable 'thr' value would be
80328 * fine for this, so using 'entry_thread' is just to silence warnings.
80329 */
80330 thr = entry_thread->heap->curr_thread;
80331 DUK_ASSERT(thr != NULL);
80332 DUK_ASSERT(thr->callstack_top >= 1);
80333 DUK_ASSERT(thr->callstack_curr != NULL);
80336
80337 DUK_GC_TORTURE(thr->heap);
80338
80339 thr->ptr_curr_pc = &curr_pc;
80340
80341 /* Relookup and initialize dispatch loop variables. Debugger check. */
80342 {
80343 duk_activation *act;
80344#if !defined(DUK_USE_EXEC_FUN_LOCAL)
80345 duk_hcompfunc *fun;
80346#endif
80347
80348 /* Assume interrupt init/counter are properly initialized here. */
80349 /* Assume that thr->valstack_bottom has been set-up before getting here. */
80350
80351 act = thr->callstack_curr;
80352 DUK_ASSERT(act != NULL);
80353 fun = (duk_hcompfunc *) DUK_ACT_GET_FUNC(act);
80354 DUK_ASSERT(fun != NULL);
80355 DUK_ASSERT(thr->valstack_top - thr->valstack_bottom == fun->nregs);
80356 consts = DUK_HCOMPFUNC_GET_CONSTS_BASE(thr->heap, fun);
80357 DUK_ASSERT(consts != NULL);
80358
80359#if defined(DUK_USE_DEBUGGER_SUPPORT)
80360 if (DUK_UNLIKELY(duk_debug_is_attached(thr->heap) && !thr->heap->dbg_processing)) {
80361 duk__executor_recheck_debugger(thr, act, fun);
80362 DUK_ASSERT(act == thr->callstack_curr);
80363 DUK_ASSERT(act != NULL);
80364 }
80365#endif /* DUK_USE_DEBUGGER_SUPPORT */
80366
80367#if defined(DUK_USE_ASSERTIONS)
80368 valstack_top_base = (duk_size_t) (thr->valstack_top - thr->valstack);
80369#endif
80370
80371 /* Set up curr_pc for opcode dispatch. */
80372 curr_pc = act->curr_pc;
80373 }
80374
80375 DUK_DD(DUK_DDPRINT("restarting execution, thr %p, act idx %ld, fun %p,"
80376 "consts %p, funcs %p, lev %ld, regbot %ld, regtop %ld, "
80377 "preventcount=%ld",
80378 (void *) thr,
80379 (long) (thr->callstack_top - 1),
80380 (void *) DUK__FUN(),
80381 (void *) DUK_HCOMPFUNC_GET_CONSTS_BASE(thr->heap, DUK__FUN()),
80382 (void *) DUK_HCOMPFUNC_GET_FUNCS_BASE(thr->heap, DUK__FUN()),
80383 (long) (thr->callstack_top - 1),
80384 (long) (thr->valstack_bottom - thr->valstack),
80385 (long) (thr->valstack_top - thr->valstack),
80386 (long) thr->callstack_preventcount));
80387
80388 /* Dispatch loop. */
80389
80390 for (;;) {
80391 duk_uint8_t op;
80392
80393 DUK_ASSERT(thr->callstack_top >= 1);
80394 DUK_ASSERT(thr->valstack_top - thr->valstack_bottom == DUK__FUN()->nregs);
80395 DUK_ASSERT((duk_size_t) (thr->valstack_top - thr->valstack) == valstack_top_base);
80396
80397 /* Executor interrupt counter check, used to implement breakpoints,
80398 * debugging interface, execution timeouts, etc. The counter is heap
80399 * specific but is maintained in the current thread to make the check
80400 * as fast as possible. The counter is copied back to the heap struct
80401 * whenever a thread switch occurs by the DUK_HEAP_SWITCH_THREAD() macro.
80402 */
80403#if defined(DUK_USE_INTERRUPT_COUNTER)
80404 int_ctr = thr->interrupt_counter;
80405 if (DUK_LIKELY(int_ctr > 0)) {
80406 thr->interrupt_counter = int_ctr - 1;
80407 } else {
80408 /* Trigger at zero or below */
80409 duk_small_uint_t exec_int_ret;
80410
80411 DUK_STATS_INC(thr->heap, stats_exec_interrupt);
80412
80413 /* Write curr_pc back for the debugger. */
80414 {
80415 duk_activation *act;
80416 DUK_ASSERT(thr->callstack_top > 0);
80417 act = thr->callstack_curr;
80418 DUK_ASSERT(act != NULL);
80419 act->curr_pc = (duk_instr_t *) curr_pc;
80420 }
80421
80422 /* Forced restart caused by a function return; must recheck
80423 * debugger breakpoints before checking line transitions,
80424 * see GH-303. Restart and then handle interrupt_counter
80425 * zero again.
80426 */
80427#if defined(DUK_USE_DEBUGGER_SUPPORT)
80428 if (thr->heap->dbg_force_restart) {
80429 DUK_DD(DUK_DDPRINT("dbg_force_restart flag forced restart execution")); /* GH-303 */
80430 thr->heap->dbg_force_restart = 0;
80431 goto restart_execution;
80432 }
80433#endif
80434
80435 exec_int_ret = duk__executor_interrupt(thr);
80436 if (exec_int_ret == DUK__INT_RESTART) {
80437 /* curr_pc synced back above */
80438 goto restart_execution;
80439 }
80440 }
80441#endif /* DUK_USE_INTERRUPT_COUNTER */
80442#if defined(DUK_USE_INTERRUPT_COUNTER) && defined(DUK_USE_DEBUG)
80443 /* For cross-checking during development: ensure dispatch count
80444 * matches cumulative interrupt counter init value sums.
80445 */
80446 thr->heap->inst_count_exec++;
80447#endif
80448
80449#if defined(DUK_USE_ASSERTIONS) || defined(DUK_USE_DEBUG)
80450 {
80451 duk_activation *act;
80452 act = thr->callstack_curr;
80453 DUK_ASSERT(curr_pc >= DUK_HCOMPFUNC_GET_CODE_BASE(thr->heap, DUK__FUN()));
80454 DUK_ASSERT(curr_pc < DUK_HCOMPFUNC_GET_CODE_END(thr->heap, DUK__FUN()));
80455 DUK_UNREF(act); /* if debugging disabled */
80456
80458 "executing bytecode: pc=%ld, ins=0x%08lx, op=%ld, valstack_top=%ld/%ld, nregs=%ld --> %!I",
80459 (long) (curr_pc - DUK_HCOMPFUNC_GET_CODE_BASE(thr->heap, DUK__FUN())),
80460 (unsigned long) *curr_pc,
80461 (long) DUK_DEC_OP(*curr_pc),
80462 (long) (thr->valstack_top - thr->valstack),
80463 (long) (thr->valstack_end - thr->valstack),
80464 (long) (DUK__FUN() ? DUK__FUN()->nregs : -1),
80465 (duk_instr_t) *curr_pc));
80466 }
80467#endif
80468
80469#if defined(DUK_USE_ASSERTIONS)
80470 /* Quite heavy assert: check valstack policy. Improper
80471 * shuffle instructions can write beyond valstack_top/end
80472 * so this check catches them in the act.
80473 */
80474 {
80475 duk_tval *tv;
80476 tv = thr->valstack_top;
80477 while (tv != thr->valstack_end) {
80479 tv++;
80480 }
80481 }
80482#endif
80483
80484 ins = *curr_pc++;
80485 DUK_STATS_INC(thr->heap, stats_exec_opcodes);
80486
80487 /* Typing: use duk_small_(u)int_fast_t when decoding small
80488 * opcode fields (op, A, B, C, BC) which fit into 16 bits
80489 * and duk_(u)int_fast_t when decoding larger fields (e.g.
80490 * ABC). Use unsigned variant by default, signed when the
80491 * value is used in signed arithmetic. Using variable names
80492 * such as 'a', 'b', 'c', 'bc', etc makes it easier to spot
80493 * typing mismatches.
80494 */
80495
80496 /* Switch based on opcode. Cast to 8-bit unsigned value and
80497 * use a fully populated case clauses so that the compiler
80498 * will (at least usually) omit a bounds check.
80499 */
80500 op = (duk_uint8_t) DUK_DEC_OP(ins);
80501 switch (op) {
80502 /* Some useful macros. These access inner executor variables
80503 * directly so they only apply within the executor.
80504 */
80505#if defined(DUK_USE_EXEC_PREFER_SIZE)
80506#define DUK__REPLACE_TOP_A_BREAK() \
80507 { goto replace_top_a; }
80508#define DUK__REPLACE_TOP_BC_BREAK() \
80509 { goto replace_top_bc; }
80510#define DUK__REPLACE_BOOL_A_BREAK(bval) \
80511 { \
80512 duk_bool_t duk__bval; \
80513 duk__bval = (bval); \
80514 DUK_ASSERT(duk__bval == 0 || duk__bval == 1); \
80515 duk_push_boolean(thr, duk__bval); \
80516 DUK__REPLACE_TOP_A_BREAK(); \
80517 }
80518#else
80519#define DUK__REPLACE_TOP_A_BREAK() \
80520 { \
80521 DUK__REPLACE_TO_TVPTR(thr, DUK__REGP_A(ins)); \
80522 break; \
80523 }
80524#define DUK__REPLACE_TOP_BC_BREAK() \
80525 { \
80526 DUK__REPLACE_TO_TVPTR(thr, DUK__REGP_BC(ins)); \
80527 break; \
80528 }
80529#define DUK__REPLACE_BOOL_A_BREAK(bval) \
80530 { \
80531 duk_bool_t duk__bval; \
80532 duk_tval *duk__tvdst; \
80533 duk__bval = (bval); \
80534 DUK_ASSERT(duk__bval == 0 || duk__bval == 1); \
80535 duk__tvdst = DUK__REGP_A(ins); \
80536 DUK_TVAL_SET_BOOLEAN_UPDREF(thr, duk__tvdst, duk__bval); \
80537 break; \
80538 }
80539#endif
80540
80541 /* XXX: 12 + 12 bit variant might make sense too, for both reg and
80542 * const loads.
80543 */
80544
80545 /* For LDREG, STREG, LDCONST footprint optimized variants would just
80546 * duk_dup() + duk_replace(), but because they're used quite a lot
80547 * they're currently intentionally not size optimized.
80548 */
80549 case DUK_OP_LDREG: {
80550 duk_tval *tv1, *tv2;
80551
80552 tv1 = DUK__REGP_A(ins);
80553 tv2 = DUK__REGP_BC(ins);
80554 DUK_TVAL_SET_TVAL_UPDREF_FAST(thr, tv1, tv2); /* side effects */
80555 break;
80556 }
80557
80558 case DUK_OP_STREG: {
80559 duk_tval *tv1, *tv2;
80560
80561 tv1 = DUK__REGP_A(ins);
80562 tv2 = DUK__REGP_BC(ins);
80563 DUK_TVAL_SET_TVAL_UPDREF_FAST(thr, tv2, tv1); /* side effects */
80564 break;
80565 }
80566
80567 case DUK_OP_LDCONST: {
80568 duk_tval *tv1, *tv2;
80569
80570 tv1 = DUK__REGP_A(ins);
80571 tv2 = DUK__CONSTP_BC(ins);
80572 DUK_TVAL_SET_TVAL_UPDREF_FAST(thr, tv1, tv2); /* side effects */
80573 break;
80574 }
80575
80576 /* LDINT and LDINTX are intended to load an arbitrary signed
80577 * 32-bit value. Only an LDINT+LDINTX sequence is supported.
80578 * This also guarantees all values remain fastints.
80579 */
80580#if defined(DUK_USE_EXEC_PREFER_SIZE)
80581 case DUK_OP_LDINT: {
80582 duk_int32_t val;
80583
80584 val = (duk_int32_t) DUK_DEC_BC(ins) - (duk_int32_t) DUK_BC_LDINT_BIAS;
80585 duk_push_int(thr, val);
80587 }
80588 case DUK_OP_LDINTX: {
80589 duk_int32_t val;
80590
80591 val = (duk_int32_t) duk_get_int(thr, DUK_DEC_A(ins));
80592 val = (val << DUK_BC_LDINTX_SHIFT) + (duk_int32_t) DUK_DEC_BC(ins); /* no bias */
80593 duk_push_int(thr, val);
80595 }
80596#else /* DUK_USE_EXEC_PREFER_SIZE */
80597 case DUK_OP_LDINT: {
80598 duk_tval *tv1;
80599 duk_int32_t val;
80600
80601 val = (duk_int32_t) DUK_DEC_BC(ins) - (duk_int32_t) DUK_BC_LDINT_BIAS;
80602 tv1 = DUK__REGP_A(ins);
80603 DUK_TVAL_SET_I32_UPDREF(thr, tv1, val); /* side effects */
80604 break;
80605 }
80606 case DUK_OP_LDINTX: {
80607 duk_tval *tv1;
80608 duk_int32_t val;
80609
80610 tv1 = DUK__REGP_A(ins);
80612#if defined(DUK_USE_FASTINT)
80614 val = DUK_TVAL_GET_FASTINT_I32(tv1);
80615#else
80616 /* XXX: fast double-to-int conversion, we know number is integer in [-0x80000000,0xffffffff]. */
80617 val = (duk_int32_t) DUK_TVAL_GET_NUMBER(tv1);
80618#endif
80619 val =
80620 (duk_int32_t) ((duk_uint32_t) val << DUK_BC_LDINTX_SHIFT) + (duk_int32_t) DUK_DEC_BC(ins); /* no bias */
80621 DUK_TVAL_SET_I32_UPDREF(thr, tv1, val); /* side effects */
80622 break;
80623 }
80624#endif /* DUK_USE_EXEC_PREFER_SIZE */
80625
80626#if defined(DUK_USE_EXEC_PREFER_SIZE)
80627 case DUK_OP_LDTHIS: {
80628 duk_push_this(thr);
80630 }
80631 case DUK_OP_LDUNDEF: {
80633 break;
80634 }
80635 case DUK_OP_LDNULL: {
80636 duk_to_null(thr, (duk_idx_t) DUK_DEC_BC(ins));
80637 break;
80638 }
80639 case DUK_OP_LDTRUE: {
80640 duk_push_true(thr);
80642 }
80643 case DUK_OP_LDFALSE: {
80644 duk_push_false(thr);
80646 }
80647#else /* DUK_USE_EXEC_PREFER_SIZE */
80648 case DUK_OP_LDTHIS: {
80649 /* Note: 'this' may be bound to any value, not just an object */
80650 duk_tval *tv1, *tv2;
80651
80652 tv1 = DUK__REGP_BC(ins);
80653 tv2 = thr->valstack_bottom - 1; /* 'this binding' is just under bottom */
80654 DUK_ASSERT(tv2 >= thr->valstack);
80655 DUK_TVAL_SET_TVAL_UPDREF_FAST(thr, tv1, tv2); /* side effects */
80656 break;
80657 }
80658 case DUK_OP_LDUNDEF: {
80659 duk_tval *tv1;
80660
80661 tv1 = DUK__REGP_BC(ins);
80662 DUK_TVAL_SET_UNDEFINED_UPDREF(thr, tv1); /* side effects */
80663 break;
80664 }
80665 case DUK_OP_LDNULL: {
80666 duk_tval *tv1;
80667
80668 tv1 = DUK__REGP_BC(ins);
80669 DUK_TVAL_SET_NULL_UPDREF(thr, tv1); /* side effects */
80670 break;
80671 }
80672 case DUK_OP_LDTRUE: {
80673 duk_tval *tv1;
80674
80675 tv1 = DUK__REGP_BC(ins);
80676 DUK_TVAL_SET_BOOLEAN_UPDREF(thr, tv1, 1); /* side effects */
80677 break;
80678 }
80679 case DUK_OP_LDFALSE: {
80680 duk_tval *tv1;
80681
80682 tv1 = DUK__REGP_BC(ins);
80683 DUK_TVAL_SET_BOOLEAN_UPDREF(thr, tv1, 0); /* side effects */
80684 break;
80685 }
80686#endif /* DUK_USE_EXEC_PREFER_SIZE */
80687
80688 case DUK_OP_BNOT: {
80689 duk__vm_bitwise_not(thr, DUK_DEC_BC(ins), DUK_DEC_A(ins));
80690 break;
80691 }
80692
80693 case DUK_OP_LNOT: {
80694 duk__vm_logical_not(thr, DUK_DEC_BC(ins), DUK_DEC_A(ins));
80695 break;
80696 }
80697
80698#if defined(DUK_USE_EXEC_PREFER_SIZE)
80699 case DUK_OP_UNM:
80700 case DUK_OP_UNP: {
80701 duk__vm_arith_unary_op(thr, DUK_DEC_BC(ins), DUK_DEC_A(ins), op);
80702 break;
80703 }
80704#else /* DUK_USE_EXEC_PREFER_SIZE */
80705 case DUK_OP_UNM: {
80707 break;
80708 }
80709 case DUK_OP_UNP: {
80711 break;
80712 }
80713#endif /* DUK_USE_EXEC_PREFER_SIZE */
80714
80715#if defined(DUK_USE_EXEC_PREFER_SIZE)
80716 case DUK_OP_TYPEOF: {
80717 duk_small_uint_t stridx;
80718
80719 stridx = duk_js_typeof_stridx(DUK__REGP_BC(ins));
80721 duk_push_hstring_stridx(thr, stridx);
80723 }
80724#else /* DUK_USE_EXEC_PREFER_SIZE */
80725 case DUK_OP_TYPEOF: {
80726 duk_tval *tv;
80727 duk_small_uint_t stridx;
80728 duk_hstring *h_str;
80729
80730 tv = DUK__REGP_BC(ins);
80731 stridx = duk_js_typeof_stridx(tv);
80733 h_str = DUK_HTHREAD_GET_STRING(thr, stridx);
80734 tv = DUK__REGP_A(ins);
80735 DUK_TVAL_SET_STRING_UPDREF(thr, tv, h_str);
80736 break;
80737 }
80738#endif /* DUK_USE_EXEC_PREFER_SIZE */
80739
80740 case DUK_OP_TYPEOFID: {
80741 duk_small_uint_t stridx;
80742#if !defined(DUK_USE_EXEC_PREFER_SIZE)
80743 duk_hstring *h_str;
80744#endif
80745 duk_activation *act;
80746 duk_hstring *name;
80747 duk_tval *tv;
80748
80749 /* A -> target register
80750 * BC -> constant index of identifier name
80751 */
80752
80753 tv = DUK__CONSTP_BC(ins);
80755 name = DUK_TVAL_GET_STRING(tv);
80756 tv = NULL; /* lookup has side effects */
80757 act = thr->callstack_curr;
80758 if (duk_js_getvar_activation(thr, act, name, 0 /*throw*/)) {
80759 /* -> [... val this] */
80760 tv = DUK_GET_TVAL_NEGIDX(thr, -2);
80761 stridx = duk_js_typeof_stridx(tv);
80762 tv = NULL; /* no longer needed */
80763 duk_pop_2_unsafe(thr);
80764 } else {
80765 /* unresolvable, no stack changes */
80766 stridx = DUK_STRIDX_LC_UNDEFINED;
80767 }
80769#if defined(DUK_USE_EXEC_PREFER_SIZE)
80770 duk_push_hstring_stridx(thr, stridx);
80772#else /* DUK_USE_EXEC_PREFER_SIZE */
80773 h_str = DUK_HTHREAD_GET_STRING(thr, stridx);
80774 tv = DUK__REGP_A(ins);
80775 DUK_TVAL_SET_STRING_UPDREF(thr, tv, h_str);
80776 break;
80777#endif /* DUK_USE_EXEC_PREFER_SIZE */
80778 }
80779
80780 /* Equality: E5 Sections 11.9.1, 11.9.3 */
80781
80782#define DUK__EQ_BODY(barg, carg) \
80783 { \
80784 duk_bool_t tmp; \
80785 tmp = duk_js_equals(thr, (barg), (carg)); \
80786 DUK_ASSERT(tmp == 0 || tmp == 1); \
80787 DUK__REPLACE_BOOL_A_BREAK(tmp); \
80788 }
80789#define DUK__NEQ_BODY(barg, carg) \
80790 { \
80791 duk_bool_t tmp; \
80792 tmp = duk_js_equals(thr, (barg), (carg)); \
80793 DUK_ASSERT(tmp == 0 || tmp == 1); \
80794 tmp ^= 1; \
80795 DUK__REPLACE_BOOL_A_BREAK(tmp); \
80796 }
80797#define DUK__SEQ_BODY(barg, carg) \
80798 { \
80799 duk_bool_t tmp; \
80800 tmp = duk_js_strict_equals((barg), (carg)); \
80801 DUK_ASSERT(tmp == 0 || tmp == 1); \
80802 DUK__REPLACE_BOOL_A_BREAK(tmp); \
80803 }
80804#define DUK__SNEQ_BODY(barg, carg) \
80805 { \
80806 duk_bool_t tmp; \
80807 tmp = duk_js_strict_equals((barg), (carg)); \
80808 DUK_ASSERT(tmp == 0 || tmp == 1); \
80809 tmp ^= 1; \
80810 DUK__REPLACE_BOOL_A_BREAK(tmp); \
80811 }
80812#if defined(DUK_USE_EXEC_PREFER_SIZE)
80813 case DUK_OP_EQ_RR:
80814 case DUK_OP_EQ_CR:
80815 case DUK_OP_EQ_RC:
80816 case DUK_OP_EQ_CC:
80818 case DUK_OP_NEQ_RR:
80819 case DUK_OP_NEQ_CR:
80820 case DUK_OP_NEQ_RC:
80821 case DUK_OP_NEQ_CC:
80823 case DUK_OP_SEQ_RR:
80824 case DUK_OP_SEQ_CR:
80825 case DUK_OP_SEQ_RC:
80826 case DUK_OP_SEQ_CC:
80828 case DUK_OP_SNEQ_RR:
80829 case DUK_OP_SNEQ_CR:
80830 case DUK_OP_SNEQ_RC:
80831 case DUK_OP_SNEQ_CC:
80833#else /* DUK_USE_EXEC_PREFER_SIZE */
80834 case DUK_OP_EQ_RR:
80836 case DUK_OP_EQ_CR:
80838 case DUK_OP_EQ_RC:
80840 case DUK_OP_EQ_CC:
80842 case DUK_OP_NEQ_RR:
80844 case DUK_OP_NEQ_CR:
80846 case DUK_OP_NEQ_RC:
80848 case DUK_OP_NEQ_CC:
80850 case DUK_OP_SEQ_RR:
80852 case DUK_OP_SEQ_CR:
80854 case DUK_OP_SEQ_RC:
80856 case DUK_OP_SEQ_CC:
80858 case DUK_OP_SNEQ_RR:
80860 case DUK_OP_SNEQ_CR:
80862 case DUK_OP_SNEQ_RC:
80864 case DUK_OP_SNEQ_CC:
80866#endif /* DUK_USE_EXEC_PREFER_SIZE */
80867
80868#define DUK__COMPARE_BODY(arg1, arg2, flags) \
80869 { \
80870 duk_bool_t tmp; \
80871 tmp = duk_js_compare_helper(thr, (arg1), (arg2), (flags)); \
80872 DUK_ASSERT(tmp == 0 || tmp == 1); \
80873 DUK__REPLACE_BOOL_A_BREAK(tmp); \
80874 }
80875#define DUK__GT_BODY(barg, carg) DUK__COMPARE_BODY((carg), (barg), 0)
80876#define DUK__GE_BODY(barg, carg) DUK__COMPARE_BODY((barg), (carg), DUK_COMPARE_FLAG_EVAL_LEFT_FIRST | DUK_COMPARE_FLAG_NEGATE)
80877#define DUK__LT_BODY(barg, carg) DUK__COMPARE_BODY((barg), (carg), DUK_COMPARE_FLAG_EVAL_LEFT_FIRST)
80878#define DUK__LE_BODY(barg, carg) DUK__COMPARE_BODY((carg), (barg), DUK_COMPARE_FLAG_NEGATE)
80879#if defined(DUK_USE_EXEC_PREFER_SIZE)
80880 case DUK_OP_GT_RR:
80881 case DUK_OP_GT_CR:
80882 case DUK_OP_GT_RC:
80883 case DUK_OP_GT_CC:
80885 case DUK_OP_GE_RR:
80886 case DUK_OP_GE_CR:
80887 case DUK_OP_GE_RC:
80888 case DUK_OP_GE_CC:
80890 case DUK_OP_LT_RR:
80891 case DUK_OP_LT_CR:
80892 case DUK_OP_LT_RC:
80893 case DUK_OP_LT_CC:
80895 case DUK_OP_LE_RR:
80896 case DUK_OP_LE_CR:
80897 case DUK_OP_LE_RC:
80898 case DUK_OP_LE_CC:
80900#else /* DUK_USE_EXEC_PREFER_SIZE */
80901 case DUK_OP_GT_RR:
80903 case DUK_OP_GT_CR:
80905 case DUK_OP_GT_RC:
80907 case DUK_OP_GT_CC:
80909 case DUK_OP_GE_RR:
80911 case DUK_OP_GE_CR:
80913 case DUK_OP_GE_RC:
80915 case DUK_OP_GE_CC:
80917 case DUK_OP_LT_RR:
80919 case DUK_OP_LT_CR:
80921 case DUK_OP_LT_RC:
80923 case DUK_OP_LT_CC:
80925 case DUK_OP_LE_RR:
80927 case DUK_OP_LE_CR:
80929 case DUK_OP_LE_RC:
80931 case DUK_OP_LE_CC:
80933#endif /* DUK_USE_EXEC_PREFER_SIZE */
80934
80935 /* No size optimized variant at present for IF. */
80936 case DUK_OP_IFTRUE_R: {
80937 if (duk_js_toboolean(DUK__REGP_BC(ins)) != 0) {
80938 curr_pc++;
80939 }
80940 break;
80941 }
80942 case DUK_OP_IFTRUE_C: {
80943 if (duk_js_toboolean(DUK__CONSTP_BC(ins)) != 0) {
80944 curr_pc++;
80945 }
80946 break;
80947 }
80948 case DUK_OP_IFFALSE_R: {
80949 if (duk_js_toboolean(DUK__REGP_BC(ins)) == 0) {
80950 curr_pc++;
80951 }
80952 break;
80953 }
80954 case DUK_OP_IFFALSE_C: {
80955 if (duk_js_toboolean(DUK__CONSTP_BC(ins)) == 0) {
80956 curr_pc++;
80957 }
80958 break;
80959 }
80960
80961#if defined(DUK_USE_EXEC_PREFER_SIZE)
80962 case DUK_OP_ADD_RR:
80963 case DUK_OP_ADD_CR:
80964 case DUK_OP_ADD_RC:
80965 case DUK_OP_ADD_CC: {
80966 /* XXX: could leave value on stack top and goto replace_top_a; */
80968 break;
80969 }
80970#else /* DUK_USE_EXEC_PREFER_SIZE */
80971 case DUK_OP_ADD_RR: {
80972 duk__vm_arith_add(thr, DUK__REGP_B(ins), DUK__REGP_C(ins), DUK_DEC_A(ins));
80973 break;
80974 }
80975 case DUK_OP_ADD_CR: {
80977 break;
80978 }
80979 case DUK_OP_ADD_RC: {
80981 break;
80982 }
80983 case DUK_OP_ADD_CC: {
80985 break;
80986 }
80987#endif /* DUK_USE_EXEC_PREFER_SIZE */
80988
80989#if defined(DUK_USE_EXEC_PREFER_SIZE)
80990 case DUK_OP_SUB_RR:
80991 case DUK_OP_SUB_CR:
80992 case DUK_OP_SUB_RC:
80993 case DUK_OP_SUB_CC:
80994 case DUK_OP_MUL_RR:
80995 case DUK_OP_MUL_CR:
80996 case DUK_OP_MUL_RC:
80997 case DUK_OP_MUL_CC:
80998 case DUK_OP_DIV_RR:
80999 case DUK_OP_DIV_CR:
81000 case DUK_OP_DIV_RC:
81001 case DUK_OP_DIV_CC:
81002 case DUK_OP_MOD_RR:
81003 case DUK_OP_MOD_CR:
81004 case DUK_OP_MOD_RC:
81005 case DUK_OP_MOD_CC:
81006#if defined(DUK_USE_ES7_EXP_OPERATOR)
81007 case DUK_OP_EXP_RR:
81008 case DUK_OP_EXP_CR:
81009 case DUK_OP_EXP_RC:
81010 case DUK_OP_EXP_CC:
81011#endif /* DUK_USE_ES7_EXP_OPERATOR */
81012 {
81013 /* XXX: could leave value on stack top and goto replace_top_a; */
81015 break;
81016 }
81017#else /* DUK_USE_EXEC_PREFER_SIZE */
81018 case DUK_OP_SUB_RR: {
81020 break;
81021 }
81022 case DUK_OP_SUB_CR: {
81024 break;
81025 }
81026 case DUK_OP_SUB_RC: {
81028 break;
81029 }
81030 case DUK_OP_SUB_CC: {
81032 break;
81033 }
81034 case DUK_OP_MUL_RR: {
81036 break;
81037 }
81038 case DUK_OP_MUL_CR: {
81040 break;
81041 }
81042 case DUK_OP_MUL_RC: {
81044 break;
81045 }
81046 case DUK_OP_MUL_CC: {
81048 break;
81049 }
81050 case DUK_OP_DIV_RR: {
81052 break;
81053 }
81054 case DUK_OP_DIV_CR: {
81056 break;
81057 }
81058 case DUK_OP_DIV_RC: {
81060 break;
81061 }
81062 case DUK_OP_DIV_CC: {
81064 break;
81065 }
81066 case DUK_OP_MOD_RR: {
81068 break;
81069 }
81070 case DUK_OP_MOD_CR: {
81072 break;
81073 }
81074 case DUK_OP_MOD_RC: {
81076 break;
81077 }
81078 case DUK_OP_MOD_CC: {
81080 break;
81081 }
81082#if defined(DUK_USE_ES7_EXP_OPERATOR)
81083 case DUK_OP_EXP_RR: {
81085 break;
81086 }
81087 case DUK_OP_EXP_CR: {
81089 break;
81090 }
81091 case DUK_OP_EXP_RC: {
81093 break;
81094 }
81095 case DUK_OP_EXP_CC: {
81097 break;
81098 }
81099#endif /* DUK_USE_ES7_EXP_OPERATOR */
81100#endif /* DUK_USE_EXEC_PREFER_SIZE */
81101
81102#if defined(DUK_USE_EXEC_PREFER_SIZE)
81103 case DUK_OP_BAND_RR:
81104 case DUK_OP_BAND_CR:
81105 case DUK_OP_BAND_RC:
81106 case DUK_OP_BAND_CC:
81107 case DUK_OP_BOR_RR:
81108 case DUK_OP_BOR_CR:
81109 case DUK_OP_BOR_RC:
81110 case DUK_OP_BOR_CC:
81111 case DUK_OP_BXOR_RR:
81112 case DUK_OP_BXOR_CR:
81113 case DUK_OP_BXOR_RC:
81114 case DUK_OP_BXOR_CC:
81115 case DUK_OP_BASL_RR:
81116 case DUK_OP_BASL_CR:
81117 case DUK_OP_BASL_RC:
81118 case DUK_OP_BASL_CC:
81119 case DUK_OP_BLSR_RR:
81120 case DUK_OP_BLSR_CR:
81121 case DUK_OP_BLSR_RC:
81122 case DUK_OP_BLSR_CC:
81123 case DUK_OP_BASR_RR:
81124 case DUK_OP_BASR_CR:
81125 case DUK_OP_BASR_RC:
81126 case DUK_OP_BASR_CC: {
81127 /* XXX: could leave value on stack top and goto replace_top_a; */
81129 break;
81130 }
81131#else /* DUK_USE_EXEC_PREFER_SIZE */
81132 case DUK_OP_BAND_RR: {
81134 break;
81135 }
81136 case DUK_OP_BAND_CR: {
81138 break;
81139 }
81140 case DUK_OP_BAND_RC: {
81142 break;
81143 }
81144 case DUK_OP_BAND_CC: {
81146 break;
81147 }
81148 case DUK_OP_BOR_RR: {
81150 break;
81151 }
81152 case DUK_OP_BOR_CR: {
81154 break;
81155 }
81156 case DUK_OP_BOR_RC: {
81158 break;
81159 }
81160 case DUK_OP_BOR_CC: {
81162 break;
81163 }
81164 case DUK_OP_BXOR_RR: {
81166 break;
81167 }
81168 case DUK_OP_BXOR_CR: {
81170 break;
81171 }
81172 case DUK_OP_BXOR_RC: {
81174 break;
81175 }
81176 case DUK_OP_BXOR_CC: {
81178 break;
81179 }
81180 case DUK_OP_BASL_RR: {
81182 break;
81183 }
81184 case DUK_OP_BASL_CR: {
81186 break;
81187 }
81188 case DUK_OP_BASL_RC: {
81190 break;
81191 }
81192 case DUK_OP_BASL_CC: {
81194 break;
81195 }
81196 case DUK_OP_BLSR_RR: {
81198 break;
81199 }
81200 case DUK_OP_BLSR_CR: {
81202 break;
81203 }
81204 case DUK_OP_BLSR_RC: {
81206 break;
81207 }
81208 case DUK_OP_BLSR_CC: {
81210 break;
81211 }
81212 case DUK_OP_BASR_RR: {
81214 break;
81215 }
81216 case DUK_OP_BASR_CR: {
81218 break;
81219 }
81220 case DUK_OP_BASR_RC: {
81222 break;
81223 }
81224 case DUK_OP_BASR_CC: {
81226 break;
81227 }
81228#endif /* DUK_USE_EXEC_PREFER_SIZE */
81229
81230 /* For INSTOF and IN, B is always a register. */
81231#define DUK__INSTOF_BODY(barg, carg) \
81232 { \
81233 duk_bool_t tmp; \
81234 tmp = duk_js_instanceof(thr, (barg), (carg)); \
81235 DUK_ASSERT(tmp == 0 || tmp == 1); \
81236 DUK__REPLACE_BOOL_A_BREAK(tmp); \
81237 }
81238#define DUK__IN_BODY(barg, carg) \
81239 { \
81240 duk_bool_t tmp; \
81241 tmp = duk_js_in(thr, (barg), (carg)); \
81242 DUK_ASSERT(tmp == 0 || tmp == 1); \
81243 DUK__REPLACE_BOOL_A_BREAK(tmp); \
81244 }
81245#if defined(DUK_USE_EXEC_PREFER_SIZE)
81246 case DUK_OP_INSTOF_RR:
81247 case DUK_OP_INSTOF_CR:
81248 case DUK_OP_INSTOF_RC:
81249 case DUK_OP_INSTOF_CC:
81251 case DUK_OP_IN_RR:
81252 case DUK_OP_IN_CR:
81253 case DUK_OP_IN_RC:
81254 case DUK_OP_IN_CC:
81256#else /* DUK_USE_EXEC_PREFER_SIZE */
81257 case DUK_OP_INSTOF_RR:
81259 case DUK_OP_INSTOF_CR:
81261 case DUK_OP_INSTOF_RC:
81263 case DUK_OP_INSTOF_CC:
81265 case DUK_OP_IN_RR:
81267 case DUK_OP_IN_CR:
81269 case DUK_OP_IN_RC:
81271 case DUK_OP_IN_CC:
81273#endif /* DUK_USE_EXEC_PREFER_SIZE */
81274
81275 /* Pre/post inc/dec for register variables, important for loops. */
81276#if defined(DUK_USE_EXEC_PREFER_SIZE)
81277 case DUK_OP_PREINCR:
81278 case DUK_OP_PREDECR:
81279 case DUK_OP_POSTINCR:
81280 case DUK_OP_POSTDECR: {
81282 break;
81283 }
81284 case DUK_OP_PREINCV:
81285 case DUK_OP_PREDECV:
81286 case DUK_OP_POSTINCV:
81287 case DUK_OP_POSTDECV: {
81289 break;
81290 }
81291#else /* DUK_USE_EXEC_PREFER_SIZE */
81292 case DUK_OP_PREINCR: {
81294 break;
81295 }
81296 case DUK_OP_PREDECR: {
81298 break;
81299 }
81300 case DUK_OP_POSTINCR: {
81302 break;
81303 }
81304 case DUK_OP_POSTDECR: {
81306 break;
81307 }
81308 case DUK_OP_PREINCV: {
81310 break;
81311 }
81312 case DUK_OP_PREDECV: {
81314 break;
81315 }
81316 case DUK_OP_POSTINCV: {
81318 break;
81319 }
81320 case DUK_OP_POSTDECV: {
81322 break;
81323 }
81324#endif /* DUK_USE_EXEC_PREFER_SIZE */
81325
81326 /* XXX: Move to separate helper, optimize for perf/size separately. */
81327 /* Preinc/predec for object properties. */
81328 case DUK_OP_PREINCP_RR:
81329 case DUK_OP_PREINCP_CR:
81330 case DUK_OP_PREINCP_RC:
81331 case DUK_OP_PREINCP_CC:
81332 case DUK_OP_PREDECP_RR:
81333 case DUK_OP_PREDECP_CR:
81334 case DUK_OP_PREDECP_RC:
81335 case DUK_OP_PREDECP_CC:
81336 case DUK_OP_POSTINCP_RR:
81337 case DUK_OP_POSTINCP_CR:
81338 case DUK_OP_POSTINCP_RC:
81339 case DUK_OP_POSTINCP_CC:
81340 case DUK_OP_POSTDECP_RR:
81341 case DUK_OP_POSTDECP_CR:
81342 case DUK_OP_POSTDECP_RC:
81343 case DUK_OP_POSTDECP_CC: {
81344 duk_tval *tv_obj;
81345 duk_tval *tv_key;
81346 duk_tval *tv_val;
81347 duk_bool_t rc;
81348 duk_double_t x, y, z;
81349#if !defined(DUK_USE_EXEC_PREFER_SIZE)
81350 duk_tval *tv_dst;
81351#endif /* DUK_USE_EXEC_PREFER_SIZE */
81352
81353 /* A -> target reg
81354 * B -> object reg/const (may be const e.g. in "'foo'[1]")
81355 * C -> key reg/const
81356 */
81357
81358 /* Opcode bits 0-1 are used to distinguish reg/const variants.
81359 * Opcode bits 2-3 are used to distinguish inc/dec variants:
81360 * Bit 2 = inc(0)/dec(1), bit 3 = pre(0)/post(1).
81361 */
81362 DUK_ASSERT((DUK_OP_PREINCP_RR & 0x0c) == 0x00);
81363 DUK_ASSERT((DUK_OP_PREDECP_RR & 0x0c) == 0x04);
81364 DUK_ASSERT((DUK_OP_POSTINCP_RR & 0x0c) == 0x08);
81365 DUK_ASSERT((DUK_OP_POSTDECP_RR & 0x0c) == 0x0c);
81366
81367 tv_obj = DUK__REGCONSTP_B(ins);
81368 tv_key = DUK__REGCONSTP_C(ins);
81369 rc = duk_hobject_getprop(thr, tv_obj, tv_key); /* -> [val] */
81370 DUK_UNREF(rc); /* ignore */
81371 tv_obj = NULL; /* invalidated */
81372 tv_key = NULL; /* invalidated */
81373
81374 /* XXX: Fastint fast path would be useful here. Also fastints
81375 * now lose their fastint status in current handling which is
81376 * not intuitive.
81377 */
81378
81379 x = duk_to_number_m1(thr);
81380 duk_pop_unsafe(thr);
81381 if (ins & DUK_BC_INCDECP_FLAG_DEC) {
81382 y = x - 1.0;
81383 } else {
81384 y = x + 1.0;
81385 }
81386
81387 duk_push_number(thr, y);
81388 tv_val = DUK_GET_TVAL_NEGIDX(thr, -1);
81389 DUK_ASSERT(tv_val != NULL);
81390 tv_obj = DUK__REGCONSTP_B(ins);
81391 tv_key = DUK__REGCONSTP_C(ins);
81392 rc = duk_hobject_putprop(thr, tv_obj, tv_key, tv_val, DUK__STRICT());
81393 DUK_UNREF(rc); /* ignore */
81394 tv_obj = NULL; /* invalidated */
81395 tv_key = NULL; /* invalidated */
81396 duk_pop_unsafe(thr);
81397
81398 z = (ins & DUK_BC_INCDECP_FLAG_POST) ? x : y;
81399#if defined(DUK_USE_EXEC_PREFER_SIZE)
81400 duk_push_number(thr, z);
81402#else
81403 tv_dst = DUK__REGP_A(ins);
81404 DUK_TVAL_SET_NUMBER_UPDREF(thr, tv_dst, z);
81405 break;
81406#endif
81407 }
81408
81409 /* XXX: GETPROP where object is 'this', GETPROPT?
81410 * Occurs relatively often in object oriented code.
81411 */
81412
81413#define DUK__GETPROP_BODY(barg, carg) \
81414 { \
81415 /* A -> target reg \
81416 * B -> object reg/const (may be const e.g. in "'foo'[1]") \
81417 * C -> key reg/const \
81418 */ \
81419 (void) duk_hobject_getprop(thr, (barg), (carg)); \
81420 DUK__REPLACE_TOP_A_BREAK(); \
81421 }
81422#define DUK__GETPROPC_BODY(barg, carg) \
81423 { \
81424 /* Same as GETPROP but callability check for property-based calls. */ \
81425 duk_tval *tv__targ; \
81426 (void) duk_hobject_getprop(thr, (barg), (carg)); \
81427 DUK_GC_TORTURE(thr->heap); \
81428 tv__targ = DUK_GET_TVAL_NEGIDX(thr, -1); \
81429 if (DUK_UNLIKELY(!duk_is_callable_tval(thr, tv__targ))) { \
81430 /* Here we intentionally re-evaluate the macro \
81431 * arguments to deal with potentially changed \
81432 * valstack base pointer! \
81433 */ \
81434 duk_call_setup_propcall_error(thr, (barg), (carg)); \
81435 } \
81436 DUK__REPLACE_TOP_A_BREAK(); \
81437 }
81438#define DUK__PUTPROP_BODY(aarg, barg, carg) \
81439 { \
81440 /* A -> object reg \
81441 * B -> key reg/const \
81442 * C -> value reg/const \
81443 * \
81444 * Note: intentional difference to register arrangement \
81445 * of e.g. GETPROP; 'A' must contain a register-only value. \
81446 */ \
81447 (void) duk_hobject_putprop(thr, (aarg), (barg), (carg), DUK__STRICT()); \
81448 break; \
81449 }
81450#define DUK__DELPROP_BODY(barg, carg) \
81451 { \
81452 /* A -> result reg \
81453 * B -> object reg \
81454 * C -> key reg/const \
81455 */ \
81456 duk_bool_t rc; \
81457 rc = duk_hobject_delprop(thr, (barg), (carg), DUK__STRICT()); \
81458 DUK_ASSERT(rc == 0 || rc == 1); \
81459 DUK__REPLACE_BOOL_A_BREAK(rc); \
81460 }
81461#if defined(DUK_USE_EXEC_PREFER_SIZE)
81462 case DUK_OP_GETPROP_RR:
81463 case DUK_OP_GETPROP_CR:
81464 case DUK_OP_GETPROP_RC:
81465 case DUK_OP_GETPROP_CC:
81467#if defined(DUK_USE_VERBOSE_ERRORS)
81468 case DUK_OP_GETPROPC_RR:
81469 case DUK_OP_GETPROPC_CR:
81470 case DUK_OP_GETPROPC_RC:
81471 case DUK_OP_GETPROPC_CC:
81473#endif
81474 case DUK_OP_PUTPROP_RR:
81475 case DUK_OP_PUTPROP_CR:
81476 case DUK_OP_PUTPROP_RC:
81477 case DUK_OP_PUTPROP_CC:
81479 case DUK_OP_DELPROP_RR:
81480 case DUK_OP_DELPROP_RC: /* B is always reg */
81482#else /* DUK_USE_EXEC_PREFER_SIZE */
81483 case DUK_OP_GETPROP_RR:
81485 case DUK_OP_GETPROP_CR:
81487 case DUK_OP_GETPROP_RC:
81489 case DUK_OP_GETPROP_CC:
81491#if defined(DUK_USE_VERBOSE_ERRORS)
81492 case DUK_OP_GETPROPC_RR:
81494 case DUK_OP_GETPROPC_CR:
81496 case DUK_OP_GETPROPC_RC:
81498 case DUK_OP_GETPROPC_CC:
81500#endif
81501 case DUK_OP_PUTPROP_RR:
81503 case DUK_OP_PUTPROP_CR:
81505 case DUK_OP_PUTPROP_RC:
81507 case DUK_OP_PUTPROP_CC:
81509 case DUK_OP_DELPROP_RR: /* B is always reg */
81511 case DUK_OP_DELPROP_RC:
81513#endif /* DUK_USE_EXEC_PREFER_SIZE */
81514
81515 /* No fast path for DECLVAR now, it's quite a rare instruction. */
81516 case DUK_OP_DECLVAR_RR:
81517 case DUK_OP_DECLVAR_CR:
81518 case DUK_OP_DECLVAR_RC:
81519 case DUK_OP_DECLVAR_CC: {
81520 duk_activation *act;
81522 duk_tval *tv1;
81523 duk_hstring *name;
81524 duk_small_uint_t prop_flags;
81525 duk_bool_t is_func_decl;
81526
81527 tv1 = DUK__REGCONSTP_B(ins);
81529 name = DUK_TVAL_GET_STRING(tv1);
81530 DUK_ASSERT(name != NULL);
81531
81532 is_func_decl = ((a & DUK_BC_DECLVAR_FLAG_FUNC_DECL) != 0);
81533
81534 /* XXX: declvar takes an duk_tval pointer, which is awkward and
81535 * should be reworked.
81536 */
81537
81538 /* Compiler is responsible for selecting property flags (configurability,
81539 * writability, etc).
81540 */
81541 prop_flags = a & DUK_PROPDESC_FLAGS_MASK;
81542
81543 if (is_func_decl) {
81545 } else {
81546 DUK_ASSERT(DUK_TVAL_IS_UNDEFINED(thr->valstack_top)); /* valstack policy */
81547 thr->valstack_top++;
81548 }
81549 tv1 = DUK_GET_TVAL_NEGIDX(thr, -1);
81550
81551 act = thr->callstack_curr;
81552 if (duk_js_declvar_activation(thr, act, name, tv1, prop_flags, is_func_decl)) {
81553 if (is_func_decl) {
81554 /* Already declared, update value. */
81555 tv1 = DUK_GET_TVAL_NEGIDX(thr, -1);
81556 duk_js_putvar_activation(thr, act, name, tv1, DUK__STRICT());
81557 } else {
81558 /* Already declared but no initializer value
81559 * (e.g. 'var xyz;'), no-op.
81560 */
81561 }
81562 }
81563
81564 duk_pop_unsafe(thr);
81565 break;
81566 }
81567
81568#if defined(DUK_USE_REGEXP_SUPPORT)
81569 /* The compiler should never emit DUK_OP_REGEXP if there is no
81570 * regexp support.
81571 */
81572 case DUK_OP_REGEXP_RR:
81573 case DUK_OP_REGEXP_CR:
81574 case DUK_OP_REGEXP_RC:
81575 case DUK_OP_REGEXP_CC: {
81576 /* A -> target register
81577 * B -> bytecode (also contains flags)
81578 * C -> escaped source
81579 */
81580
81582 duk_push_tval(thr, DUK__REGCONSTP_B(ins)); /* -> [ ... escaped_source bytecode ] */
81583 duk_regexp_create_instance(thr); /* -> [ ... regexp_instance ] */
81585 }
81586#endif /* DUK_USE_REGEXP_SUPPORT */
81587
81588 /* XXX: 'c' is unused, use whole BC, etc. */
81589 case DUK_OP_CSVAR_RR:
81590 case DUK_OP_CSVAR_CR:
81591 case DUK_OP_CSVAR_RC:
81592 case DUK_OP_CSVAR_CC: {
81593 /* The speciality of calling through a variable binding is that the
81594 * 'this' value may be provided by the variable lookup: E5 Section 6.b.i.
81595 *
81596 * The only (standard) case where the 'this' binding is non-null is when
81597 * (1) the variable is found in an object environment record, and
81598 * (2) that object environment record is a 'with' block.
81599 */
81600
81601 duk_activation *act;
81602 duk_uint_fast_t idx;
81603 duk_tval *tv1;
81604 duk_hstring *name;
81605
81606 /* A -> target registers (A, A + 1) for call setup
81607 * B -> identifier name, usually constant but can be a register due to shuffling
81608 */
81609
81610 tv1 = DUK__REGCONSTP_B(ins);
81612 name = DUK_TVAL_GET_STRING(tv1);
81613 DUK_ASSERT(name != NULL);
81614 act = thr->callstack_curr;
81615 (void) duk_js_getvar_activation(thr, act, name, 1 /*throw*/); /* -> [... val this] */
81616
81617 idx = (duk_uint_fast_t) DUK_DEC_A(ins);
81618
81619 /* Could add direct value stack handling. */
81620 duk_replace(thr, (duk_idx_t) (idx + 1)); /* 'this' binding */
81621 duk_replace(thr, (duk_idx_t) idx); /* variable value (function, we hope, not checked here) */
81622 break;
81623 }
81624
81625 case DUK_OP_CLOSURE: {
81626 duk_activation *act;
81627 duk_hcompfunc *fun_act;
81629 duk_hobject *fun_temp;
81630
81631 /* A -> target reg
81632 * BC -> inner function index
81633 */
81634
81635 DUK_DDD(DUK_DDDPRINT("CLOSURE to target register %ld, fnum %ld (count %ld)",
81636 (long) DUK_DEC_A(ins),
81637 (long) DUK_DEC_BC(ins),
81638 (long) DUK_HCOMPFUNC_GET_FUNCS_COUNT(thr->heap, DUK__FUN())));
81639
81640 DUK_ASSERT_DISABLE(bc >= 0); /* unsigned */
81642
81643 act = thr->callstack_curr;
81644 fun_act = (duk_hcompfunc *) DUK_ACT_GET_FUNC(act);
81645 fun_temp = DUK_HCOMPFUNC_GET_FUNCS_BASE(thr->heap, fun_act)[bc];
81646 DUK_ASSERT(fun_temp != NULL);
81648
81649 DUK_DDD(
81650 DUK_DDDPRINT("CLOSURE: function template is: %p -> %!O", (void *) fun_temp, (duk_heaphdr *) fun_temp));
81651
81652 if (act->lex_env == NULL) {
81653 DUK_ASSERT(act->var_env == NULL);
81655 act = thr->callstack_curr;
81656 }
81657 DUK_ASSERT(act->lex_env != NULL);
81658 DUK_ASSERT(act->var_env != NULL);
81659
81660 /* functions always have a NEWENV flag, i.e. they get a
81661 * new variable declaration environment, so only lex_env
81662 * matters here.
81663 */
81664 duk_js_push_closure(thr, (duk_hcompfunc *) fun_temp, act->var_env, act->lex_env, 1 /*add_auto_proto*/);
81666 }
81667
81668 case DUK_OP_GETVAR: {
81669 duk_activation *act;
81670 duk_tval *tv1;
81671 duk_hstring *name;
81672
81673 tv1 = DUK__CONSTP_BC(ins);
81675 name = DUK_TVAL_GET_STRING(tv1);
81676 DUK_ASSERT(name != NULL);
81677 act = thr->callstack_curr;
81678 DUK_ASSERT(act != NULL);
81679 (void) duk_js_getvar_activation(thr, act, name, 1 /*throw*/); /* -> [... val this] */
81680 duk_pop_unsafe(thr); /* 'this' binding is not needed here */
81682 }
81683
81684 case DUK_OP_PUTVAR: {
81685 duk_activation *act;
81686 duk_tval *tv1;
81687 duk_hstring *name;
81688
81689 tv1 = DUK__CONSTP_BC(ins);
81691 name = DUK_TVAL_GET_STRING(tv1);
81692 DUK_ASSERT(name != NULL);
81693
81694 /* XXX: putvar takes a duk_tval pointer, which is awkward and
81695 * should be reworked.
81696 */
81697
81698 tv1 = DUK__REGP_A(ins); /* val */
81699 act = thr->callstack_curr;
81700 duk_js_putvar_activation(thr, act, name, tv1, DUK__STRICT());
81701 break;
81702 }
81703
81704 case DUK_OP_DELVAR: {
81705 duk_activation *act;
81706 duk_tval *tv1;
81707 duk_hstring *name;
81708 duk_bool_t rc;
81709
81710 tv1 = DUK__CONSTP_BC(ins);
81712 name = DUK_TVAL_GET_STRING(tv1);
81713 DUK_ASSERT(name != NULL);
81714 act = thr->callstack_curr;
81715 rc = duk_js_delvar_activation(thr, act, name);
81717 }
81718
81719 case DUK_OP_JUMP: {
81720 /* Note: without explicit cast to signed, MSVC will
81721 * apparently generate a large positive jump when the
81722 * bias-corrected value would normally be negative.
81723 */
81725 break;
81726 }
81727
81728#define DUK__RETURN_SHARED() \
81729 do { \
81730 duk_small_uint_t ret_result; \
81731 /* duk__handle_return() is guaranteed never to throw, except \
81732 * for potential out-of-memory situations which will then \
81733 * propagate out of the executor longjmp handler. \
81734 */ \
81735 DUK_ASSERT(thr->ptr_curr_pc == NULL); \
81736 ret_result = duk__handle_return(thr, entry_act); \
81737 if (ret_result == DUK__RETHAND_RESTART) { \
81738 goto restart_execution; \
81739 } \
81740 DUK_ASSERT(ret_result == DUK__RETHAND_FINISHED); \
81741 return; \
81742 } while (0)
81743#if defined(DUK_USE_EXEC_PREFER_SIZE)
81744 case DUK_OP_RETREG:
81745 case DUK_OP_RETCONST:
81746 case DUK_OP_RETCONSTN:
81747 case DUK_OP_RETUNDEF: {
81748 /* BC -> return value reg/const */
81749
81751
81752 if (op == DUK_OP_RETREG) {
81753 duk_push_tval(thr, DUK__REGP_BC(ins));
81754 } else if (op == DUK_OP_RETUNDEF) {
81755 DUK_ASSERT(DUK_TVAL_IS_UNDEFINED(thr->valstack_top)); /* valstack policy */
81756 thr->valstack_top++;
81757 } else {
81759 duk_push_tval(thr, DUK__CONSTP_BC(ins));
81760 }
81761
81763 }
81764#else /* DUK_USE_EXEC_PREFER_SIZE */
81765 case DUK_OP_RETREG: {
81766 duk_tval *tv;
81767
81769 tv = DUK__REGP_BC(ins);
81770 DUK_TVAL_SET_TVAL(thr->valstack_top, tv);
81771 DUK_TVAL_INCREF(thr, tv);
81772 thr->valstack_top++;
81774 }
81775 /* This will be unused without refcounting. */
81776 case DUK_OP_RETCONST: {
81777 duk_tval *tv;
81778
81780 tv = DUK__CONSTP_BC(ins);
81781 DUK_TVAL_SET_TVAL(thr->valstack_top, tv);
81782 DUK_TVAL_INCREF(thr, tv);
81783 thr->valstack_top++;
81785 }
81786 case DUK_OP_RETCONSTN: {
81787 duk_tval *tv;
81788
81790 tv = DUK__CONSTP_BC(ins);
81791 DUK_TVAL_SET_TVAL(thr->valstack_top, tv);
81792#if defined(DUK_USE_REFERENCE_COUNTING)
81793 /* Without refcounting only RETCONSTN is used. */
81794 DUK_ASSERT(!DUK_TVAL_IS_HEAP_ALLOCATED(tv)); /* no INCREF for this constant */
81795#endif
81796 thr->valstack_top++;
81798 }
81799 case DUK_OP_RETUNDEF: {
81801 thr->valstack_top++; /* value at valstack top is already undefined by valstack policy */
81802 DUK_ASSERT(DUK_TVAL_IS_UNDEFINED(thr->valstack_top));
81804 }
81805#endif /* DUK_USE_EXEC_PREFER_SIZE */
81806
81807 case DUK_OP_LABEL: {
81808 duk_activation *act;
81809 duk_catcher *cat;
81811
81812 /* Allocate catcher and populate it (must be atomic). */
81813
81814 cat = duk_hthread_catcher_alloc(thr);
81815 DUK_ASSERT(cat != NULL);
81816
81817 cat->flags = (duk_uint32_t) (DUK_CAT_TYPE_LABEL | (bc << DUK_CAT_LABEL_SHIFT));
81818 cat->pc_base = (duk_instr_t *) curr_pc; /* pre-incremented, points to first jump slot */
81819 cat->idx_base = 0; /* unused for label */
81820 cat->h_varname = NULL;
81821
81822 act = thr->callstack_curr;
81823 DUK_ASSERT(act != NULL);
81824 cat->parent = act->cat;
81825 act->cat = cat;
81826
81827 DUK_DDD(DUK_DDDPRINT("LABEL catcher: flags=0x%08lx, pc_base=%ld, "
81828 "idx_base=%ld, h_varname=%!O, label_id=%ld",
81829 (long) cat->flags,
81830 (long) cat->pc_base,
81831 (long) cat->idx_base,
81832 (duk_heaphdr *) cat->h_varname,
81833 (long) DUK_CAT_GET_LABEL(cat)));
81834
81835 curr_pc += 2; /* skip jump slots */
81836 break;
81837 }
81838
81839 case DUK_OP_ENDLABEL: {
81840 duk_activation *act;
81841#if (defined(DUK_USE_DEBUG_LEVEL) && (DUK_USE_DEBUG_LEVEL >= 2)) || defined(DUK_USE_ASSERTIONS)
81843#endif
81844#if defined(DUK_USE_DEBUG_LEVEL) && (DUK_USE_DEBUG_LEVEL >= 2)
81845 DUK_DDD(DUK_DDDPRINT("ENDLABEL %ld", (long) bc));
81846#endif
81847
81848 act = thr->callstack_curr;
81849 DUK_ASSERT(act->cat != NULL);
81853
81854 /* no need to unwind callstack */
81855 break;
81856 }
81857
81858 case DUK_OP_BREAK: {
81860
81863 goto restart_execution;
81864 }
81865
81866 case DUK_OP_CONTINUE: {
81868
81871 goto restart_execution;
81872 }
81873
81874 /* XXX: move to helper, too large to be inline here */
81875 case DUK_OP_TRYCATCH: {
81876 duk__handle_op_trycatch(thr, ins, curr_pc);
81877 curr_pc += 2; /* skip jump slots */
81878 break;
81879 }
81880
81881 case DUK_OP_ENDTRY: {
81882 curr_pc = duk__handle_op_endtry(thr, ins);
81883 break;
81884 }
81885
81886 case DUK_OP_ENDCATCH: {
81887 duk__handle_op_endcatch(thr, ins);
81888 break;
81889 }
81890
81891 case DUK_OP_ENDFIN: {
81892 /* Sync and NULL early. */
81894
81895 if (duk__handle_op_endfin(thr, ins, entry_act) != 0) {
81896 return;
81897 }
81898
81899 /* Must restart because we NULLed out curr_pc. */
81900 goto restart_execution;
81901 }
81902
81903 case DUK_OP_THROW: {
81905
81906 /* Note: errors are augmented when they are created, not
81907 * when they are thrown. So, don't augment here, it would
81908 * break re-throwing for instance.
81909 */
81910
81911 /* Sync so that augmentation sees up-to-date activations, NULL
81912 * thr->ptr_curr_pc so that it's not used if side effects occur
81913 * in augmentation or longjmp handling.
81914 */
81916
81917 duk_dup(thr, (duk_idx_t) bc);
81918 DUK_DDD(DUK_DDDPRINT("THROW ERROR (BYTECODE): %!dT (before throw augment)",
81919 (duk_tval *) duk_get_tval(thr, -1)));
81920#if defined(DUK_USE_AUGMENT_ERROR_THROW)
81922 DUK_DDD(
81923 DUK_DDDPRINT("THROW ERROR (BYTECODE): %!dT (after throw augment)", (duk_tval *) duk_get_tval(thr, -1)));
81924#endif
81925
81927#if defined(DUK_USE_DEBUGGER_SUPPORT)
81928 duk_err_check_debugger_integration(thr);
81929#endif
81930
81931 DUK_ASSERT(thr->heap->lj.jmpbuf_ptr != NULL); /* always in executor */
81932 duk_err_longjmp(thr);
81934 break;
81935 }
81936
81937 case DUK_OP_CSREG: {
81938 /*
81939 * Assuming a register binds to a variable declared within this
81940 * function (a declarative binding), the 'this' for the call
81941 * setup is always 'undefined'. E5 Section 10.2.1.1.6.
81942 */
81943
81946
81947 /* A -> register containing target function (not type checked here)
81948 * BC -> target registers (BC, BC + 1) for call setup
81949 */
81950
81951#if defined(DUK_USE_PREFER_SIZE)
81952 duk_dup(thr, (duk_idx_t) a);
81953 duk_replace(thr, (duk_idx_t) bc);
81954 duk_to_undefined(thr, (duk_idx_t) (bc + 1));
81955#else
81956 duk_tval *tv1;
81957 duk_tval *tv2;
81958 duk_tval *tv3;
81959 duk_tval tv_tmp1;
81960 duk_tval tv_tmp2;
81961
81962 tv1 = DUK__REGP(bc);
81963 tv2 = tv1 + 1;
81964 DUK_TVAL_SET_TVAL(&tv_tmp1, tv1);
81965 DUK_TVAL_SET_TVAL(&tv_tmp2, tv2);
81966 tv3 = DUK__REGP(a);
81967 DUK_TVAL_SET_TVAL(tv1, tv3);
81968 DUK_TVAL_INCREF(thr, tv1); /* no side effects */
81969 DUK_TVAL_SET_UNDEFINED(tv2); /* no need for incref */
81970 DUK_TVAL_DECREF(thr, &tv_tmp1);
81971 DUK_TVAL_DECREF(thr, &tv_tmp2);
81972#endif
81973 break;
81974 }
81975
81976 /* XXX: in some cases it's faster NOT to reuse the value
81977 * stack but rather copy the arguments on top of the stack
81978 * (mainly when the calling value stack is large and the value
81979 * stack resize would be large).
81980 */
81981
81982 case DUK_OP_CALL0:
81983 case DUK_OP_CALL1:
81984 case DUK_OP_CALL2:
81985 case DUK_OP_CALL3:
81986 case DUK_OP_CALL4:
81987 case DUK_OP_CALL5:
81988 case DUK_OP_CALL6:
81989 case DUK_OP_CALL7: {
81990 /* Opcode packs 4 flag bits: 1 for indirect, 3 map
81991 * 1:1 to three lowest call handling flags.
81992 *
81993 * A -> nargs or register with nargs (indirect)
81994 * BC -> base register for call (base -> func, base+1 -> this, base+2 -> arg1 ... base+2+N-1 -> argN)
81995 */
81996
81997 duk_idx_t nargs;
81998 duk_idx_t idx;
81999 duk_small_uint_t call_flags;
82000#if !defined(DUK_USE_EXEC_FUN_LOCAL)
82001 duk_hcompfunc *fun;
82002#endif
82003
82004 DUK_ASSERT((DUK_OP_CALL0 & 0x0fU) == 0);
82006
82007 nargs = (duk_idx_t) DUK_DEC_A(ins);
82008 call_flags = (ins & 0x07U) | DUK_CALL_FLAG_ALLOW_ECMATOECMA;
82009 idx = (duk_idx_t) DUK_DEC_BC(ins);
82010
82011 if (duk__executor_handle_call(thr, idx, nargs, call_flags)) {
82012 /* curr_pc synced by duk_handle_call_unprotected() */
82013 DUK_ASSERT(thr->ptr_curr_pc == NULL);
82014 goto restart_execution;
82015 }
82016 DUK_ASSERT(thr->ptr_curr_pc != NULL);
82017
82018 /* duk_js_call.c is required to restore the stack reserve
82019 * so we only need to reset the top.
82020 */
82021#if !defined(DUK_USE_EXEC_FUN_LOCAL)
82022 fun = DUK__FUN();
82023#endif
82024 duk_set_top_unsafe(thr, (duk_idx_t) fun->nregs);
82025
82026 /* No need to reinit setjmp() catchpoint, as call handling
82027 * will store and restore our state.
82028 *
82029 * When debugger is enabled, we need to recheck the activation
82030 * status after returning. This is now handled by call handling
82031 * and heap->dbg_force_restart.
82032 */
82033 break;
82034 }
82035
82036 case DUK_OP_CALL8:
82037 case DUK_OP_CALL9:
82038 case DUK_OP_CALL10:
82039 case DUK_OP_CALL11:
82040 case DUK_OP_CALL12:
82041 case DUK_OP_CALL13:
82042 case DUK_OP_CALL14:
82043 case DUK_OP_CALL15: {
82044 /* Indirect variant. */
82045 duk_uint_fast_t nargs;
82046 duk_idx_t idx;
82047 duk_small_uint_t call_flags;
82048#if !defined(DUK_USE_EXEC_FUN_LOCAL)
82049 duk_hcompfunc *fun;
82050#endif
82051
82052 DUK_ASSERT((DUK_OP_CALL0 & 0x0fU) == 0);
82054
82055 nargs = (duk_uint_fast_t) DUK_DEC_A(ins);
82056 DUK__LOOKUP_INDIRECT(nargs);
82057 call_flags = (ins & 0x07U) | DUK_CALL_FLAG_ALLOW_ECMATOECMA;
82058 idx = (duk_idx_t) DUK_DEC_BC(ins);
82059
82060 if (duk__executor_handle_call(thr, idx, (duk_idx_t) nargs, call_flags)) {
82061 DUK_ASSERT(thr->ptr_curr_pc == NULL);
82062 goto restart_execution;
82063 }
82064 DUK_ASSERT(thr->ptr_curr_pc != NULL);
82065
82066#if !defined(DUK_USE_EXEC_FUN_LOCAL)
82067 fun = DUK__FUN();
82068#endif
82069 duk_set_top_unsafe(thr, (duk_idx_t) fun->nregs);
82070 break;
82071 }
82072
82073 case DUK_OP_NEWOBJ: {
82074 duk_push_object(thr);
82075#if defined(DUK_USE_ASSERTIONS)
82076 {
82077 duk_hobject *h;
82078 h = duk_require_hobject(thr, -1);
82083 }
82084#endif
82085#if !defined(DUK_USE_PREFER_SIZE)
82086 /* XXX: could do a direct props realloc, but need hash size */
82088#endif
82090 }
82091
82092 case DUK_OP_NEWARR: {
82093 duk_push_array(thr);
82094#if defined(DUK_USE_ASSERTIONS)
82095 {
82096 duk_hobject *h;
82097 h = duk_require_hobject(thr, -1);
82103 }
82104#endif
82105#if !defined(DUK_USE_PREFER_SIZE)
82107 duk_known_hobject(thr, -1),
82108 0 /*new_e_size*/,
82109 DUK_DEC_A(ins) /*new_a_size*/,
82110 0 /*new_h_size*/,
82111 0 /*abandon_array*/);
82112#if 0
82113 duk_hobject_resize_arraypart(thr, duk_known_hobject(thr, -1), DUK_DEC_A(ins));
82114#endif
82115#endif
82117 }
82118
82119 case DUK_OP_MPUTOBJ:
82120 case DUK_OP_MPUTOBJI: {
82121 duk_idx_t obj_idx;
82122 duk_uint_fast_t idx, idx_end;
82124
82125 /* A -> register of target object
82126 * B -> first register of key/value pair list
82127 * or register containing first register number if indirect
82128 * C -> number of key/value pairs * 2
82129 * (= number of value stack indices used starting from 'B')
82130 */
82131
82132 obj_idx = DUK_DEC_A(ins);
82133 DUK_ASSERT(duk_is_object(thr, obj_idx));
82134
82135 idx = (duk_uint_fast_t) DUK_DEC_B(ins);
82136 if (DUK_DEC_OP(ins) == DUK_OP_MPUTOBJI) {
82138 }
82139
82141 DUK_ASSERT(count > 0); /* compiler guarantees */
82142 idx_end = idx + count;
82143
82144#if defined(DUK_USE_EXEC_INDIRECT_BOUND_CHECK)
82145 if (DUK_UNLIKELY(idx_end > (duk_uint_fast_t) duk_get_top(thr))) {
82146 /* XXX: use duk_is_valid_index() instead? */
82147 /* XXX: improve check; check against nregs, not against top */
82148 DUK__INTERNAL_ERROR("MPUTOBJ out of bounds");
82149 }
82150#endif
82151
82152 /* Use 'force' flag to duk_def_prop() to ensure that any
82153 * inherited properties don't prevent the operation.
82154 * With ES2015 duplicate properties are allowed, so that we
82155 * must overwrite any previous data or accessor property.
82156 *
82157 * With ES2015 computed property names the literal keys
82158 * may be arbitrary values and need to be ToPropertyKey()
82159 * coerced at runtime.
82160 */
82161 do {
82162 /* XXX: faster initialization (direct access or better primitives) */
82163 duk_dup(thr, (duk_idx_t) idx);
82164 duk_dup(thr, (duk_idx_t) (idx + 1));
82165 duk_def_prop(thr,
82166 obj_idx,
82169 idx += 2;
82170 } while (idx < idx_end);
82171 break;
82172 }
82173
82174 case DUK_OP_INITSET:
82175 case DUK_OP_INITGET: {
82177 break;
82178 }
82179
82180 case DUK_OP_MPUTARR:
82181 case DUK_OP_MPUTARRI: {
82182 duk_idx_t obj_idx;
82183 duk_uint_fast_t idx, idx_end;
82185 duk_tval *tv1;
82186 duk_uint32_t arr_idx;
82187
82188 /* A -> register of target object
82189 * B -> first register of value data (start_index, value1, value2, ..., valueN)
82190 * or register containing first register number if indirect
82191 * C -> number of key/value pairs (N)
82192 */
82193
82194 obj_idx = DUK_DEC_A(ins);
82195 DUK_ASSERT(duk_is_object(thr, obj_idx));
82196
82197 idx = (duk_uint_fast_t) DUK_DEC_B(ins);
82198 if (DUK_DEC_OP(ins) == DUK_OP_MPUTARRI) {
82200 }
82201
82203 DUK_ASSERT(count > 0 + 1); /* compiler guarantees */
82204 idx_end = idx + count;
82205
82206#if defined(DUK_USE_EXEC_INDIRECT_BOUND_CHECK)
82207 if (idx_end > (duk_uint_fast_t) duk_get_top(thr)) {
82208 /* XXX: use duk_is_valid_index() instead? */
82209 /* XXX: improve check; check against nregs, not against top */
82210 DUK__INTERNAL_ERROR("MPUTARR out of bounds");
82211 }
82212#endif
82213
82214 tv1 = DUK__REGP(idx);
82216#if defined(DUK_USE_FASTINT)
82218 arr_idx = (duk_uint32_t) DUK_TVAL_GET_FASTINT_U32(tv1);
82219#else
82220 arr_idx = (duk_uint32_t) DUK_TVAL_GET_NUMBER(tv1);
82221#endif
82222 idx++;
82223
82224 do {
82225 /* duk_xdef_prop() will define an own property without any array
82226 * special behaviors. We'll need to set the array length explicitly
82227 * in the end. For arrays with elisions, the compiler will emit an
82228 * explicit SETALEN which will update the length.
82229 */
82230
82231 /* XXX: because we're dealing with 'own' properties of a fresh array,
82232 * the array initializer should just ensure that the array has a large
82233 * enough array part and write the values directly into array part,
82234 * and finally set 'length' manually in the end (as already happens now).
82235 */
82236
82237 duk_dup(thr, (duk_idx_t) idx);
82238 duk_xdef_prop_index_wec(thr, obj_idx, arr_idx);
82239
82240 idx++;
82241 arr_idx++;
82242 } while (idx < idx_end);
82243
82244 /* XXX: E5.1 Section 11.1.4 coerces the final length through
82245 * ToUint32() which is odd but happens now as a side effect of
82246 * 'arr_idx' type.
82247 */
82248 duk_set_length(thr, obj_idx, (duk_size_t) (duk_uarridx_t) arr_idx);
82249 break;
82250 }
82251
82252 case DUK_OP_SETALEN: {
82253 duk_tval *tv1;
82254 duk_hobject *h;
82255 duk_uint32_t len;
82256
82257 tv1 = DUK__REGP_A(ins);
82259 h = DUK_TVAL_GET_OBJECT(tv1);
82261
82262 tv1 = DUK__REGP_BC(ins);
82264#if defined(DUK_USE_FASTINT)
82266 len = (duk_uint32_t) DUK_TVAL_GET_FASTINT_U32(tv1);
82267#else
82268 len = (duk_uint32_t) DUK_TVAL_GET_NUMBER(tv1);
82269#endif
82270 ((duk_harray *) h)->length = len;
82271 break;
82272 }
82273
82274 case DUK_OP_INITENUM: {
82275 duk__handle_op_initenum(thr, ins);
82276 break;
82277 }
82278
82279 case DUK_OP_NEXTENUM: {
82280 curr_pc += duk__handle_op_nextenum(thr, ins);
82281 break;
82282 }
82283
82284 case DUK_OP_INVLHS: {
82286 DUK_WO_NORETURN(return;);
82287 break;
82288 }
82289
82290 case DUK_OP_DEBUGGER: {
82291 /* Opcode only emitted by compiler when debugger
82292 * support is enabled. Ignore it silently without
82293 * debugger support, in case it has been loaded
82294 * from precompiled bytecode.
82295 */
82296#if defined(DUK_USE_DEBUGGER_SUPPORT)
82297 if (duk_debug_is_attached(thr->heap)) {
82298 DUK_D(DUK_DPRINT("DEBUGGER statement encountered, halt execution"));
82300 duk_debug_halt_execution(thr, 1 /*use_prev_pc*/);
82301 DUK_D(DUK_DPRINT("DEBUGGER statement finished, resume execution"));
82302 goto restart_execution;
82303 } else {
82304 DUK_D(DUK_DPRINT("DEBUGGER statement ignored, debugger not attached"));
82305 }
82306#else
82307 DUK_D(DUK_DPRINT("DEBUGGER statement ignored, no debugger support"));
82308#endif
82309 break;
82310 }
82311
82312 case DUK_OP_NOP: {
82313 /* Nop, ignored, but ABC fields may carry a value e.g.
82314 * for indirect opcode handling.
82315 */
82316 break;
82317 }
82318
82319 case DUK_OP_INVALID: {
82320 DUK_ERROR_FMT1(thr, DUK_ERR_ERROR, "INVALID opcode (%ld)", (long) DUK_DEC_ABC(ins));
82321 DUK_WO_NORETURN(return;);
82322 break;
82323 }
82324
82325#if defined(DUK_USE_ES6)
82326 case DUK_OP_NEWTARGET: {
82329 }
82330#endif /* DUK_USE_ES6 */
82331
82332#if !defined(DUK_USE_EXEC_PREFER_SIZE)
82333#if !defined(DUK_USE_ES7_EXP_OPERATOR)
82334 case DUK_OP_EXP_RR:
82335 case DUK_OP_EXP_CR:
82336 case DUK_OP_EXP_RC:
82337 case DUK_OP_EXP_CC:
82338#endif
82339#if !defined(DUK_USE_ES6)
82340 case DUK_OP_NEWTARGET:
82341#endif
82342#if !defined(DUK_USE_VERBOSE_ERRORS)
82343 case DUK_OP_GETPROPC_RR:
82344 case DUK_OP_GETPROPC_CR:
82345 case DUK_OP_GETPROPC_RC:
82346 case DUK_OP_GETPROPC_CC:
82347#endif
82348 case DUK_OP_UNUSED207:
82349 case DUK_OP_UNUSED212:
82350 case DUK_OP_UNUSED213:
82351 case DUK_OP_UNUSED214:
82352 case DUK_OP_UNUSED215:
82353 case DUK_OP_UNUSED216:
82354 case DUK_OP_UNUSED217:
82355 case DUK_OP_UNUSED218:
82356 case DUK_OP_UNUSED219:
82357 case DUK_OP_UNUSED220:
82358 case DUK_OP_UNUSED221:
82359 case DUK_OP_UNUSED222:
82360 case DUK_OP_UNUSED223:
82361 case DUK_OP_UNUSED224:
82362 case DUK_OP_UNUSED225:
82363 case DUK_OP_UNUSED226:
82364 case DUK_OP_UNUSED227:
82365 case DUK_OP_UNUSED228:
82366 case DUK_OP_UNUSED229:
82367 case DUK_OP_UNUSED230:
82368 case DUK_OP_UNUSED231:
82369 case DUK_OP_UNUSED232:
82370 case DUK_OP_UNUSED233:
82371 case DUK_OP_UNUSED234:
82372 case DUK_OP_UNUSED235:
82373 case DUK_OP_UNUSED236:
82374 case DUK_OP_UNUSED237:
82375 case DUK_OP_UNUSED238:
82376 case DUK_OP_UNUSED239:
82377 case DUK_OP_UNUSED240:
82378 case DUK_OP_UNUSED241:
82379 case DUK_OP_UNUSED242:
82380 case DUK_OP_UNUSED243:
82381 case DUK_OP_UNUSED244:
82382 case DUK_OP_UNUSED245:
82383 case DUK_OP_UNUSED246:
82384 case DUK_OP_UNUSED247:
82385 case DUK_OP_UNUSED248:
82386 case DUK_OP_UNUSED249:
82387 case DUK_OP_UNUSED250:
82388 case DUK_OP_UNUSED251:
82389 case DUK_OP_UNUSED252:
82390 case DUK_OP_UNUSED253:
82391 case DUK_OP_UNUSED254:
82392 case DUK_OP_UNUSED255:
82393 /* Force all case clauses to map to an actual handler
82394 * so that the compiler can emit a jump without a bounds
82395 * check: the switch argument is a duk_uint8_t so that
82396 * the compiler may be able to figure it out. This is
82397 * a small detail and obviously compiler dependent.
82398 */
82399 /* default: clause omitted on purpose */
82400#else /* DUK_USE_EXEC_PREFER_SIZE */
82401 default:
82402#endif /* DUK_USE_EXEC_PREFER_SIZE */
82403 {
82404 /* Default case catches invalid/unsupported opcodes. */
82405 DUK_D(DUK_DPRINT("invalid opcode: %ld - %!I", (long) op, ins));
82406 DUK__INTERNAL_ERROR("invalid opcode");
82407 break;
82408 }
82409
82410 } /* end switch */
82411
82412 continue;
82413
82414 /* Some shared exit paths for opcode handling below. These
82415 * are mostly useful to reduce code footprint when multiple
82416 * opcodes have a similar epilogue (like replacing stack top
82417 * with index 'a').
82418 */
82419
82420#if defined(DUK_USE_EXEC_PREFER_SIZE)
82421 replace_top_a:
82423 continue;
82424 replace_top_bc:
82426 continue;
82427#endif
82428 }
82429 DUK_WO_NORETURN(return;);
82430
82431#if !defined(DUK_USE_VERBOSE_EXECUTOR_ERRORS)
82432internal_error:
82433 DUK_ERROR_INTERNAL(thr);
82434 DUK_WO_NORETURN(return;);
82435#endif
82436}
82437
82438/* automatic undefs */
82439#undef DUK__BYTEOFF_A
82440#undef DUK__BYTEOFF_B
82441#undef DUK__BYTEOFF_BC
82442#undef DUK__BYTEOFF_C
82443#undef DUK__COMPARE_BODY
82444#undef DUK__CONST
82445#undef DUK__CONSTP
82446#undef DUK__CONSTP_A
82447#undef DUK__CONSTP_B
82448#undef DUK__CONSTP_BC
82449#undef DUK__CONSTP_C
82450#undef DUK__DELPROP_BODY
82451#undef DUK__EQ_BODY
82452#undef DUK__FUN
82453#undef DUK__GETPROPC_BODY
82454#undef DUK__GETPROP_BODY
82455#undef DUK__GE_BODY
82456#undef DUK__GT_BODY
82457#undef DUK__INSTOF_BODY
82458#undef DUK__INTERNAL_ERROR
82459#undef DUK__INT_NOACTION
82460#undef DUK__INT_RESTART
82461#undef DUK__IN_BODY
82462#undef DUK__LE_BODY
82463#undef DUK__LONGJMP_RESTART
82464#undef DUK__LONGJMP_RETHROW
82465#undef DUK__LOOKUP_INDIRECT
82466#undef DUK__LT_BODY
82467#undef DUK__MASK_A
82468#undef DUK__MASK_B
82469#undef DUK__MASK_BC
82470#undef DUK__MASK_C
82471#undef DUK__NEQ_BODY
82472#undef DUK__PUTPROP_BODY
82473#undef DUK__RCBIT_B
82474#undef DUK__RCBIT_C
82475#undef DUK__REG
82476#undef DUK__REGCONSTP_B
82477#undef DUK__REGCONSTP_C
82478#undef DUK__REGP
82479#undef DUK__REGP_A
82480#undef DUK__REGP_B
82481#undef DUK__REGP_BC
82482#undef DUK__REGP_C
82483#undef DUK__REPLACE_BOOL_A_BREAK
82484#undef DUK__REPLACE_TOP_A_BREAK
82485#undef DUK__REPLACE_TOP_BC_BREAK
82486#undef DUK__REPLACE_TO_TVPTR
82487#undef DUK__RETHAND_FINISHED
82488#undef DUK__RETHAND_RESTART
82489#undef DUK__RETURN_SHARED
82490#undef DUK__SEQ_BODY
82491#undef DUK__SHIFT_A
82492#undef DUK__SHIFT_B
82493#undef DUK__SHIFT_BC
82494#undef DUK__SHIFT_C
82495#undef DUK__SNEQ_BODY
82496#undef DUK__STRICT
82497#undef DUK__SYNC_AND_NULL_CURR_PC
82498#undef DUK__SYNC_CURR_PC
82499#undef DUK__TVAL_SHIFT
82500/*
82501 * ECMAScript specification algorithm and conversion helpers.
82502 *
82503 * These helpers encapsulate the primitive ECMAScript operation semantics,
82504 * and are used by the bytecode executor and the API (among other places).
82505 * Some primitives are only implemented as part of the API and have no
82506 * "internal" helper. This is the case when an internal helper would not
82507 * really be useful; e.g. the operation is rare, uses value stack heavily,
82508 * etc.
82509 *
82510 * The operation arguments depend on what is required to implement
82511 * the operation:
82512 *
82513 * - If an operation is simple and stateless, and has no side
82514 * effects, it won't take an duk_hthread argument and its
82515 * arguments may be duk_tval pointers (which are safe as long
82516 * as no side effects take place).
82517 *
82518 * - If complex coercions are required (e.g. a "ToNumber" coercion)
82519 * or errors may be thrown, the operation takes an duk_hthread
82520 * argument. This also implies that the operation may have
82521 * arbitrary side effects, invalidating any duk_tval pointers.
82522 *
82523 * - For operations with potential side effects, arguments can be
82524 * taken in several ways:
82525 *
82526 * a) as duk_tval pointers, which makes sense if the "common case"
82527 * can be resolved without side effects (e.g. coercion); the
82528 * arguments are pushed to the valstack for coercion if
82529 * necessary
82530 *
82531 * b) as duk_tval values
82532 *
82533 * c) implicitly on value stack top
82534 *
82535 * d) as indices to the value stack
82536 *
82537 * Future work:
82538 *
82539 * - Argument styles may not be the most sensible in every case now.
82540 *
82541 * - In-place coercions might be useful for several operations, if
82542 * in-place coercion is OK for the bytecode executor and the API.
82543 */
82544
82545/* #include duk_internal.h -> already included */
82546
82547/*
82548 * ToPrimitive() (E5 Section 9.1)
82549 *
82550 * ==> implemented in the API.
82551 */
82552
82553/*
82554 * ToBoolean() (E5 Section 9.2)
82555 */
82556
82558 switch (DUK_TVAL_GET_TAG(tv)) {
82559 case DUK_TAG_UNDEFINED:
82560 case DUK_TAG_NULL:
82561 return 0;
82562 case DUK_TAG_BOOLEAN:
82564 return DUK_TVAL_GET_BOOLEAN(tv);
82565 case DUK_TAG_STRING: {
82566 /* Symbols ToBoolean() coerce to true, regardless of their
82567 * description. This happens with no explicit check because
82568 * of the symbol representation byte prefix.
82569 */
82571 DUK_ASSERT(h != NULL);
82572 return (DUK_HSTRING_GET_BYTELEN(h) > 0 ? 1 : 0);
82573 }
82574 case DUK_TAG_OBJECT: {
82575 return 1;
82576 }
82577 case DUK_TAG_BUFFER: {
82578 /* Mimic Uint8Array semantics: objects coerce true, regardless
82579 * of buffer length (zero or not) or context.
82580 */
82581 return 1;
82582 }
82583 case DUK_TAG_POINTER: {
82584 void *p = DUK_TVAL_GET_POINTER(tv);
82585 return (p != NULL ? 1 : 0);
82586 }
82587 case DUK_TAG_LIGHTFUNC: {
82588 return 1;
82589 }
82590#if defined(DUK_USE_FASTINT)
82591 case DUK_TAG_FASTINT:
82592 if (DUK_TVAL_GET_FASTINT(tv) != 0) {
82593 return 1;
82594 } else {
82595 return 0;
82596 }
82597#endif
82598 default: {
82599 /* number */
82600 duk_double_t d;
82601#if defined(DUK_USE_PREFER_SIZE)
82602 int c;
82603#endif
82606 d = DUK_TVAL_GET_DOUBLE(tv);
82607#if defined(DUK_USE_PREFER_SIZE)
82608 c = DUK_FPCLASSIFY((double) d);
82609 if (c == DUK_FP_ZERO || c == DUK_FP_NAN) {
82610 return 0;
82611 } else {
82612 return 1;
82613 }
82614#else
82616 return duk_double_is_nan_or_zero(d) ^ 1;
82617#endif
82618 }
82619 }
82621 DUK_WO_UNREACHABLE(return 0;);
82622}
82623
82624/*
82625 * ToNumber() (E5 Section 9.3)
82626 *
82627 * Value to convert must be on stack top, and is popped before exit.
82628 *
82629 * See: http://www.cs.indiana.edu/~burger/FP-Printing-PLDI96.pdf
82630 * http://www.cs.indiana.edu/~burger/fp/index.html
82631 *
82632 * Notes on the conversion:
82633 *
82634 * - There are specific requirements on the accuracy of the conversion
82635 * through a "Mathematical Value" (MV), so this conversion is not
82636 * trivial.
82637 *
82638 * - Quick rejects (e.g. based on first char) are difficult because
82639 * the grammar allows leading and trailing white space.
82640 *
82641 * - Quick reject based on string length is difficult even after
82642 * accounting for white space; there may be arbitrarily many
82643 * decimal digits.
82644 *
82645 * - Standard grammar allows decimal values ("123"), hex values
82646 * ("0x123") and infinities
82647 *
82648 * - Unlike source code literals, ToNumber() coerces empty strings
82649 * and strings with only whitespace to zero (not NaN). However,
82650 * while '' coerces to 0, '+' and '-' coerce to NaN.
82651 */
82652
82653/* E5 Section 9.3.1 */
82655 duk_small_uint_t s2n_flags;
82656 duk_double_t d;
82657
82658 DUK_ASSERT(duk_is_string(thr, -1));
82659
82660 /* Quite lenient, e.g. allow empty as zero, but don't allow trailing
82661 * garbage.
82662 */
82667
82668 duk_numconv_parse(thr, 10 /*radix*/, s2n_flags);
82669
82670#if defined(DUK_USE_PREFER_SIZE)
82671 d = duk_get_number(thr, -1);
82672 duk_pop_unsafe(thr);
82673#else
82674 thr->valstack_top--;
82676 DUK_ASSERT(DUK_TVAL_IS_DOUBLE(thr->valstack_top)); /* no fastint conversion in numconv now */
82678 d = DUK_TVAL_GET_DOUBLE(thr->valstack_top); /* assumes not a fastint */
82680#endif
82681
82682 return d;
82683}
82684
82686 DUK_ASSERT(thr != NULL);
82687 DUK_ASSERT(tv != NULL);
82688
82689 switch (DUK_TVAL_GET_TAG(tv)) {
82690 case DUK_TAG_UNDEFINED: {
82691 /* return a specific NaN (although not strictly necessary) */
82695 return du.d;
82696 }
82697 case DUK_TAG_NULL: {
82698 /* +0.0 */
82699 return 0.0;
82700 }
82701 case DUK_TAG_BOOLEAN: {
82702 if (DUK_TVAL_IS_BOOLEAN_TRUE(tv)) {
82703 return 1.0;
82704 }
82705 return 0.0;
82706 }
82707 case DUK_TAG_STRING: {
82708 /* For Symbols ToNumber() is always a TypeError. */
82712 DUK_WO_NORETURN(return 0.0;);
82713 }
82714 duk_push_hstring(thr, h);
82715 return duk__tonumber_string_raw(thr);
82716 }
82717 case DUK_TAG_BUFFER: /* plain buffer treated like object */
82718 case DUK_TAG_OBJECT: {
82719 duk_double_t d;
82720 duk_push_tval(thr, tv);
82721 duk_to_primitive(thr, -1, DUK_HINT_NUMBER); /* 'tv' becomes invalid */
82722
82723 /* recursive call for a primitive value (guaranteed not to cause second
82724 * recursion).
82725 */
82726 DUK_ASSERT(duk_get_tval(thr, -1) != NULL);
82727 d = duk_js_tonumber(thr, duk_get_tval(thr, -1));
82728
82729 duk_pop_unsafe(thr);
82730 return d;
82731 }
82732 case DUK_TAG_POINTER: {
82733 /* Coerce like boolean */
82734 void *p = DUK_TVAL_GET_POINTER(tv);
82735 return (p != NULL ? 1.0 : 0.0);
82736 }
82737 case DUK_TAG_LIGHTFUNC: {
82738 /* +(function(){}) -> NaN */
82739 return DUK_DOUBLE_NAN;
82740 }
82741#if defined(DUK_USE_FASTINT)
82742 case DUK_TAG_FASTINT:
82744#endif
82745 default: {
82746 /* number */
82749 return DUK_TVAL_GET_DOUBLE(tv);
82750 }
82751 }
82752
82754 DUK_WO_UNREACHABLE(return 0.0;);
82755}
82756
82757/*
82758 * ToInteger() (E5 Section 9.4)
82759 */
82760
82761/* exposed, used by e.g. duk_bi_date.c */
82763#if defined(DUK_USE_PREFER_SIZE)
82765
82766 if (DUK_UNLIKELY(c == DUK_FP_NAN)) {
82767 return 0.0;
82768 } else if (DUK_UNLIKELY(c == DUK_FP_INFINITE)) {
82769 return x;
82770 } else {
82771 /* Finite, including neg/pos zero. Neg zero sign must be
82772 * preserved.
82773 */
82775 }
82776#else /* DUK_USE_PREFER_SIZE */
82777 /* NaN and Infinity have the same exponent so it's a cheap
82778 * initial check for the rare path.
82779 */
82780 if (DUK_UNLIKELY(duk_double_is_nan_or_inf(x) != 0U)) {
82781 if (duk_double_is_nan(x)) {
82782 return 0.0;
82783 } else {
82784 return x;
82785 }
82786 } else {
82788 }
82789#endif /* DUK_USE_PREFER_SIZE */
82790}
82791
82793 /* XXX: fastint */
82794 duk_double_t d = duk_js_tonumber(thr, tv); /* invalidates tv */
82795 return duk_js_tointeger_number(d);
82796}
82797
82798/*
82799 * ToInt32(), ToUint32(), ToUint16() (E5 Sections 9.5, 9.6, 9.7)
82800 */
82801
82802/* combined algorithm matching E5 Sections 9.5 and 9.6 */
82804#if defined(DUK_USE_PREFER_SIZE)
82806#endif
82807
82808#if defined(DUK_USE_PREFER_SIZE)
82810 if (c == DUK_FP_NAN || c == DUK_FP_ZERO || c == DUK_FP_INFINITE) {
82811 return 0.0;
82812 }
82813#else
82815 return 0.0;
82816 }
82817#endif
82818
82819 /* x = sign(x) * floor(abs(x)), i.e. truncate towards zero, keep sign */
82821
82822 /* NOTE: fmod(x) result sign is same as sign of x, which
82823 * differs from what Javascript wants (see Section 9.6).
82824 */
82825
82826 x = DUK_FMOD(x, DUK_DOUBLE_2TO32); /* -> x in ]-2**32, 2**32[ */
82827
82828 if (x < 0.0) {
82829 x += DUK_DOUBLE_2TO32;
82830 }
82831 DUK_ASSERT(x >= 0 && x < DUK_DOUBLE_2TO32); /* -> x in [0, 2**32[ */
82832
82833 if (is_toint32) {
82834 if (x >= DUK_DOUBLE_2TO31) {
82835 /* x in [2**31, 2**32[ */
82836
82837 x -= DUK_DOUBLE_2TO32; /* -> x in [-2**31,2**31[ */
82838 }
82840
82841 return x;
82842}
82843
82844DUK_INTERNAL duk_int32_t duk_js_toint32(duk_hthread *thr, duk_tval *tv) {
82845 duk_double_t d;
82846
82847#if defined(DUK_USE_FASTINT)
82848 if (DUK_TVAL_IS_FASTINT(tv)) {
82849 return DUK_TVAL_GET_FASTINT_I32(tv);
82850 }
82851#endif
82852
82853 d = duk_js_tonumber(thr, tv); /* invalidates tv */
82856 DUK_ASSERT(d >= -2147483648.0 && d <= 2147483647.0); /* [-0x80000000,0x7fffffff] */
82857 DUK_ASSERT(duk_double_equals(d, (duk_double_t) ((duk_int32_t) d))); /* whole, won't clip */
82858 return (duk_int32_t) d;
82859}
82860
82861DUK_INTERNAL duk_uint32_t duk_js_touint32(duk_hthread *thr, duk_tval *tv) {
82862 duk_double_t d;
82863
82864#if defined(DUK_USE_FASTINT)
82865 if (DUK_TVAL_IS_FASTINT(tv)) {
82866 return DUK_TVAL_GET_FASTINT_U32(tv);
82867 }
82868#endif
82869
82870 d = duk_js_tonumber(thr, tv); /* invalidates tv */
82873 DUK_ASSERT(d >= 0.0 && d <= 4294967295.0); /* [0x00000000, 0xffffffff] */
82874 DUK_ASSERT(duk_double_equals(d, (duk_double_t) ((duk_uint32_t) d))); /* whole, won't clip */
82875 return (duk_uint32_t) d;
82876}
82877
82878DUK_INTERNAL duk_uint16_t duk_js_touint16(duk_hthread *thr, duk_tval *tv) {
82879 /* should be a safe way to compute this */
82880 return (duk_uint16_t) (duk_js_touint32(thr, tv) & 0x0000ffffU);
82881}
82882
82883/*
82884 * ToString() (E5 Section 9.8)
82885 * ToObject() (E5 Section 9.9)
82886 * CheckObjectCoercible() (E5 Section 9.10)
82887 * IsCallable() (E5 Section 9.11)
82888 *
82889 * ==> implemented in the API.
82890 */
82891
82892/*
82893 * Loose equality, strict equality, and SameValue (E5 Sections 11.9.1, 11.9.4,
82894 * 9.12). These have much in common so they can share some helpers.
82895 *
82896 * Future work notes:
82897 *
82898 * - Current implementation (and spec definition) has recursion; this should
82899 * be fixed if possible.
82900 *
82901 * - String-to-number coercion should be possible without going through the
82902 * value stack (and be more compact) if a shared helper is invoked.
82903 */
82904
82905/* Note that this is the same operation for strict and loose equality:
82906 * - E5 Section 11.9.3, step 1.c (loose)
82907 * - E5 Section 11.9.6, step 4 (strict)
82908 */
82911#if defined(DUK_USE_PARANOID_MATH)
82912 /* Straightforward algorithm, makes fewer compiler assumptions. */
82915 if (cx == DUK_FP_NAN || cy == DUK_FP_NAN) {
82916 return 0;
82917 }
82918 if (cx == DUK_FP_ZERO && cy == DUK_FP_ZERO) {
82919 return 1;
82920 }
82921 if (x == y) {
82922 return 1;
82923 }
82924 return 0;
82925#else /* DUK_USE_PARANOID_MATH */
82926 /* Better equivalent algorithm. If the compiler is compliant, C and
82927 * ECMAScript semantics are identical for this particular comparison.
82928 * In particular, NaNs must never compare equal and zeroes must compare
82929 * equal regardless of sign. Could also use a macro, but this inlines
82930 * already nicely (no difference on gcc, for instance).
82931 */
82932 if (duk_double_equals(x, y)) {
82933 /* IEEE requires that NaNs compare false */
82936 return 1;
82937 } else {
82938 /* IEEE requires that zeros compare the same regardless
82939 * of their signed, so if both x and y are zeroes, they
82940 * are caught above.
82941 */
82943 return 0;
82944 }
82945#endif /* DUK_USE_PARANOID_MATH */
82946}
82947
82949#if defined(DUK_USE_PARANOID_MATH)
82952
82953 if (cx == DUK_FP_NAN && cy == DUK_FP_NAN) {
82954 /* SameValue(NaN, NaN) = true, regardless of NaN sign or extra bits */
82955 return 1;
82956 }
82957 if (cx == DUK_FP_ZERO && cy == DUK_FP_ZERO) {
82958 /* Note: cannot assume that a non-zero return value of signbit() would
82959 * always be the same -- hence cannot (portably) use something like:
82960 *
82961 * signbit(x) == signbit(y)
82962 */
82963 duk_small_int_t sx = DUK_SIGNBIT(x) ? 1 : 0;
82964 duk_small_int_t sy = DUK_SIGNBIT(y) ? 1 : 0;
82965 return (sx == sy);
82966 }
82967
82968 /* normal comparison; known:
82969 * - both x and y are not NaNs (but one of them can be)
82970 * - both x and y are not zero (but one of them can be)
82971 * - x and y may be denormal or infinite
82972 */
82973
82974 return (x == y);
82975#else /* DUK_USE_PARANOID_MATH */
82978
82979 if (duk_double_equals(x, y)) {
82980 /* IEEE requires that NaNs compare false */
82983
82984 /* Using classification has smaller footprint than direct comparison. */
82985 if (DUK_UNLIKELY(cx == DUK_FP_ZERO && cy == DUK_FP_ZERO)) {
82986 /* Note: cannot assume that a non-zero return value of signbit() would
82987 * always be the same -- hence cannot (portably) use something like:
82988 *
82989 * signbit(x) == signbit(y)
82990 */
82991 return duk_double_same_sign(x, y);
82992 }
82993 return 1;
82994 } else {
82995 /* IEEE requires that zeros compare the same regardless
82996 * of their sign, so if both x and y are zeroes, they
82997 * are caught above.
82998 */
83000
83001 /* Difference to non-strict/strict comparison is that NaNs compare
83002 * equal and signed zero signs matter.
83003 */
83004 if (DUK_UNLIKELY(cx == DUK_FP_NAN && cy == DUK_FP_NAN)) {
83005 /* SameValue(NaN, NaN) = true, regardless of NaN sign or extra bits */
83006 return 1;
83007 }
83008 return 0;
83009 }
83010#endif /* DUK_USE_PARANOID_MATH */
83011}
83012
83014 duk_uint_t type_mask_x;
83015 duk_uint_t type_mask_y;
83016
83017 /* If flags != 0 (strict or SameValue), thr can be NULL. For loose
83018 * equals comparison it must be != NULL.
83019 */
83020 DUK_ASSERT(flags != 0 || thr != NULL);
83021
83022 /*
83023 * Same type?
83024 *
83025 * Note: since number values have no explicit tag in the 8-byte
83026 * representation, need the awkward if + switch.
83027 */
83028
83029#if defined(DUK_USE_FASTINT)
83030 if (DUK_TVAL_IS_FASTINT(tv_x) && DUK_TVAL_IS_FASTINT(tv_y)) {
83031 if (DUK_TVAL_GET_FASTINT(tv_x) == DUK_TVAL_GET_FASTINT(tv_y)) {
83032 return 1;
83033 } else {
83034 return 0;
83035 }
83036 } else
83037#endif
83038 if (DUK_TVAL_IS_NUMBER(tv_x) && DUK_TVAL_IS_NUMBER(tv_y)) {
83039 duk_double_t d1, d2;
83040
83041 /* Catches both doubles and cases where only one argument is
83042 * a fastint so can't assume a double.
83043 */
83044 d1 = DUK_TVAL_GET_NUMBER(tv_x);
83045 d2 = DUK_TVAL_GET_NUMBER(tv_y);
83046 if (DUK_UNLIKELY((flags & DUK_EQUALS_FLAG_SAMEVALUE) != 0)) {
83047 /* SameValue */
83048 return duk__js_samevalue_number(d1, d2);
83049 } else {
83050 /* equals and strict equals */
83051 return duk__js_equals_number(d1, d2);
83052 }
83053 } else if (DUK_TVAL_GET_TAG(tv_x) == DUK_TVAL_GET_TAG(tv_y)) {
83054 switch (DUK_TVAL_GET_TAG(tv_x)) {
83055 case DUK_TAG_UNDEFINED:
83056 case DUK_TAG_NULL: {
83057 return 1;
83058 }
83059 case DUK_TAG_BOOLEAN: {
83060 return DUK_TVAL_GET_BOOLEAN(tv_x) == DUK_TVAL_GET_BOOLEAN(tv_y);
83061 }
83062 case DUK_TAG_POINTER: {
83063 return DUK_TVAL_GET_POINTER(tv_x) == DUK_TVAL_GET_POINTER(tv_y);
83064 }
83065 case DUK_TAG_STRING:
83066 case DUK_TAG_OBJECT: {
83067 /* Heap pointer comparison suffices for strings and objects.
83068 * Symbols compare equal if they have the same internal
83069 * representation; again heap pointer comparison suffices.
83070 */
83071 return DUK_TVAL_GET_HEAPHDR(tv_x) == DUK_TVAL_GET_HEAPHDR(tv_y);
83072 }
83073 case DUK_TAG_BUFFER: {
83074 /* In Duktape 2.x plain buffers mimic Uint8Array objects
83075 * so always compare by heap pointer. In Duktape 1.x
83076 * strict comparison would compare heap pointers and
83077 * non-strict would compare contents.
83078 */
83079 return DUK_TVAL_GET_HEAPHDR(tv_x) == DUK_TVAL_GET_HEAPHDR(tv_y);
83080 }
83081 case DUK_TAG_LIGHTFUNC: {
83082 /* At least 'magic' has a significant impact on function
83083 * identity.
83084 */
83085 duk_small_uint_t lf_flags_x;
83086 duk_small_uint_t lf_flags_y;
83087 duk_c_function func_x;
83088 duk_c_function func_y;
83089
83090 DUK_TVAL_GET_LIGHTFUNC(tv_x, func_x, lf_flags_x);
83091 DUK_TVAL_GET_LIGHTFUNC(tv_y, func_y, lf_flags_y);
83092 return ((func_x == func_y) && (lf_flags_x == lf_flags_y)) ? 1 : 0;
83093 }
83094#if defined(DUK_USE_FASTINT)
83095 case DUK_TAG_FASTINT:
83096#endif
83097 default: {
83103 DUK_WO_UNREACHABLE(return 0;);
83104 }
83105 }
83106 }
83107
83108 if ((flags & (DUK_EQUALS_FLAG_STRICT | DUK_EQUALS_FLAG_SAMEVALUE)) != 0) {
83109 return 0;
83110 }
83111
83112 DUK_ASSERT(flags == 0); /* non-strict equality from here on */
83113
83114 /*
83115 * Types are different; various cases for non-strict comparison
83116 *
83117 * Since comparison is symmetric, we use a "swap trick" to reduce
83118 * code size.
83119 */
83120
83121 type_mask_x = duk_get_type_mask_tval(tv_x);
83122 type_mask_y = duk_get_type_mask_tval(tv_y);
83123
83124 /* Undefined/null are considered equal (e.g. "null == undefined" -> true). */
83125 if ((type_mask_x & (DUK_TYPE_MASK_UNDEFINED | DUK_TYPE_MASK_NULL)) &&
83126 (type_mask_y & (DUK_TYPE_MASK_NULL | DUK_TYPE_MASK_UNDEFINED))) {
83127 return 1;
83128 }
83129
83130 /* Number/string -> coerce string to number (e.g. "'1.5' == 1.5" -> true). */
83131 if ((type_mask_x & DUK_TYPE_MASK_NUMBER) && (type_mask_y & DUK_TYPE_MASK_STRING)) {
83132 if (!DUK_TVAL_STRING_IS_SYMBOL(tv_y)) {
83133 duk_double_t d1, d2;
83134 d1 = DUK_TVAL_GET_NUMBER(tv_x);
83135 d2 = duk_to_number_tval(thr, tv_y);
83136 return duk__js_equals_number(d1, d2);
83137 }
83138 }
83139 if ((type_mask_x & DUK_TYPE_MASK_STRING) && (type_mask_y & DUK_TYPE_MASK_NUMBER)) {
83140 if (!DUK_TVAL_STRING_IS_SYMBOL(tv_x)) {
83141 duk_double_t d1, d2;
83142 d1 = DUK_TVAL_GET_NUMBER(tv_y);
83143 d2 = duk_to_number_tval(thr, tv_x);
83144 return duk__js_equals_number(d1, d2);
83145 }
83146 }
83147
83148 /* Boolean/any -> coerce boolean to number and try again. If boolean is
83149 * compared to a pointer, the final comparison after coercion now always
83150 * yields false (as pointer vs. number compares to false), but this is
83151 * not special cased.
83152 *
83153 * ToNumber(bool) is +1.0 or 0.0. Tagged boolean value is always 0 or 1.
83154 */
83155 if (type_mask_x & DUK_TYPE_MASK_BOOLEAN) {
83156 DUK_ASSERT(DUK_TVAL_GET_BOOLEAN(tv_x) == 0 || DUK_TVAL_GET_BOOLEAN(tv_x) == 1);
83158 duk_push_tval(thr, tv_y);
83159 goto recursive_call;
83160 }
83161 if (type_mask_y & DUK_TYPE_MASK_BOOLEAN) {
83162 DUK_ASSERT(DUK_TVAL_GET_BOOLEAN(tv_y) == 0 || DUK_TVAL_GET_BOOLEAN(tv_y) == 1);
83163 duk_push_tval(thr, tv_x);
83165 goto recursive_call;
83166 }
83167
83168 /* String-number-symbol/object -> coerce object to primitive (apparently without hint), then try again. */
83169 if ((type_mask_x & (DUK_TYPE_MASK_STRING | DUK_TYPE_MASK_NUMBER)) && (type_mask_y & DUK_TYPE_MASK_OBJECT)) {
83170 /* No symbol check needed because symbols and strings are accepted. */
83171 duk_push_tval(thr, tv_x);
83172 duk_push_tval(thr, tv_y);
83173 duk_to_primitive(thr, -1, DUK_HINT_NONE); /* apparently no hint? */
83174 goto recursive_call;
83175 }
83176 if ((type_mask_x & DUK_TYPE_MASK_OBJECT) && (type_mask_y & (DUK_TYPE_MASK_STRING | DUK_TYPE_MASK_NUMBER))) {
83177 /* No symbol check needed because symbols and strings are accepted. */
83178 duk_push_tval(thr, tv_x);
83179 duk_push_tval(thr, tv_y);
83180 duk_to_primitive(thr, -2, DUK_HINT_NONE); /* apparently no hint? */
83181 goto recursive_call;
83182 }
83183
83184 /* Nothing worked -> not equal. */
83185 return 0;
83186
83187recursive_call:
83188 /* Shared code path to call the helper again with arguments on stack top. */
83189 {
83190 duk_bool_t rc;
83191 rc = duk_js_equals_helper(thr, DUK_GET_TVAL_NEGIDX(thr, -2), DUK_GET_TVAL_NEGIDX(thr, -1), 0 /*flags:nonstrict*/);
83192 duk_pop_2_unsafe(thr);
83193 return rc;
83194 }
83195}
83196
83197/*
83198 * Comparisons (x >= y, x > y, x <= y, x < y)
83199 *
83200 * E5 Section 11.8.5: implement 'x < y' and then use negate and eval_left_first
83201 * flags to get the rest.
83202 */
83203
83204/* XXX: this should probably just operate on the stack top, because it
83205 * needs to push stuff on the stack anyway...
83206 */
83207
83208DUK_INTERNAL duk_small_int_t duk_js_data_compare(const duk_uint8_t *buf1,
83209 const duk_uint8_t *buf2,
83210 duk_size_t len1,
83211 duk_size_t len2) {
83212 duk_size_t prefix_len;
83213 duk_small_int_t rc;
83214
83215 prefix_len = (len1 <= len2 ? len1 : len2);
83216
83217 /* duk_memcmp() is guaranteed to return zero (equal) for zero length
83218 * inputs.
83219 */
83220 rc = duk_memcmp_unsafe((const void *) buf1, (const void *) buf2, (size_t) prefix_len);
83221
83222 if (rc < 0) {
83223 return -1;
83224 } else if (rc > 0) {
83225 return 1;
83226 }
83227
83228 /* prefix matches, lengths matter now */
83229 if (len1 < len2) {
83230 /* e.g. "x" < "xx" */
83231 return -1;
83232 } else if (len1 > len2) {
83233 return 1;
83234 }
83235
83236 return 0;
83237}
83238
83240 /*
83241 * String comparison (E5 Section 11.8.5, step 4), which
83242 * needs to compare codepoint by codepoint.
83243 *
83244 * However, UTF-8 allows us to use strcmp directly: the shared
83245 * prefix will be encoded identically (UTF-8 has unique encoding)
83246 * and the first differing character can be compared with a simple
83247 * unsigned byte comparison (which strcmp does).
83248 *
83249 * This will not work properly for non-xutf-8 strings, but this
83250 * is not an issue for compliance.
83251 */
83252
83253 DUK_ASSERT(h1 != NULL);
83254 DUK_ASSERT(h2 != NULL);
83255
83256 return duk_js_data_compare((const duk_uint8_t *) DUK_HSTRING_GET_DATA(h1),
83257 (const duk_uint8_t *) DUK_HSTRING_GET_DATA(h2),
83260}
83261
83262#if 0 /* unused */
83263DUK_INTERNAL duk_small_int_t duk_js_buffer_compare(duk_heap *heap, duk_hbuffer *h1, duk_hbuffer *h2) {
83264 /* Similar to String comparison. */
83265
83266 DUK_ASSERT(h1 != NULL);
83267 DUK_ASSERT(h2 != NULL);
83268 DUK_UNREF(heap);
83269
83270 return duk_js_data_compare((const duk_uint8_t *) DUK_HBUFFER_GET_DATA_PTR(heap, h1),
83271 (const duk_uint8_t *) DUK_HBUFFER_GET_DATA_PTR(heap, h2),
83274}
83275#endif
83276
83277#if defined(DUK_USE_FASTINT)
83278DUK_LOCAL duk_bool_t duk__compare_fastint(duk_bool_t retval, duk_int64_t v1, duk_int64_t v2) {
83279 DUK_ASSERT(retval == 0 || retval == 1);
83280 if (v1 < v2) {
83281 return retval ^ 1;
83282 } else {
83283 return retval;
83284 }
83285}
83286#endif
83287
83288#if defined(DUK_USE_PARANOID_MATH)
83290 duk_small_int_t c1, s1, c2, s2;
83291
83292 DUK_ASSERT(retval == 0 || retval == 1);
83294 s1 = (duk_small_int_t) DUK_SIGNBIT(d1);
83296 s2 = (duk_small_int_t) DUK_SIGNBIT(d2);
83297
83298 if (c1 == DUK_FP_NAN || c2 == DUK_FP_NAN) {
83299 return 0; /* Always false, regardless of negation. */
83300 }
83302 if (c1 == DUK_FP_ZERO && c2 == DUK_FP_ZERO) {
83303 /* For all combinations: +0 < +0, +0 < -0, -0 < +0, -0 < -0,
83304 * steps e, f, and g.
83305 */
83306 return retval; /* false */
83307 }
83308
83309 if (d1 == d2) {
83310 return retval; /* false */
83311 }
83312
83313 if (c1 == DUK_FP_INFINITE && s1 == 0) {
83314 /* x == +Infinity */
83315 return retval; /* false */
83316 }
83317
83318 if (c2 == DUK_FP_INFINITE && s2 == 0) {
83319 /* y == +Infinity */
83320 return retval ^ 1; /* true */
83321 }
83322
83323 if (c2 == DUK_FP_INFINITE && s2 != 0) {
83324 /* y == -Infinity */
83325 return retval; /* false */
83326 }
83327
83328 if (c1 == DUK_FP_INFINITE && s1 != 0) {
83329 /* x == -Infinity */
83330 return retval ^ 1; /* true */
83331 }
83332
83333 if (d1 < d2) {
83334 return retval ^ 1; /* true */
83335 }
83336
83337 return retval; /* false */
83338}
83339#else /* DUK_USE_PARANOID_MATH */
83341 /* This comparison tree relies doesn't match the exact steps in
83342 * E5 Section 11.8.5 but should produce the same results. The
83343 * steps rely on exact IEEE semantics for NaNs, etc.
83344 */
83345
83346 DUK_ASSERT(retval == 0 || retval == 1);
83347 if (d1 < d2) {
83348 /* In no case should both (d1 < d2) and (d2 < d1) be true.
83349 * It's possible that neither is true though, and that's
83350 * handled below.
83351 */
83352 DUK_ASSERT(!(d2 < d1));
83353
83354 /* - d1 < d2, both d1/d2 are normals (not Infinity, not NaN)
83355 * - d2 is +Infinity, d1 != +Infinity and NaN
83356 * - d1 is -Infinity, d2 != -Infinity and NaN
83357 */
83358 return retval ^ 1;
83359 } else {
83360 if (d2 < d1) {
83361 /* - !(d1 < d2), both d1/d2 are normals (not Infinity, not NaN)
83362 * - d1 is +Infinity, d2 != +Infinity and NaN
83363 * - d2 is -Infinity, d1 != -Infinity and NaN
83364 */
83365 return retval;
83366 } else {
83367 /* - d1 and/or d2 is NaN
83368 * - d1 and d2 are both +/- 0
83369 * - d1 == d2 (including infinities)
83370 */
83371 if (duk_double_is_nan(d1) || duk_double_is_nan(d2)) {
83372 /* Note: undefined from Section 11.8.5 always
83373 * results in false return (see e.g. Section
83374 * 11.8.3) - hence special treatment here.
83375 */
83376 return 0; /* zero regardless of negation */
83377 } else {
83378 return retval;
83379 }
83380 }
83381 }
83382}
83383#endif /* DUK_USE_PARANOID_MATH */
83384
83386 duk_double_t d1, d2;
83387 duk_small_int_t rc;
83388 duk_bool_t retval;
83389
83390 DUK_ASSERT(DUK_COMPARE_FLAG_NEGATE == 1); /* Rely on this flag being lowest. */
83391 retval = flags & DUK_COMPARE_FLAG_NEGATE;
83392 DUK_ASSERT(retval == 0 || retval == 1);
83393
83394 /* Fast path for fastints */
83395#if defined(DUK_USE_FASTINT)
83398 }
83399#endif /* DUK_USE_FASTINT */
83400
83401 /* Fast path for numbers (one of which may be a fastint) */
83402#if !defined(DUK_USE_PREFER_SIZE)
83403 if (DUK_LIKELY(DUK_TVAL_IS_NUMBER(tv_x) && DUK_TVAL_IS_NUMBER(tv_y))) {
83404 return duk__compare_number(retval, DUK_TVAL_GET_NUMBER(tv_x), DUK_TVAL_GET_NUMBER(tv_y));
83405 }
83406#endif
83407
83408 /* Slow path */
83409
83410 duk_push_tval(thr, tv_x);
83411 duk_push_tval(thr, tv_y);
83412
83416 } else {
83419 }
83420
83421 /* Note: reuse variables */
83422 tv_x = DUK_GET_TVAL_NEGIDX(thr, -2);
83423 tv_y = DUK_GET_TVAL_NEGIDX(thr, -1);
83424
83425 if (DUK_TVAL_IS_STRING(tv_x) && DUK_TVAL_IS_STRING(tv_y)) {
83426 duk_hstring *h1 = DUK_TVAL_GET_STRING(tv_x);
83427 duk_hstring *h2 = DUK_TVAL_GET_STRING(tv_y);
83428 DUK_ASSERT(h1 != NULL);
83429 DUK_ASSERT(h2 != NULL);
83430
83432 rc = duk_js_string_compare(h1, h2);
83433 duk_pop_2_unsafe(thr);
83434 if (rc < 0) {
83435 return retval ^ 1;
83436 } else {
83437 return retval;
83438 }
83439 }
83440
83441 /* One or both are Symbols: fall through to handle in the
83442 * generic path. Concretely, ToNumber() will fail.
83443 */
83444 }
83445
83446 /* Ordering should not matter (E5 Section 11.8.5, step 3.a). */
83447#if 0
83449 d1 = duk_to_number_m2(thr);
83450 d2 = duk_to_number_m1(thr);
83451 } else {
83452 d2 = duk_to_number_m1(thr);
83453 d1 = duk_to_number_m2(thr);
83454 }
83455#endif
83457 d2 = duk_to_number_m1(thr);
83458
83459 /* We want to duk_pop_2_unsafe(thr); because the values are numbers
83460 * no decref check is needed.
83461 */
83462#if defined(DUK_USE_PREFER_SIZE)
83464#else
83467 DUK_ASSERT(duk_get_top(thr) >= 2);
83468 thr->valstack_top -= 2;
83469 tv_x = thr->valstack_top;
83470 tv_y = tv_x + 1;
83471 DUK_TVAL_SET_UNDEFINED(tv_x); /* Value stack policy */
83473#endif
83474
83475 return duk__compare_number(retval, d1, d2);
83476}
83477
83478/*
83479 * instanceof
83480 */
83481
83482/*
83483 * ES2015 Section 7.3.19 describes the OrdinaryHasInstance() algorithm
83484 * which covers both bound and non-bound functions; in effect the algorithm
83485 * includes E5 Sections 11.8.6, 15.3.5.3, and 15.3.4.5.3.
83486 *
83487 * ES2015 Section 12.9.4 describes the instanceof operator which first
83488 * checks @@hasInstance well-known symbol and falls back to
83489 * OrdinaryHasInstance().
83490 *
83491 * Limited Proxy support: don't support 'getPrototypeOf' trap but
83492 * continue lookup in Proxy target if the value is a Proxy.
83493 */
83494
83496 duk_hobject *func;
83497 duk_hobject *val;
83498 duk_hobject *proto;
83499 duk_tval *tv;
83500 duk_bool_t skip_first;
83501 duk_uint_t sanity;
83502
83503 /*
83504 * Get the values onto the stack first. It would be possible to cover
83505 * some normal cases without resorting to the value stack.
83506 *
83507 * The right hand side could be a light function (as they generally
83508 * behave like objects). Light functions never have a 'prototype'
83509 * property so E5.1 Section 15.3.5.3 step 3 always throws a TypeError.
83510 * Using duk_require_hobject() is thus correct (except for error msg).
83511 */
83512
83513 duk_push_tval(thr, tv_x);
83514 duk_push_tval(thr, tv_y);
83515 func = duk_require_hobject(thr, -1);
83516 DUK_ASSERT(func != NULL);
83517
83518#if defined(DUK_USE_SYMBOL_BUILTIN)
83519 /*
83520 * @@hasInstance check, ES2015 Section 12.9.4, Steps 2-4.
83521 */
83522 if (!skip_sym_check) {
83524 /* [ ... lhs rhs func ] */
83525 duk_insert(thr, -3); /* -> [ ... func lhs rhs ] */
83526 duk_swap_top(thr, -2); /* -> [ ... func rhs(this) lhs ] */
83527 duk_call_method(thr, 1);
83528 return duk_to_boolean_top_pop(thr);
83529 }
83530 }
83531#else
83532 DUK_UNREF(skip_sym_check);
83533#endif
83534
83535 /*
83536 * For bound objects, [[HasInstance]] just calls the target function
83537 * [[HasInstance]]. If that is again a bound object, repeat until
83538 * we find a non-bound Function object.
83539 *
83540 * The bound function chain is now "collapsed" so there can be only
83541 * one bound function in the chain.
83542 */
83543
83544 if (!DUK_HOBJECT_IS_CALLABLE(func)) {
83545 /*
83546 * Note: of native ECMAScript objects, only Function instances
83547 * have a [[HasInstance]] internal property. Custom objects might
83548 * also have it, but not in current implementation.
83549 *
83550 * XXX: add a separate flag, DUK_HOBJECT_FLAG_ALLOW_INSTANCEOF?
83551 */
83552 goto error_invalid_rval;
83553 }
83554
83555 if (DUK_HOBJECT_HAS_BOUNDFUNC(func)) {
83556 duk_push_tval(thr, &((duk_hboundfunc *) (void *) func)->target);
83557 duk_replace(thr, -2);
83558 func = duk_require_hobject(thr, -1); /* lightfunc throws */
83559
83560 /* Rely on Function.prototype.bind() never creating bound
83561 * functions whose target is not proper.
83562 */
83563 DUK_ASSERT(func != NULL);
83565 }
83566
83567 /*
83568 * 'func' is now a non-bound object which supports [[HasInstance]]
83569 * (which here just means DUK_HOBJECT_FLAG_CALLABLE). Move on
83570 * to execute E5 Section 15.3.5.3.
83571 */
83572
83573 DUK_ASSERT(func != NULL);
83576
83577 /* [ ... lval rval(func) ] */
83578
83579 /* For lightfuncs, buffers, and pointers start the comparison directly
83580 * from the virtual prototype object.
83581 */
83582 skip_first = 0;
83583 tv = DUK_GET_TVAL_NEGIDX(thr, -2);
83584 switch (DUK_TVAL_GET_TAG(tv)) {
83585 case DUK_TAG_LIGHTFUNC:
83587 DUK_ASSERT(val != NULL);
83588 break;
83589 case DUK_TAG_BUFFER:
83591 DUK_ASSERT(val != NULL);
83592 break;
83593 case DUK_TAG_POINTER:
83595 DUK_ASSERT(val != NULL);
83596 break;
83597 case DUK_TAG_OBJECT:
83598 skip_first = 1; /* Ignore object itself on first round. */
83599 val = DUK_TVAL_GET_OBJECT(tv);
83600 DUK_ASSERT(val != NULL);
83601 break;
83602 default:
83603 goto pop2_and_false;
83604 }
83605 DUK_ASSERT(val != NULL); /* Loop doesn't actually rely on this. */
83606
83607 /* Look up .prototype of rval. Leave it on the value stack in case it
83608 * has been virtualized (e.g. getter, Proxy trap).
83609 */
83610 duk_get_prop_stridx_short(thr, -1, DUK_STRIDX_PROTOTYPE); /* -> [ ... lval rval rval.prototype ] */
83611#if defined(DUK_USE_VERBOSE_ERRORS)
83612 proto = duk_get_hobject(thr, -1);
83613 if (proto == NULL) {
83614 goto error_invalid_rval_noproto;
83615 }
83616#else
83617 proto = duk_require_hobject(thr, -1);
83618#endif
83619
83621 do {
83622 /*
83623 * Note: prototype chain is followed BEFORE first comparison. This
83624 * means that the instanceof lval is never itself compared to the
83625 * rval.prototype property. This is apparently intentional, see E5
83626 * Section 15.3.5.3, step 4.a.
83627 *
83628 * Also note:
83629 *
83630 * js> (function() {}) instanceof Function
83631 * true
83632 * js> Function instanceof Function
83633 * true
83634 *
83635 * For the latter, h_proto will be Function.prototype, which is the
83636 * built-in Function prototype. Because Function.[[Prototype]] is
83637 * also the built-in Function prototype, the result is true.
83638 */
83639
83640 if (!val) {
83641 goto pop3_and_false;
83642 }
83643
83644 DUK_ASSERT(val != NULL);
83645#if defined(DUK_USE_ES6_PROXY)
83647#endif
83649 if (skip_first) {
83650 skip_first = 0;
83651 } else if (val == proto) {
83652 goto pop3_and_true;
83654
83655 DUK_ASSERT(val != NULL);
83656 val = DUK_HOBJECT_GET_PROTOTYPE(thr->heap, val);
83657 } while (--sanity > 0);
83658
83659 DUK_ASSERT(sanity == 0);
83661 DUK_WO_NORETURN(return 0;);
83662
83663pop2_and_false:
83664 duk_pop_2_unsafe(thr);
83665 return 0;
83666
83667pop3_and_false:
83668 duk_pop_3_unsafe(thr);
83669 return 0;
83670
83671pop3_and_true:
83672 duk_pop_3_unsafe(thr);
83673 return 1;
83674
83675error_invalid_rval:
83677 DUK_WO_NORETURN(return 0;);
83678
83679#if defined(DUK_USE_VERBOSE_ERRORS)
83680error_invalid_rval_noproto:
83682 DUK_WO_NORETURN(return 0;);
83683#endif
83684}
83685
83686#if defined(DUK_USE_SYMBOL_BUILTIN)
83688 return duk__js_instanceof_helper(thr, tv_x, tv_y, 1 /*skip_sym_check*/);
83689}
83690#endif
83691
83693 return duk__js_instanceof_helper(thr, tv_x, tv_y, 0 /*skip_sym_check*/);
83694}
83695
83696/*
83697 * in
83698 */
83699
83700/*
83701 * E5 Sections 11.8.7, 8.12.6.
83702 *
83703 * Basically just a property existence check using [[HasProperty]].
83704 */
83705
83707 duk_bool_t retval;
83708
83709 /*
83710 * Get the values onto the stack first. It would be possible to cover
83711 * some normal cases without resorting to the value stack (e.g. if
83712 * lval is already a string).
83714
83715 /* XXX: The ES5/5.1/6 specifications require that the key in 'key in obj'
83716 * must be string coerced before the internal HasProperty() algorithm is
83717 * invoked. A fast path skipping coercion could be safely implemented for
83718 * numbers (as number-to-string coercion has no side effects). For ES2015
83719 * proxy behavior, the trap 'key' argument must be in a string coerced
83720 * form (which is a shame).
83721 */
83722
83723 /* TypeError if rval is not an object or object like (e.g. lightfunc
83724 * or plain buffer).
83725 */
83726 duk_push_tval(thr, tv_x);
83727 duk_push_tval(thr, tv_y);
83729
83730 (void) duk_to_property_key_hstring(thr, -2);
83731
83732 retval = duk_hobject_hasprop(thr, DUK_GET_TVAL_NEGIDX(thr, -1), DUK_GET_TVAL_NEGIDX(thr, -2));
83733
83734 duk_pop_2_unsafe(thr);
83735 return retval;
83736}
83737
83738/*
83739 * typeof
83740 *
83741 * E5 Section 11.4.3.
83742 *
83743 * Very straightforward. The only question is what to return for our
83744 * non-standard tag / object types.
83745 *
83746 * There is an unfortunate string constant define naming problem with
83747 * typeof return values for e.g. "Object" and "object"; careful with
83748 * the built-in string defines. The LC_XXX defines are used for the
83749 * lowercase variants now.
83750 */
83751
83753 duk_small_uint_t stridx = 0;
83754
83755 switch (DUK_TVAL_GET_TAG(tv_x)) {
83756 case DUK_TAG_UNDEFINED: {
83757 stridx = DUK_STRIDX_LC_UNDEFINED;
83758 break;
83759 }
83760 case DUK_TAG_NULL: {
83761 /* Note: not a typo, "object" is returned for a null value. */
83762 stridx = DUK_STRIDX_LC_OBJECT;
83763 break;
83764 }
83765 case DUK_TAG_BOOLEAN: {
83766 stridx = DUK_STRIDX_LC_BOOLEAN;
83767 break;
83768 }
83769 case DUK_TAG_POINTER: {
83770 /* Implementation specific. */
83771 stridx = DUK_STRIDX_LC_POINTER;
83772 break;
83773 }
83774 case DUK_TAG_STRING: {
83775 duk_hstring *str;
83776
83777 /* All internal keys are identified as Symbols. */
83778 str = DUK_TVAL_GET_STRING(tv_x);
83779 DUK_ASSERT(str != NULL);
83781 stridx = DUK_STRIDX_LC_SYMBOL;
83782 } else {
83783 stridx = DUK_STRIDX_LC_STRING;
83784 }
83785 break;
83786 }
83787 case DUK_TAG_OBJECT: {
83788 duk_hobject *obj = DUK_TVAL_GET_OBJECT(tv_x);
83789 DUK_ASSERT(obj != NULL);
83791 stridx = DUK_STRIDX_LC_FUNCTION;
83792 } else {
83793 stridx = DUK_STRIDX_LC_OBJECT;
83794 }
83795 break;
83796 }
83797 case DUK_TAG_BUFFER: {
83798 /* Implementation specific. In Duktape 1.x this would be
83799 * 'buffer', in Duktape 2.x changed to 'object' because plain
83800 * buffers now mimic Uint8Array objects.
83801 */
83802 stridx = DUK_STRIDX_LC_OBJECT;
83803 break;
83804 }
83805 case DUK_TAG_LIGHTFUNC: {
83806 stridx = DUK_STRIDX_LC_FUNCTION;
83807 break;
83808 }
83809#if defined(DUK_USE_FASTINT)
83810 case DUK_TAG_FASTINT:
83811#endif
83812 default: {
83813 /* number */
83817 break;
83818 }
83819 }
83820
83822 return stridx;
83823}
83824
83825/*
83826 * IsArray()
83827 */
83828
83830 DUK_ASSERT(h != NULL);
83831#if defined(DUK_USE_ES6_PROXY)
83833#endif
83835}
83836
83838 DUK_ASSERT(tv != NULL);
83839 if (DUK_TVAL_IS_OBJECT(tv)) {
83841 }
83842 return 0;
83843}
83844
83845/*
83846 * Array index and length
83847 *
83848 * Array index: E5 Section 15.4
83849 * Array length: E5 Section 15.4.5.1 steps 3.c - 3.d (array length write)
83850 */
83851
83852/* Compure array index from string context, or return a "not array index"
83853 * indicator.
83854 */
83855DUK_INTERNAL duk_uarridx_t duk_js_to_arrayindex_string(const duk_uint8_t *str, duk_uint32_t blen) {
83856 duk_uarridx_t res;
83857
83858 /* Only strings with byte length 1-10 can be 32-bit array indices.
83859 * Leading zeroes (except '0' alone), plus/minus signs are not allowed.
83860 * We could do a lot of prechecks here, but since most strings won't
83861 * start with any digits, it's simpler to just parse the number and
83862 * fail quickly.
83863 */
83864
83865 res = 0;
83866 if (blen == 0) {
83867 goto parse_fail;
83868 }
83869 do {
83870 duk_uarridx_t dig;
83871 dig = (duk_uarridx_t) (*str++) - DUK_ASC_0;
83872
83873 if (dig <= 9U) {
83874 /* Careful overflow handling. When multiplying by 10:
83875 * - 0x19999998 x 10 = 0xfffffff0: no overflow, and adding
83876 * 0...9 is safe.
83877 * - 0x19999999 x 10 = 0xfffffffa: no overflow, adding
83878 * 0...5 is safe, 6...9 overflows.
83879 * - 0x1999999a x 10 = 0x100000004: always overflow.
83880 */
83881 if (DUK_UNLIKELY(res >= 0x19999999UL)) {
83882 if (res >= 0x1999999aUL) {
83883 /* Always overflow. */
83884 goto parse_fail;
83885 }
83886 DUK_ASSERT(res == 0x19999999UL);
83887 if (dig >= 6U) {
83888 goto parse_fail;
83889 }
83890 res = 0xfffffffaUL + dig;
83891 DUK_ASSERT(res >= 0xfffffffaUL);
83892 DUK_ASSERT_DISABLE(res <= 0xffffffffUL); /* range */
83893 } else {
83894 res = res * 10U + dig;
83895 if (DUK_UNLIKELY(res == 0)) {
83896 /* If 'res' is 0, previous 'res' must
83897 * have been 0 and we scanned in a zero.
83898 * This is only allowed if blen == 1,
83899 * i.e. the exact string '0'.
83900 */
83901 if (blen == (duk_uint32_t) 1) {
83902 return 0;
83903 }
83904 goto parse_fail;
83905 }
83906 }
83907 } else {
83908 /* Because 'dig' is unsigned, catches both values
83909 * above '9' and below '0'.
83910 */
83911 goto parse_fail;
83912 }
83913 } while (--blen > 0);
83914
83915 return res;
83916
83917parse_fail:
83919}
83920
83921#if !defined(DUK_USE_HSTRING_ARRIDX)
83922/* Get array index for a string which is known to be an array index. This helper
83923 * is needed when duk_hstring doesn't concretely store the array index, but strings
83924 * are flagged as array indices at intern time.
83925 */
83926DUK_INTERNAL duk_uarridx_t duk_js_to_arrayindex_hstring_fast_known(duk_hstring *h) {
83927 const duk_uint8_t *p;
83928 duk_uarridx_t res;
83929 duk_uint8_t t;
83930
83931 DUK_ASSERT(h != NULL);
83933
83934 p = DUK_HSTRING_GET_DATA(h);
83935 res = 0;
83936 for (;;) {
83937 t = *p++;
83938 if (DUK_UNLIKELY(t == 0)) {
83939 /* Scanning to NUL is always safe for interned strings. */
83940 break;
83941 }
83942 DUK_ASSERT(t >= (duk_uint8_t) DUK_ASC_0 && t <= (duk_uint8_t) DUK_ASC_9);
83943 res = res * 10U + (duk_uarridx_t) t - (duk_uarridx_t) DUK_ASC_0;
83944 }
83945 return res;
83946}
83947
83948DUK_INTERNAL duk_uarridx_t duk_js_to_arrayindex_hstring_fast(duk_hstring *h) {
83949 DUK_ASSERT(h != NULL);
83950 if (!DUK_HSTRING_HAS_ARRIDX(h)) {
83952 }
83953 return duk_js_to_arrayindex_hstring_fast_known(h);
83954}
83955#endif /* DUK_USE_HSTRING_ARRIDX */
83957 * Identifier access and function closure handling.
83959 * Provides the primitives for slow path identifier accesses: GETVAR,
83960 * PUTVAR, DELVAR, etc. The fast path, direct register accesses, should
83961 * be used for most identifier accesses. Consequently, these slow path
83962 * primitives should be optimized for maximum compactness.
83963 *
83964 * ECMAScript environment records (declarative and object) are represented
83965 * as internal objects with control keys. Environment records have a
83966 * parent record ("outer environment reference") which is represented by
83967 * the implicit prototype for technical reasons (in other words, it is a
83968 * convenient field). The prototype chain is not followed in the ordinary
83969 * sense for variable lookups.
83970 *
83971 * See identifier-handling.rst for more details on the identifier algorithms
83972 * and the internal representation. See function-objects.rst for details on
83973 * what function templates and instances are expected to look like.
83974 *
83975 * Care must be taken to avoid duk_tval pointer invalidation caused by
83976 * e.g. value stack or object resizing.
83977 *
83978 * TODO: properties for function instances could be initialized much more
83979 * efficiently by creating a property allocation for a certain size and
83980 * filling in keys and values directly (and INCREFing both with "bulk incref"
83981 * primitives.
83982 *
83983 * XXX: duk_hobject_getprop() and duk_hobject_putprop() calls are a bit
83984 * awkward (especially because they follow the prototype chain); rework
83985 * if "raw" own property helpers are added.
83986 */
83987
83988/* #include duk_internal.h -> already included */
83990/*
83991 * Local result type for duk__get_identifier_reference() lookup.
83992 */
83993
83994typedef struct {
83995 duk_hobject *env;
83996 duk_hobject *holder; /* for object-bound identifiers */
83997 duk_tval *value; /* for register-bound and declarative env identifiers */
83998 duk_uint_t attrs; /* property attributes for identifier (relevant if value != NULL) */
83999 duk_bool_t has_this; /* for object-bound identifiers: provide 'this' binding */
84001
84002/*
84003 * Create a new function object based on a "template function" which contains
84004 * compiled bytecode, constants, etc, but lacks a lexical environment.
84005 *
84006 * ECMAScript requires that each created closure is a separate object, with
84007 * its own set of editable properties. However, structured property values
84008 * (such as the formal arguments list and the variable map) are shared.
84009 * Also the bytecode, constants, and inner functions are shared.
84010 *
84011 * See E5 Section 13.2 for detailed requirements on the function objects;
84012 * there are no similar requirements for function "templates" which are an
84013 * implementation dependent internal feature. Also see function-objects.rst
84014 * for a discussion on the function instance properties provided by this
84015 * implementation.
84016 *
84017 * Notes:
84018 *
84019 * * Order of internal properties should match frequency of use, since the
84020 * properties will be linearly scanned on lookup (functions usually don't
84021 * have enough properties to warrant a hash part).
84022 *
84023 * * The created closure is independent of its template; they do share the
84024 * same 'data' buffer object, but the template object itself can be freed
84025 * even if the closure object remains reachable.
84026 */
84027
84029 duk_tval *tv, *tv_end;
84030 duk_hobject **funcs, **funcs_end;
84031
84032 DUK_UNREF(thr);
84033
84034 /* If function creation fails due to out-of-memory, the data buffer
84035 * pointer may be NULL in some cases. That's actually possible for
84036 * GC code, but shouldn't be possible here because the incomplete
84037 * function will be unwound from the value stack and never instantiated.
84038 */
84039 DUK_ASSERT(DUK_HCOMPFUNC_GET_DATA(thr->heap, f) != NULL);
84041 tv = DUK_HCOMPFUNC_GET_CONSTS_BASE(thr->heap, f);
84042 tv_end = DUK_HCOMPFUNC_GET_CONSTS_END(thr->heap, f);
84043 while (tv < tv_end) {
84044 DUK_TVAL_INCREF(thr, tv);
84045 tv++;
84046 }
84047
84048 funcs = DUK_HCOMPFUNC_GET_FUNCS_BASE(thr->heap, f);
84049 funcs_end = DUK_HCOMPFUNC_GET_FUNCS_END(thr->heap, f);
84050 while (funcs < funcs_end) {
84051 DUK_HEAPHDR_INCREF(thr, (duk_heaphdr *) *funcs);
84052 funcs++;
84053 }
84054}
84055
84056/* Push a new closure on the stack.
84057 *
84058 * Note: if fun_temp has NEWENV, i.e. a new lexical and variable declaration
84059 * is created when the function is called, only outer_lex_env matters
84060 * (outer_var_env is ignored and may or may not be same as outer_lex_env).
84061 */
84062
84063DUK_LOCAL const duk_uint16_t duk__closure_copy_proplist[] = {
84064 /* order: most frequent to least frequent */
84067#if defined(DUK_USE_PC2LINE)
84069#endif
84070#if defined(DUK_USE_FUNC_FILENAME_PROPERTY)
84072#endif
84073#if defined(DUK_USE_NONSTD_FUNC_SOURCE_PROPERTY)
84075#endif
84076};
84077
84080 duk_hcompfunc *fun_temp,
84081 duk_hobject *outer_var_env,
84082 duk_hobject *outer_lex_env,
84083 duk_bool_t add_auto_proto) {
84084 duk_hcompfunc *fun_clos;
84085 duk_harray *formals;
84087 duk_uint_t len_value;
84088
84089 DUK_ASSERT(fun_temp != NULL);
84090 DUK_ASSERT(DUK_HCOMPFUNC_GET_DATA(thr->heap, fun_temp) != NULL);
84091 DUK_ASSERT(DUK_HCOMPFUNC_GET_FUNCS(thr->heap, fun_temp) != NULL);
84092 DUK_ASSERT(DUK_HCOMPFUNC_GET_BYTECODE(thr->heap, fun_temp) != NULL);
84093 DUK_ASSERT(outer_var_env != NULL);
84094 DUK_ASSERT(outer_lex_env != NULL);
84095 DUK_UNREF(len_value);
84096
84097 DUK_STATS_INC(thr->heap, stats_envrec_pushclosure);
84098
84099 fun_clos = duk_push_hcompfunc(thr);
84100 DUK_ASSERT(fun_clos != NULL);
84102
84103 duk_push_hobject(thr, &fun_temp->obj); /* -> [ ... closure template ] */
84104
84106 DUK_ASSERT(DUK_HCOMPFUNC_GET_DATA(thr->heap, fun_clos) == NULL);
84107 DUK_ASSERT(DUK_HCOMPFUNC_GET_FUNCS(thr->heap, fun_clos) == NULL);
84108 DUK_ASSERT(DUK_HCOMPFUNC_GET_BYTECODE(thr->heap, fun_clos) == NULL);
84109
84110 DUK_HCOMPFUNC_SET_DATA(thr->heap, fun_clos, DUK_HCOMPFUNC_GET_DATA(thr->heap, fun_temp));
84111 DUK_HCOMPFUNC_SET_FUNCS(thr->heap, fun_clos, DUK_HCOMPFUNC_GET_FUNCS(thr->heap, fun_temp));
84112 DUK_HCOMPFUNC_SET_BYTECODE(thr->heap, fun_clos, DUK_HCOMPFUNC_GET_BYTECODE(thr->heap, fun_temp));
84113
84114 /* Note: all references inside 'data' need to get their refcounts
84115 * upped too. This is the case because refcounts are decreased
84116 * through every function referencing 'data' independently.
84117 */
84118
84119 DUK_HBUFFER_INCREF(thr, DUK_HCOMPFUNC_GET_DATA(thr->heap, fun_clos));
84120 duk__inc_data_inner_refcounts(thr, fun_temp);
84121
84122 fun_clos->nregs = fun_temp->nregs;
84123 fun_clos->nargs = fun_temp->nargs;
84124#if defined(DUK_USE_DEBUGGER_SUPPORT)
84125 fun_clos->start_line = fun_temp->start_line;
84126 fun_clos->end_line = fun_temp->end_line;
84127#endif
84128
84129 DUK_ASSERT(DUK_HCOMPFUNC_GET_DATA(thr->heap, fun_clos) != NULL);
84130 DUK_ASSERT(DUK_HCOMPFUNC_GET_FUNCS(thr->heap, fun_clos) != NULL);
84131 DUK_ASSERT(DUK_HCOMPFUNC_GET_BYTECODE(thr->heap, fun_clos) != NULL);
84132
84133 /* XXX: Could also copy from template, but there's no way to have any
84134 * other value here now (used code has no access to the template).
84135 * Prototype is set by duk_push_hcompfunc().
84136 */
84138#if 0
84140#endif
84141
84142 /* Copy duk_hobject flags as is from the template using a mask.
84143 * Leave out duk_heaphdr owned flags just in case (e.g. if there's
84144 * some GC flag or similar). Some flags can then be adjusted
84145 * separately if necessary.
84146 */
84147
84148 /* DUK_HEAPHDR_SET_FLAGS() masks changes to non-duk_heaphdr flags only. */
84150 DUK_DD(DUK_DDPRINT("fun_temp heaphdr flags: 0x%08lx, fun_clos heaphdr flags: 0x%08lx",
84151 (unsigned long) DUK_HEAPHDR_GET_FLAGS_RAW((duk_heaphdr *) fun_temp),
84152 (unsigned long) DUK_HEAPHDR_GET_FLAGS_RAW((duk_heaphdr *) fun_clos)));
84153
84154 DUK_ASSERT(DUK_HOBJECT_HAS_EXTENSIBLE(&fun_clos->obj));
84155 DUK_ASSERT(!DUK_HOBJECT_HAS_BOUNDFUNC(&fun_clos->obj));
84156 DUK_ASSERT(DUK_HOBJECT_HAS_COMPFUNC(&fun_clos->obj));
84157 DUK_ASSERT(!DUK_HOBJECT_HAS_NATFUNC(&fun_clos->obj));
84158 DUK_ASSERT(!DUK_HOBJECT_IS_THREAD(&fun_clos->obj));
84159 /* DUK_HOBJECT_FLAG_ARRAY_PART: don't care */
84160 /* DUK_HOBJECT_FLAG_NEWENV: handled below */
84161 DUK_ASSERT(!DUK_HOBJECT_HAS_EXOTIC_ARRAY(&fun_clos->obj));
84164
84165 if (!DUK_HOBJECT_HAS_CONSTRUCTABLE(&fun_clos->obj)) {
84166 /* If the template is not constructable don't add an automatic
84167 * .prototype property. This is the case for e.g. ES2015 object
84168 * literal getters/setters and method definitions.
84169 */
84170 add_auto_proto = 0;
84171 }
84172
84173 /*
84174 * Setup environment record properties based on the template and
84175 * its flags.
84176 *
84177 * If DUK_HOBJECT_HAS_NEWENV(fun_temp) is true, the environment
84178 * records represent identifiers "outside" the function; the
84179 * "inner" environment records are created on demand. Otherwise,
84180 * the environment records are those that will be directly used
84181 * (e.g. for declarations).
84182 *
84183 * _Lexenv is always set; _Varenv defaults to _Lexenv if missing,
84184 * so _Varenv is only set if _Lexenv != _Varenv.
84185 *
84186 * This is relatively complex, see doc/identifier-handling.rst.
84187 */
84188
84189 if (DUK_HOBJECT_HAS_NEWENV(&fun_clos->obj)) {
84190#if defined(DUK_USE_FUNC_NAME_PROPERTY)
84191 if (DUK_HOBJECT_HAS_NAMEBINDING(&fun_clos->obj)) {
84192 duk_hobject *proto;
84193 duk_hdecenv *new_env;
84194
84195 /*
84196 * Named function expression, name needs to be bound
84197 * in an intermediate environment record. The "outer"
84198 * lexical/variable environment will thus be:
84199 *
84200 * a) { funcname: <func>, __prototype: outer_lex_env }
84201 * b) { funcname: <func>, __prototype: <globalenv> } (if outer_lex_env missing)
84202 */
84203
84204 if (outer_lex_env) {
84205 proto = outer_lex_env;
84206 } else {
84207 proto = thr->builtins[DUK_BIDX_GLOBAL_ENV];
84208 }
84209
84210 /* -> [ ... closure template env ] */
84211 new_env =
84214 DUK_ASSERT(new_env != NULL);
84215 duk_push_hobject(thr, (duk_hobject *) new_env);
84216
84217 DUK_ASSERT(DUK_HOBJECT_GET_PROTOTYPE(thr->heap, (duk_hobject *) new_env) == NULL);
84218 DUK_HOBJECT_SET_PROTOTYPE(thr->heap, (duk_hobject *) new_env, proto);
84219 DUK_HOBJECT_INCREF_ALLOWNULL(thr, proto);
84220
84221 DUK_ASSERT(new_env->thread == NULL); /* Closed. */
84222 DUK_ASSERT(new_env->varmap == NULL);
84223
84224 /* It's important that duk_xdef_prop() is a 'raw define' so that any
84225 * properties in an ancestor are never an issue (they should never be
84226 * e.g. non-writable, but just in case).
84227 *
84228 * Because template objects are not visible to user code, the case
84229 * where .name is missing shouldn't happen in practice. It it does,
84230 * the name 'undefined' gets bound and maps to the closure (which is
84231 * a bit odd, but safe).
84232 */
84234 /* -> [ ... closure template env funcname ] */
84235 duk_dup_m4(thr); /* -> [ ... closure template env funcname closure ] */
84236 duk_xdef_prop(thr, -3, DUK_PROPDESC_FLAGS_NONE); /* -> [ ... closure template env ] */
84237 /* env[funcname] = closure */
84238
84239 /* [ ... closure template env ] */
84240
84241 DUK_HCOMPFUNC_SET_LEXENV(thr->heap, fun_clos, (duk_hobject *) new_env);
84242 DUK_HCOMPFUNC_SET_VARENV(thr->heap, fun_clos, (duk_hobject *) new_env);
84243 DUK_HOBJECT_INCREF(thr, (duk_hobject *) new_env);
84244 DUK_HOBJECT_INCREF(thr, (duk_hobject *) new_env);
84245 duk_pop_unsafe(thr);
84246
84247 /* [ ... closure template ] */
84248 } else
84249#endif /* DUK_USE_FUNC_NAME_PROPERTY */
84250 {
84251 /*
84252 * Other cases (function declaration, anonymous function expression,
84253 * strict direct eval code). The "outer" environment will be whatever
84254 * the caller gave us.
84255 */
84256
84257 DUK_HCOMPFUNC_SET_LEXENV(thr->heap, fun_clos, outer_lex_env);
84258 DUK_HCOMPFUNC_SET_VARENV(thr->heap, fun_clos, outer_lex_env);
84259 DUK_HOBJECT_INCREF(thr, outer_lex_env);
84260 DUK_HOBJECT_INCREF(thr, outer_lex_env);
84261
84262 /* [ ... closure template ] */
84263 }
84264 } else {
84265 /*
84266 * Function gets no new environment when called. This is the
84267 * case for global code, indirect eval code, and non-strict
84268 * direct eval code. There is no direct correspondence to the
84269 * E5 specification, as global/eval code is not exposed as a
84270 * function.
84271 */
84272
84273 DUK_ASSERT(!DUK_HOBJECT_HAS_NAMEBINDING(&fun_temp->obj));
84274
84275 DUK_HCOMPFUNC_SET_LEXENV(thr->heap, fun_clos, outer_lex_env);
84276 DUK_HCOMPFUNC_SET_VARENV(thr->heap, fun_clos, outer_var_env);
84277 DUK_HOBJECT_INCREF(thr, outer_lex_env); /* NULLs not allowed; asserted on entry */
84278 DUK_HOBJECT_INCREF(thr, outer_var_env);
84279 }
84280 DUK_DDD(DUK_DDDPRINT("closure varenv -> %!ipO, lexenv -> %!ipO",
84281 (duk_heaphdr *) fun_clos->var_env,
84282 (duk_heaphdr *) fun_clos->lex_env));
84283
84284 /* Call handling assumes this for all callable closures. */
84285 DUK_ASSERT(DUK_HCOMPFUNC_GET_LEXENV(thr->heap, fun_clos) != NULL);
84286 DUK_ASSERT(DUK_HCOMPFUNC_GET_VARENV(thr->heap, fun_clos) != NULL);
84287
84288 /*
84289 * Copy some internal properties directly
84290 *
84291 * The properties will be non-writable and non-enumerable, but
84292 * configurable.
84293 *
84294 * Function templates are bare objects, so inheritance of internal
84295 * Symbols is not an issue here even when using ordinary property
84296 * reads. The function instance created is not bare, so internal
84297 * Symbols must be defined without inheritance checks.
84298 */
84299
84300 /* [ ... closure template ] */
84301
84302 DUK_DDD(DUK_DDDPRINT("copying properties: closure=%!iT, template=%!iT",
84303 (duk_tval *) duk_get_tval(thr, -2),
84304 (duk_tval *) duk_get_tval(thr, -1)));
84305
84306 for (i = 0; i < (duk_small_uint_t) (sizeof(duk__closure_copy_proplist) / sizeof(duk_uint16_t)); i++) {
84308 if (duk_xget_owndataprop_stridx_short(thr, -1, stridx)) {
84309 /* [ ... closure template val ] */
84310 DUK_DDD(DUK_DDDPRINT("copying property, stridx=%ld -> found", (long) stridx));
84312 } else {
84313 DUK_DDD(DUK_DDDPRINT("copying property, stridx=%ld -> not found", (long) stridx));
84314 duk_pop_unsafe(thr);
84315 }
84316 }
84317
84318 /*
84319 * "length" maps to number of formals (E5 Section 13.2) for function
84320 * declarations/expressions (non-bound functions). Note that 'nargs'
84321 * is NOT necessarily equal to the number of arguments. Use length
84322 * of _Formals; if missing, assume nargs matches .length.
84323 */
84324
84325 /* [ ... closure template ] */
84326
84327 formals = duk_hobject_get_formals(thr, (duk_hobject *) fun_temp);
84328 if (formals) {
84329 len_value = (duk_uint_t) formals->length;
84330 DUK_DD(DUK_DDPRINT("closure length from _Formals -> %ld", (long) len_value));
84331 } else {
84332 len_value = fun_temp->nargs;
84333 DUK_DD(DUK_DDPRINT("closure length defaulted from nargs -> %ld", (long) len_value));
84334 }
84335
84336 duk_push_uint(thr, len_value); /* [ ... closure template len_value ] */
84338
84339 /*
84340 * "prototype" is, by default, a fresh object with the "constructor"
84341 * property.
84342 *
84343 * Note that this creates a circular reference for every function
84344 * instance (closure) which prevents refcount-based collection of
84345 * function instances.
84346 *
84347 * XXX: Try to avoid creating the default prototype object, because
84348 * many functions are not used as constructors and the default
84349 * prototype is unnecessary. Perhaps it could be created on-demand
84350 * when it is first accessed?
84351 */
84352
84353 /* [ ... closure template ] */
84354
84355 if (add_auto_proto) {
84356 duk_push_object(thr); /* -> [ ... closure template newobj ] */
84357 duk_dup_m3(thr); /* -> [ ... closure template newobj closure ] */
84359 -2,
84361 DUK_PROPDESC_FLAGS_WC); /* -> [ ... closure template newobj ] */
84362 duk_compact(thr, -1); /* compact the prototype */
84363 duk_xdef_prop_stridx_short(thr, -3, DUK_STRIDX_PROTOTYPE, DUK_PROPDESC_FLAGS_W); /* -> [ ... closure template ] */
84364 }
84365
84366 /*
84367 * "arguments" and "caller" must be mapped to throwers for strict
84368 * mode and bound functions (E5 Section 15.3.5).
84369 *
84370 * XXX: This is expensive to have for every strict function instance.
84371 * Try to implement as virtual properties or on-demand created properties.
84372 */
84373
84374 /* [ ... closure template ] */
84375
84376 if (DUK_HOBJECT_HAS_STRICT(&fun_clos->obj)) {
84379 } else {
84380#if defined(DUK_USE_NONSTD_FUNC_CALLER_PROPERTY)
84381 DUK_DDD(DUK_DDDPRINT("function is non-strict and non-standard 'caller' property in use, add initial 'null' value"));
84382 duk_push_null(thr);
84384#else
84385 DUK_DDD(DUK_DDDPRINT("function is non-strict and non-standard 'caller' property not used"));
84386#endif
84387 }
84388
84389 /*
84390 * "name" used to be non-standard but is now defined by ES2015.
84391 * In ES2015/ES2016 the .name property is configurable.
84392 */
84393
84394 /* [ ... closure template ] */
84395
84396#if defined(DUK_USE_FUNC_NAME_PROPERTY)
84397 /* XXX: Look for own property only; doesn't matter much because
84398 * templates are bare objects.
84399 */
84401 /* [ ... closure template name ] */
84402 DUK_ASSERT(duk_is_string(thr, -1));
84403 DUK_DD(DUK_DDPRINT("setting function instance name to %!T", duk_get_tval(thr, -1)));
84404 duk_xdef_prop_stridx_short(thr, -3, DUK_STRIDX_NAME, DUK_PROPDESC_FLAGS_C); /* -> [ ... closure template ] */
84405 } else {
84406 /* Anonymous functions don't have a .name in ES2015, so don't set
84407 * it on the instance either. The instance will then inherit
84408 * it from Function.prototype.name.
84409 */
84410 DUK_DD(DUK_DDPRINT("not setting function instance .name"));
84411 duk_pop_unsafe(thr);
84412 }
84413#endif
84414
84415 /*
84416 * Compact the closure, in most cases no properties will be added later.
84417 * Also, without this the closures end up having unused property slots
84418 * (e.g. in Duktape 0.9.0, 8 slots would be allocated and only 7 used).
84419 * A better future solution would be to allocate the closure directly
84420 * to correct size (and setup the properties directly without going
84421 * through the API).
84423
84424 duk_compact(thr, -2);
84425
84426 /*
84427 * Some assertions (E5 Section 13.2).
84428 */
84429
84432 DUK_ASSERT(DUK_HOBJECT_HAS_EXTENSIBLE(&fun_clos->obj));
84434 DUK_ASSERT(add_auto_proto == 0 || duk_has_prop_stridx(thr, -2, DUK_STRIDX_PROTOTYPE) != 0);
84435 /* May be missing .name */
84436 DUK_ASSERT(!DUK_HOBJECT_HAS_STRICT(&fun_clos->obj) || duk_has_prop_stridx(thr, -2, DUK_STRIDX_CALLER) != 0);
84438
84439 /*
84440 * Finish
84441 */
84442
84443 /* [ ... closure template ] */
84444
84445 DUK_DDD(DUK_DDDPRINT("created function instance: template=%!iT -> closure=%!iT",
84446 (duk_tval *) duk_get_tval(thr, -1),
84447 (duk_tval *) duk_get_tval(thr, -2)));
84448
84449 duk_pop_unsafe(thr);
84450
84451 /* [ ... closure ] */
84452}
84453
84454/*
84455 * Delayed activation environment record initialization (for functions
84456 * with NEWENV).
84457 *
84458 * The non-delayed initialization is handled by duk_handle_call().
84459 */
84460
84463
84464 for (i = 0; i < (duk_uint_fast32_t) DUK_HOBJECT_GET_ENEXT(varmap); i++) {
84465 duk_hstring *key;
84466
84467 key = DUK_HOBJECT_E_GET_KEY(thr->heap, varmap, i);
84468 DUK_ASSERT(key != NULL); /* assume keys are compact in _Varmap */
84469 DUK_ASSERT(!DUK_HOBJECT_E_SLOT_IS_ACCESSOR(thr->heap, varmap, i)); /* assume plain values */
84470
84471 /* Predefine as 'undefined' to reserve a property slot.
84472 * This makes the unwind process (where register values
84473 * are copied to the env object) safe against throwing.
84474 *
84475 * XXX: This could be made much faster by creating the
84476 * property table directly.
84477 */
84478 duk_push_undefined(thr);
84479 DUK_DDD(DUK_DDDPRINT("preallocate env entry for key %!O", key));
84481 }
84482}
84483
84484/* shared helper */
84487 duk_hdecenv *env;
84489 duk_hcompfunc *f;
84490
84491 DUK_ASSERT(thr != NULL);
84492 DUK_ASSERT(func != NULL);
84493
84494 DUK_STATS_INC(thr->heap, stats_envrec_create);
84495
84496 f = (duk_hcompfunc *) func;
84498 if (!parent) {
84500 }
84501
84503 DUK_ASSERT(env != NULL);
84504 duk_push_hobject(thr, (duk_hobject *) env);
84505
84506 DUK_ASSERT(DUK_HOBJECT_GET_PROTOTYPE(thr->heap, (duk_hobject *) env) == NULL);
84508 DUK_HOBJECT_INCREF_ALLOWNULL(thr, parent); /* parent env is the prototype */
84509
84510 /* open scope information, for compiled functions only */
84511
84512 DUK_ASSERT(env->thread == NULL);
84513 DUK_ASSERT(env->varmap == NULL);
84514 DUK_ASSERT(env->regbase_byteoff == 0);
84515 if (DUK_HOBJECT_IS_COMPFUNC(func)) {
84516 duk_hobject *varmap;
84517
84518 varmap = duk_hobject_get_varmap(thr, func);
84519 if (varmap != NULL) {
84520 env->varmap = varmap;
84521 DUK_HOBJECT_INCREF(thr, varmap);
84522 env->thread = thr;
84523 DUK_HTHREAD_INCREF(thr, thr);
84524 env->regbase_byteoff = bottom_byteoff;
84525
84526 /* Preallocate env property table to avoid potential
84527 * for out-of-memory on unwind when the env is closed.
84528 */
84529 duk__preallocate_env_entries(thr, varmap, (duk_hobject *) env);
84530 } else {
84531 /* If function has no _Varmap, leave the environment closed. */
84532 DUK_ASSERT(env->thread == NULL);
84533 DUK_ASSERT(env->varmap == NULL);
84534 DUK_ASSERT(env->regbase_byteoff == 0);
84535 }
84536 }
84537
84538 return (duk_hobject *) env;
84539}
84540
84543 duk_hobject *func;
84544 duk_hobject *env;
84545
84546 DUK_ASSERT(thr != NULL);
84547 func = DUK_ACT_GET_FUNC(act);
84548 DUK_ASSERT(func != NULL);
84549 DUK_ASSERT(!DUK_HOBJECT_HAS_BOUNDFUNC(func)); /* bound functions are never in act 'func' */
84550
84551 /*
84552 * Delayed initialization only occurs for 'NEWENV' functions.
84554
84556 DUK_ASSERT(act->lex_env == NULL);
84557 DUK_ASSERT(act->var_env == NULL);
84558
84559 DUK_STATS_INC(thr->heap, stats_envrec_delayedcreate);
84560
84562 DUK_ASSERT(env != NULL);
84563 /* 'act' is a stable pointer, so still OK. */
84564
84565 DUK_DDD(DUK_DDDPRINT("created delayed fresh env: %!ipO", (duk_heaphdr *) env));
84566#if defined(DUK_USE_DEBUG_LEVEL) && (DUK_USE_DEBUG_LEVEL >= 2)
84567 {
84568 duk_hobject *p = env;
84569 while (p) {
84570 DUK_DDD(DUK_DDDPRINT(" -> %!ipO", (duk_heaphdr *) p));
84571 p = DUK_HOBJECT_GET_PROTOTYPE(thr->heap, p);
84572 }
84573 }
84574#endif
84575
84576 act->lex_env = env;
84577 act->var_env = env;
84578 DUK_HOBJECT_INCREF(thr, env); /* XXX: incref by count (here 2 times) */
84579 DUK_HOBJECT_INCREF(thr, env);
84580
84581 duk_pop_unsafe(thr);
84582}
84583
84584/*
84585 * Closing environment records.
84586 *
84587 * The environment record MUST be closed with the thread where its activation
84588 * is; i.e. if 'env' is open, 'thr' must match env->thread, and the regbase
84589 * and varmap must still be valid. On entry, 'env' must be reachable.
84590 */
84591
84594 duk_hobject *varmap;
84595 duk_hstring *key;
84596 duk_tval *tv;
84597 duk_uint_t regnum;
84598
84599 DUK_ASSERT(thr != NULL);
84600 DUK_ASSERT(env != NULL);
84601
84603 DUK_DDD(DUK_DDDPRINT("env not a declarative record: %!iO", (duk_heaphdr *) env));
84604 return;
84605 }
84606
84607 varmap = ((duk_hdecenv *) env)->varmap;
84608 if (varmap == NULL) {
84609 DUK_DDD(DUK_DDDPRINT("env already closed: %!iO", (duk_heaphdr *) env));
84610
84611 return;
84612 }
84613 DUK_ASSERT(((duk_hdecenv *) env)->thread != NULL);
84615
84616 DUK_DDD(DUK_DDDPRINT("closing env: %!iO", (duk_heaphdr *) env));
84617 DUK_DDD(DUK_DDDPRINT("varmap: %!O", (duk_heaphdr *) varmap));
84618
84619 /* Env must be closed in the same thread as where it runs. */
84620 DUK_ASSERT(((duk_hdecenv *) env)->thread == thr);
84621
84622 /* XXX: additional conditions when to close variables? we don't want to do it
84623 * unless the environment may have "escaped" (referenced in a function closure).
84624 * With delayed environments, the existence is probably good enough of a check.
84625 */
84626
84627 /* Note: we rely on the _Varmap having a bunch of nice properties, like:
84628 * - being compacted and unmodified during this process
84629 * - not containing an array part
84630 * - having correct value types
84631 */
84632
84633 DUK_DDD(DUK_DDDPRINT("copying bound register values, %ld bound regs", (long) DUK_HOBJECT_GET_ENEXT(varmap)));
84634
84635 /* Copy over current variable values from value stack to the
84636 * environment record. The scope object is empty but may
84637 * inherit from another scope which has conflicting names.
84638 */
84639
84640 /* XXX: Do this using a once allocated entry area, no side effects.
84641 * Hash part would need special treatment however (maybe copy, and
84642 * then realloc with hash part if large enough).
84643 */
84644 for (i = 0; i < (duk_uint_fast32_t) DUK_HOBJECT_GET_ENEXT(varmap); i++) {
84645 duk_size_t regbase_byteoff;
84646
84647 key = DUK_HOBJECT_E_GET_KEY(thr->heap, varmap, i);
84648 DUK_ASSERT(key != NULL); /* assume keys are compact in _Varmap */
84649 DUK_ASSERT(!DUK_HOBJECT_E_SLOT_IS_ACCESSOR(thr->heap, varmap, i)); /* assume plain values */
84650
84651 tv = DUK_HOBJECT_E_GET_VALUE_TVAL_PTR(thr->heap, varmap, i);
84654#if defined(DUK_USE_FASTINT)
84656 regnum = (duk_uint_t) DUK_TVAL_GET_FASTINT_U32(tv);
84657#else
84658 regnum = (duk_uint_t) DUK_TVAL_GET_NUMBER(tv);
84659#endif
84660
84661 regbase_byteoff = ((duk_hdecenv *) env)->regbase_byteoff;
84662 DUK_ASSERT((duk_uint8_t *) thr->valstack + regbase_byteoff + sizeof(duk_tval) * regnum >=
84663 (duk_uint8_t *) thr->valstack);
84664 DUK_ASSERT((duk_uint8_t *) thr->valstack + regbase_byteoff + sizeof(duk_tval) * regnum <
84665 (duk_uint8_t *) thr->valstack_top);
84666
84667 /* Write register value into env as named properties.
84668 * If property already exists, overwrites silently.
84669 * Property is writable, but not deletable (not configurable
84670 * in terms of property attributes).
84671 *
84672 * This property write must not throw because we're unwinding
84673 * and unwind code is not allowed to throw at present. The
84674 * call itself has no such guarantees, but we've preallocated
84675 * entries for each property when the env was created, so no
84676 * out-of-memory error should be possible. If this guarantee
84677 * is not provided, problems like GH-476 may happen.
84678 */
84679 duk_push_tval(thr,
84680 (duk_tval *) (void *) ((duk_uint8_t *) thr->valstack + regbase_byteoff + sizeof(duk_tval) * regnum));
84681 DUK_DDD(DUK_DDDPRINT("closing identifier %!O -> reg %ld, value %!T",
84682 (duk_heaphdr *) key,
84683 (long) regnum,
84684 (duk_tval *) duk_get_tval(thr, -1)));
84686 }
84687
84688 /* NULL atomically to avoid inconsistent state + side effects. */
84689 DUK_HOBJECT_DECREF_NORZ(thr, ((duk_hdecenv *) env)->thread);
84690 DUK_HOBJECT_DECREF_NORZ(thr, ((duk_hdecenv *) env)->varmap);
84691 ((duk_hdecenv *) env)->thread = NULL;
84692 ((duk_hdecenv *) env)->varmap = NULL;
84693
84694 DUK_DDD(DUK_DDDPRINT("env after closing: %!O", (duk_heaphdr *) env));
84695}
84696
84697/*
84698 * GETIDREF: a GetIdentifierReference-like helper.
84699 *
84700 * Provides a parent traversing lookup and a single level lookup
84701 * (for HasBinding).
84702 *
84703 * Instead of returning the value, returns a bunch of values allowing
84704 * the caller to read, write, or delete the binding. Value pointers
84705 * are duk_tval pointers which can be mutated directly as long as
84706 * refcounts are properly updated. Note that any operation which may
84707 * reallocate valstacks or compact objects may invalidate the returned
84708 * duk_tval (but not object) pointers, so caller must be very careful.
84709 *
84710 * If starting environment record 'env' is given, 'act' is ignored.
84711 * However, if 'env' is NULL, the caller may identify, in 'act', an
84712 * activation which hasn't had its declarative environment initialized
84713 * yet. The activation registers are then looked up, and its parent
84714 * traversed normally.
84715 *
84716 * The 'out' structure values are only valid if the function returns
84717 * success (non-zero).
84718 */
84719
84720/* lookup name from an open declarative record's registers */
84723 duk_tval *tv;
84724 duk_size_t reg_rel;
84725
84726 DUK_ASSERT(thr != NULL);
84727 DUK_ASSERT(name != NULL);
84728 DUK_ASSERT(env != NULL);
84729 DUK_ASSERT(out != NULL);
84730
84733
84734 if (env->thread == NULL) {
84735 /* already closed */
84736 return 0;
84737 }
84738 DUK_ASSERT(env->varmap != NULL);
84739
84740 tv = duk_hobject_find_entry_tval_ptr(thr->heap, env->varmap, name);
84741 if (DUK_UNLIKELY(tv == NULL)) {
84742 return 0;
84743 }
84744
84747#if defined(DUK_USE_FASTINT)
84749 reg_rel = (duk_size_t) DUK_TVAL_GET_FASTINT_U32(tv);
84750#else
84751 reg_rel = (duk_size_t) DUK_TVAL_GET_NUMBER(tv);
84752#endif
84753 DUK_ASSERT_DISABLE(reg_rel >= 0); /* unsigned */
84754
84755 tv = (duk_tval *) (void *) ((duk_uint8_t *) env->thread->valstack + env->regbase_byteoff + sizeof(duk_tval) * reg_rel);
84756 DUK_ASSERT(tv >= env->thread->valstack && tv < env->thread->valstack_end); /* XXX: more accurate? */
84757
84758 out->value = tv;
84759 out->attrs = DUK_PROPDESC_FLAGS_W; /* registers are mutable, non-deletable */
84760 out->env = (duk_hobject *) env;
84761 out->holder = NULL;
84762 out->has_this = 0;
84763 return 1;
84764}
84765
84766/* lookup name from current activation record's functions' registers */
84769 duk_tval *tv;
84770 duk_hobject *func;
84771 duk_hobject *varmap;
84772 duk_size_t reg_rel;
84773
84774 DUK_ASSERT(thr != NULL);
84775 DUK_ASSERT(name != NULL);
84776 DUK_ASSERT(act != NULL);
84777 DUK_ASSERT(out != NULL);
84778
84779 func = DUK_ACT_GET_FUNC(act);
84780 DUK_ASSERT(func != NULL);
84782
84783 if (!DUK_HOBJECT_IS_COMPFUNC(func)) {
84784 return 0;
84785 }
84786
84787 /* XXX: move varmap to duk_hcompfunc struct field? */
84788 varmap = duk_hobject_get_varmap(thr, func);
84789 if (!varmap) {
84790 return 0;
84791 }
84792
84793 tv = duk_hobject_find_entry_tval_ptr(thr->heap, varmap, name);
84794 if (!tv) {
84795 return 0;
84796 }
84798 reg_rel = (duk_size_t) DUK_TVAL_GET_NUMBER(tv);
84799 DUK_ASSERT_DISABLE(reg_rel >= 0);
84800 DUK_ASSERT(reg_rel < ((duk_hcompfunc *) func)->nregs);
84801
84802 tv = (duk_tval *) (void *) ((duk_uint8_t *) thr->valstack + act->bottom_byteoff);
84803 tv += reg_rel;
84804
84805 out->value = tv;
84806 out->attrs = DUK_PROPDESC_FLAGS_W; /* registers are mutable, non-deletable */
84807 out->env = NULL;
84808 out->holder = NULL;
84809 out->has_this = 0;
84810 return 1;
84811}
84812
84815 duk_hobject *env,
84816 duk_hstring *name,
84817 duk_activation *act,
84818 duk_bool_t parents,
84819 duk__id_lookup_result *out) {
84820 duk_tval *tv;
84821 duk_uint_t sanity;
84822
84823 DUK_ASSERT(thr != NULL);
84824 DUK_ASSERT(env != NULL || act != NULL);
84825 DUK_ASSERT(name != NULL);
84826 DUK_ASSERT(out != NULL);
84827
84828 DUK_ASSERT(!env || DUK_HOBJECT_IS_ENV(env));
84830
84831 /*
84832 * Conceptually, we look for the identifier binding by starting from
84833 * 'env' and following to chain of environment records (represented
84834 * by the prototype chain).
84835 *
84836 * If 'env' is NULL, the current activation does not yet have an
84837 * allocated declarative environment record; this should be treated
84838 * exactly as if the environment record existed but had no bindings
84839 * other than register bindings.
84840 *
84841 * Note: we assume that with the DUK_HOBJECT_FLAG_NEWENV cleared
84842 * the environment will always be initialized immediately; hence
84843 * a NULL 'env' should only happen with the flag set. This is the
84844 * case for: (1) function calls, and (2) strict, direct eval calls.
84845 */
84846
84847 if (env == NULL && act != NULL) {
84848 duk_hobject *func;
84849 duk_hcompfunc *f;
84850
84851 DUK_DDD(DUK_DDDPRINT("duk__get_identifier_reference: env is NULL, activation is non-NULL -> "
84852 "delayed env case, look up activation regs first"));
84853
84854 /*
84855 * Try registers
84856 */
84857
84858 if (duk__getid_activation_regs(thr, name, act, out)) {
84859 DUK_DDD(DUK_DDDPRINT("duk__get_identifier_reference successful: "
84860 "name=%!O -> value=%!T, attrs=%ld, has_this=%ld, env=%!O, holder=%!O "
84861 "(found from register bindings when env=NULL)",
84862 (duk_heaphdr *) name,
84863 (duk_tval *) out->value,
84864 (long) out->attrs,
84865 (long) out->has_this,
84866 (duk_heaphdr *) out->env,
84867 (duk_heaphdr *) out->holder));
84868 return 1;
84869 }
84870
84871 DUK_DDD(DUK_DDDPRINT("not found in current activation regs"));
84872
84873 /*
84874 * Not found in registers, proceed to the parent record.
84875 * Here we need to determine what the parent would be,
84876 * if 'env' was not NULL (i.e. same logic as when initializing
84877 * the record).
84878 *
84879 * Note that environment initialization is only deferred when
84880 * DUK_HOBJECT_HAS_NEWENV is set, and this only happens for:
84881 * - Function code
84882 * - Strict eval code
84883 *
84884 * We only need to check _Lexenv here; _Varenv exists only if it
84885 * differs from _Lexenv (and thus _Lexenv will also be present).
84886 */
84887
84888 if (!parents) {
84889 DUK_DDD(DUK_DDDPRINT("duk__get_identifier_reference failed, no parent traversal "
84890 "(not found from register bindings when env=NULL)"));
84891 goto fail_not_found;
84892 }
84893
84894 func = DUK_ACT_GET_FUNC(act);
84895 DUK_ASSERT(func != NULL);
84897 f = (duk_hcompfunc *) func;
84898
84899 env = DUK_HCOMPFUNC_GET_LEXENV(thr->heap, f);
84900 if (!env) {
84901 env = thr->builtins[DUK_BIDX_GLOBAL_ENV];
84902 }
84903
84904 DUK_DDD(DUK_DDDPRINT("continue lookup from env: %!iO", (duk_heaphdr *) env));
84905 }
84906
84907 /*
84908 * Prototype walking starting from 'env'.
84909 *
84910 * ('act' is not needed anywhere here.)
84911 */
84912
84914 while (env != NULL) {
84916 duk_uint_t attrs;
84917
84918 DUK_DDD(DUK_DDDPRINT("duk__get_identifier_reference, name=%!O, considering env=%p -> %!iO",
84919 (duk_heaphdr *) name,
84920 (void *) env,
84921 (duk_heaphdr *) env));
84922
84923 DUK_ASSERT(env != NULL);
84926
84929 if (cl == DUK_HOBJECT_CLASS_DECENV) {
84930 /*
84931 * Declarative environment record.
84932 *
84933 * Identifiers can never be stored in ancestors and are
84934 * always plain values, so we can use an internal helper
84935 * and access the value directly with an duk_tval ptr.
84936 *
84937 * A closed environment is only indicated by it missing
84938 * the "book-keeping" properties required for accessing
84939 * register-bound variables.
84940 */
84941
84943 if (duk__getid_open_decl_env_regs(thr, name, (duk_hdecenv *) env, out)) {
84944 DUK_DDD(DUK_DDDPRINT("duk__get_identifier_reference successful: "
84945 "name=%!O -> value=%!T, attrs=%ld, has_this=%ld, env=%!O, holder=%!O "
84946 "(declarative environment record, scope open, found in regs)",
84947 (duk_heaphdr *) name,
84948 (duk_tval *) out->value,
84949 (long) out->attrs,
84950 (long) out->has_this,
84951 (duk_heaphdr *) out->env,
84952 (duk_heaphdr *) out->holder));
84953 return 1;
84954 }
84955
84956 tv = duk_hobject_find_entry_tval_ptr_and_attrs(thr->heap, env, name, &attrs);
84957 if (tv) {
84958 out->value = tv;
84959 out->attrs = attrs;
84960 out->env = env;
84961 out->holder = env;
84962 out->has_this = 0;
84963
84964 DUK_DDD(DUK_DDDPRINT("duk__get_identifier_reference successful: "
84965 "name=%!O -> value=%!T, attrs=%ld, has_this=%ld, env=%!O, holder=%!O "
84966 "(declarative environment record, found in properties)",
84967 (duk_heaphdr *) name,
84968 (duk_tval *) out->value,
84969 (long) out->attrs,
84970 (long) out->has_this,
84971 (duk_heaphdr *) out->env,
84972 (duk_heaphdr *) out->holder));
84973 return 1;
84974 }
84975 } else {
84976 /*
84977 * Object environment record.
84978 *
84979 * Binding (target) object is an external, uncontrolled object.
84980 * Identifier may be bound in an ancestor property, and may be
84981 * an accessor. Target can also be a Proxy which we must support
84982 * here.
84983 */
84984
84985 /* XXX: we could save space by using _Target OR _This. If _Target, assume
84986 * this binding is undefined. If _This, assumes this binding is _This, and
84987 * target is also _This. One property would then be enough.
84988 */
84989
84990 duk_hobject *target;
84991 duk_bool_t found;
84992
84995
84996 target = ((duk_hobjenv *) env)->target;
84997 DUK_ASSERT(target != NULL);
84998
84999 /* Target may be a Proxy or property may be an accessor, so we must
85000 * use an actual, Proxy-aware hasprop check here.
85001 *
85002 * out->holder is NOT set to the actual duk_hobject where the
85003 * property is found, but rather the object binding target object.
85004 */
85005
85006#if defined(DUK_USE_ES6_PROXY)
85007 if (DUK_UNLIKELY(DUK_HOBJECT_IS_PROXY(target))) {
85008 duk_tval tv_name;
85009 duk_tval tv_target_tmp;
85010
85011 DUK_ASSERT(name != NULL);
85012 DUK_TVAL_SET_STRING(&tv_name, name);
85013 DUK_TVAL_SET_OBJECT(&tv_target_tmp, target);
85014
85015 found = duk_hobject_hasprop(thr, &tv_target_tmp, &tv_name);
85016 } else
85017#endif /* DUK_USE_ES6_PROXY */
85018 {
85019 /* XXX: duk_hobject_hasprop() would be correct for
85020 * non-Proxy objects too, but it is about ~20-25%
85021 * slower at present so separate code paths for
85022 * Proxy and non-Proxy now.
85023 */
85024 found = duk_hobject_hasprop_raw(thr, target, name);
85025 }
85026
85027 if (found) {
85028 out->value = NULL; /* can't get value, may be accessor */
85029 out->attrs = 0; /* irrelevant when out->value == NULL */
85030 out->env = env;
85031 out->holder = target;
85032 out->has_this = ((duk_hobjenv *) env)->has_this;
85033
85034 DUK_DDD(DUK_DDDPRINT("duk__get_identifier_reference successful: "
85035 "name=%!O -> value=%!T, attrs=%ld, has_this=%ld, env=%!O, holder=%!O "
85036 "(object environment record)",
85037 (duk_heaphdr *) name,
85038 (duk_tval *) out->value,
85039 (long) out->attrs,
85040 (long) out->has_this,
85041 (duk_heaphdr *) out->env,
85042 (duk_heaphdr *) out->holder));
85043 return 1;
85044 }
85045 }
85046
85047 if (!parents) {
85048 DUK_DDD(DUK_DDDPRINT("duk__get_identifier_reference failed, no parent traversal "
85049 "(not found from first traversed env)"));
85050 goto fail_not_found;
85051 }
85052
85053 if (DUK_UNLIKELY(sanity-- == 0)) {
85055 DUK_WO_NORETURN(return 0;);
85056 }
85057 env = DUK_HOBJECT_GET_PROTOTYPE(thr->heap, env);
85058 }
85059
85060 /*
85061 * Not found (even in global object)
85062 */
85063
85064fail_not_found:
85065 return 0;
85066}
85067
85068/*
85069 * HASVAR: check identifier binding from a given environment record
85070 * without traversing its parents.
85071 *
85072 * This primitive is not exposed to user code as such, but is used
85073 * internally for e.g. declaration binding instantiation.
85074 *
85075 * See E5 Sections:
85076 * 10.2.1.1.1 HasBinding(N)
85077 * 10.2.1.2.1 HasBinding(N)
85078 *
85079 * Note: strictness has no bearing on this check. Hence we don't take
85080 * a 'strict' parameter.
85081 */
85082
85083#if 0 /*unused*/
85085duk_bool_t duk_js_hasvar_envrec(duk_hthread *thr,
85086 duk_hobject *env,
85087 duk_hstring *name) {
85089 duk_bool_t parents;
85090
85091 DUK_DDD(DUK_DDDPRINT("hasvar: thr=%p, env=%p, name=%!O "
85092 "(env -> %!dO)",
85093 (void *) thr, (void *) env, (duk_heaphdr *) name,
85094 (duk_heaphdr *) env));
85095
85096 DUK_ASSERT(thr != NULL);
85097 DUK_ASSERT(env != NULL);
85098 DUK_ASSERT(name != NULL);
85099
85102
85105
85106 /* lookup results is ignored */
85107 parents = 0;
85108 return duk__get_identifier_reference(thr, env, name, NULL, parents, &ref);
85109}
85110#endif
85111
85112/*
85113 * GETVAR
85114 *
85115 * See E5 Sections:
85116 * 11.1.2 Identifier Reference
85117 * 10.3.1 Identifier Resolution
85118 * 11.13.1 Simple Assignment [example of where the Reference is GetValue'd]
85119 * 8.7.1 GetValue (V)
85120 * 8.12.1 [[GetOwnProperty]] (P)
85121 * 8.12.2 [[GetProperty]] (P)
85122 * 8.12.3 [[Get]] (P)
85123 *
85124 * If 'throw' is true, always leaves two values on top of stack: [val this].
85125 *
85126 * If 'throw' is false, returns 0 if identifier cannot be resolved, and the
85127 * stack will be unaffected in this case. If identifier is resolved, returns
85128 * 1 and leaves [val this] on top of stack.
85129 *
85130 * Note: the 'strict' flag of a reference returned by GetIdentifierReference
85131 * is ignored by GetValue. Hence we don't take a 'strict' parameter.
85132 *
85133 * The 'throw' flag is needed for implementing 'typeof' for an unreferenced
85134 * identifier. An unreference identifier in other contexts generates a
85135 * ReferenceError.
85136 */
85137
85141 duk_tval tv_tmp_obj;
85142 duk_tval tv_tmp_key;
85143 duk_bool_t parents;
85144
85145 DUK_DDD(DUK_DDDPRINT("getvar: thr=%p, env=%p, act=%p, name=%!O "
85146 "(env -> %!dO)",
85147 (void *) thr,
85148 (void *) env,
85149 (void *) act,
85150 (duk_heaphdr *) name,
85151 (duk_heaphdr *) env));
85152
85153 DUK_ASSERT(thr != NULL);
85154 DUK_ASSERT(name != NULL);
85155 /* env and act may be NULL */
85156
85157 DUK_STATS_INC(thr->heap, stats_getvar_all);
85158
85161
85162 parents = 1; /* follow parent chain */
85163 if (duk__get_identifier_reference(thr, env, name, act, parents, &ref)) {
85164 if (ref.value) {
85165 duk_push_tval(thr, ref.value);
85166 duk_push_undefined(thr);
85167 } else {
85168 DUK_ASSERT(ref.holder != NULL);
85170 /* ref.holder is safe across the getprop call (even
85171 * with side effects) because 'env' is reachable and
85172 * ref.holder is a direct heap pointer.
85173 */
85174
85175 DUK_TVAL_SET_OBJECT(&tv_tmp_obj, ref.holder);
85176 DUK_TVAL_SET_STRING(&tv_tmp_key, name);
85177 (void) duk_hobject_getprop(thr, &tv_tmp_obj, &tv_tmp_key); /* [value] */
85178
85179 if (ref.has_this) {
85180 duk_push_hobject(thr, ref.holder);
85181 } else {
85182 duk_push_undefined(thr);
85183 }
85184
85185 /* [value this] */
85186 }
85187
85188 return 1;
85189 } else {
85190 if (throw_flag) {
85191 DUK_ERROR_FMT1(thr,
85193 "identifier '%s' undefined",
85194 (const char *) DUK_HSTRING_GET_DATA(name));
85195 DUK_WO_NORETURN(return 0;);
85196 }
85197
85198 return 0;
85199 }
85200}
85201
85204 return duk__getvar_helper(thr, env, NULL, name, throw_flag);
85205}
85206
85209 DUK_ASSERT(act != NULL);
85210 return duk__getvar_helper(thr, act->lex_env, act, name, throw_flag);
85211}
85212
85213/*
85214 * PUTVAR
85215 *
85216 * See E5 Sections:
85217 * 11.1.2 Identifier Reference
85218 * 10.3.1 Identifier Resolution
85219 * 11.13.1 Simple Assignment [example of where the Reference is PutValue'd]
85220 * 8.7.2 PutValue (V,W) [see especially step 3.b, undefined -> automatic global in non-strict mode]
85221 * 8.12.4 [[CanPut]] (P)
85222 * 8.12.5 [[Put]] (P)
85223 *
85224 * Note: may invalidate any valstack (or object) duk_tval pointers because
85225 * putting a value may reallocate any object or any valstack. Caller beware.
85226 */
85227
85230 duk_hobject *env,
85231 duk_activation *act,
85232 duk_hstring *name,
85233 duk_tval *val,
85234 duk_bool_t strict) {
85236 duk_tval tv_tmp_val;
85237 duk_tval tv_tmp_obj;
85238 duk_tval tv_tmp_key;
85239 duk_bool_t parents;
85240
85241 DUK_STATS_INC(thr->heap, stats_putvar_all);
85242
85243 DUK_DDD(DUK_DDDPRINT("putvar: thr=%p, env=%p, act=%p, name=%!O, val=%p, strict=%ld "
85244 "(env -> %!dO, val -> %!T)",
85245 (void *) thr,
85246 (void *) env,
85247 (void *) act,
85248 (duk_heaphdr *) name,
85249 (void *) val,
85250 (long) strict,
85251 (duk_heaphdr *) env,
85252 (duk_tval *) val));
85253
85254 DUK_ASSERT(thr != NULL);
85255 DUK_ASSERT(name != NULL);
85256 DUK_ASSERT(val != NULL);
85257 /* env and act may be NULL */
85258
85262
85263 DUK_TVAL_SET_TVAL(&tv_tmp_val, val); /* Stabilize. */
85264 val = NULL;
85265
85266 /*
85267 * In strict mode E5 protects 'eval' and 'arguments' from being
85268 * assigned to (or even declared anywhere). Attempt to do so
85269 * should result in a compile time SyntaxError. See the internal
85270 * design documentation for details.
85271 *
85272 * Thus, we should never come here, run-time, for strict code,
85273 * and name 'eval' or 'arguments'.
85274 */
85275
85276 DUK_ASSERT(!strict || (name != DUK_HTHREAD_STRING_EVAL(thr) && name != DUK_HTHREAD_STRING_LC_ARGUMENTS(thr)));
85277
85278 /*
85279 * Lookup variable and update in-place if found.
85280 */
85281
85282 parents = 1; /* follow parent chain */
85283
85284 if (duk__get_identifier_reference(thr, env, name, act, parents, &ref)) {
85285 if (ref.value && (ref.attrs & DUK_PROPDESC_FLAG_WRITABLE)) {
85286 /* Update duk_tval in-place if pointer provided and the
85287 * property is writable. If the property is not writable
85288 * (immutable binding), use duk_hobject_putprop() which
85289 * will respect mutability.
85290 */
85291 duk_tval *tv_val;
85292
85293 tv_val = ref.value;
85294 DUK_ASSERT(tv_val != NULL);
85295 DUK_TVAL_SET_TVAL_UPDREF(thr, tv_val, &tv_tmp_val); /* side effects */
85296
85297 /* ref.value invalidated here */
85298 } else {
85299 DUK_ASSERT(ref.holder != NULL);
85300
85301 DUK_TVAL_SET_OBJECT(&tv_tmp_obj, ref.holder);
85302 DUK_TVAL_SET_STRING(&tv_tmp_key, name);
85303 (void) duk_hobject_putprop(thr, &tv_tmp_obj, &tv_tmp_key, &tv_tmp_val, strict);
85304
85305 /* ref.value invalidated here */
85306 }
85307
85308 return;
85309 }
85310
85311 /*
85312 * Not found: write to global object (non-strict) or ReferenceError
85313 * (strict); see E5 Section 8.7.2, step 3.
85314 */
85315
85316 if (strict) {
85317 DUK_DDD(DUK_DDDPRINT("identifier binding not found, strict => reference error"));
85318 DUK_ERROR_FMT1(thr,
85320 "identifier '%s' undefined",
85321 (const char *) DUK_HSTRING_GET_DATA(name));
85322 DUK_WO_NORETURN(return;);
85323 }
85324
85325 DUK_DDD(DUK_DDDPRINT("identifier binding not found, not strict => set to global"));
85326
85327 DUK_TVAL_SET_OBJECT(&tv_tmp_obj, thr->builtins[DUK_BIDX_GLOBAL]);
85328 DUK_TVAL_SET_STRING(&tv_tmp_key, name);
85329 (void) duk_hobject_putprop(thr, &tv_tmp_obj, &tv_tmp_key, &tv_tmp_val, 0); /* 0 = no throw */
85330
85331 /* NB: 'val' may be invalidated here because put_value may realloc valstack,
85332 * caller beware.
85333 */
85334}
85335
85337void duk_js_putvar_envrec(duk_hthread *thr, duk_hobject *env, duk_hstring *name, duk_tval *val, duk_bool_t strict) {
85338 duk__putvar_helper(thr, env, NULL, name, val, strict);
85339}
85340
85343 DUK_ASSERT(act != NULL);
85344 duk__putvar_helper(thr, act->lex_env, act, name, val, strict);
85345}
85346
85347/*
85348 * DELVAR
85349 *
85350 * See E5 Sections:
85351 * 11.4.1 The delete operator
85352 * 10.2.1.1.5 DeleteBinding (N) [declarative environment record]
85353 * 10.2.1.2.5 DeleteBinding (N) [object environment record]
85354 *
85355 * Variable bindings established inside eval() are deletable (configurable),
85356 * other bindings are not, including variables declared in global level.
85357 * Registers are always non-deletable, and the deletion of other bindings
85358 * is controlled by the configurable flag.
85359 *
85360 * For strict mode code, the 'delete' operator should fail with a compile
85361 * time SyntaxError if applied to identifiers. Hence, no strict mode
85362 * run-time deletion of identifiers should ever happen. This function
85363 * should never be called from strict mode code!
85364 */
85365
85369 duk_bool_t parents;
85370
85371 DUK_DDD(DUK_DDDPRINT("delvar: thr=%p, env=%p, act=%p, name=%!O "
85372 "(env -> %!dO)",
85373 (void *) thr,
85374 (void *) env,
85375 (void *) act,
85376 (duk_heaphdr *) name,
85377 (duk_heaphdr *) env));
85378
85379 DUK_ASSERT(thr != NULL);
85380 DUK_ASSERT(name != NULL);
85381 /* env and act may be NULL */
85382
85385 parents = 1; /* follow parent chain */
85386
85387 if (duk__get_identifier_reference(thr, env, name, act, parents, &ref)) {
85388 if (ref.value && !(ref.attrs & DUK_PROPDESC_FLAG_CONFIGURABLE)) {
85389 /* Identifier found in registers (always non-deletable)
85390 * or declarative environment record and non-configurable.
85391 */
85392 return 0;
85393 }
85394 DUK_ASSERT(ref.holder != NULL);
85395
85396 return duk_hobject_delprop_raw(thr, ref.holder, name, 0);
85397 }
85398
85399 /*
85400 * Not found (even in global object).
85401 *
85402 * In non-strict mode this is a silent SUCCESS (!), see E5 Section 11.4.1,
85403 * step 3.b. In strict mode this case is a compile time SyntaxError so
85404 * we should not come here.
85405 */
85406
85407 DUK_DDD(DUK_DDDPRINT("identifier to be deleted not found: name=%!O "
85408 "(treated as silent success)",
85409 (duk_heaphdr *) name));
85410 return 1;
85411}
85412
85413#if 0 /*unused*/
85415duk_bool_t duk_js_delvar_envrec(duk_hthread *thr,
85416 duk_hobject *env,
85417 duk_hstring *name) {
85418 return duk__delvar_helper(thr, env, NULL, name);
85419}
85420#endif
85421
85424 DUK_ASSERT(act != NULL);
85425 return duk__delvar_helper(thr, act->lex_env, act, name);
85426}
85427
85428/*
85429 * DECLVAR
85430 *
85431 * See E5 Sections:
85432 * 10.4.3 Entering Function Code
85433 * 10.5 Declaration Binding Instantion
85434 * 12.2 Variable Statement
85435 * 11.1.2 Identifier Reference
85436 * 10.3.1 Identifier Resolution
85437 *
85438 * Variable declaration behavior is mainly discussed in Section 10.5,
85439 * and is not discussed in the execution semantics (Sections 11-13).
85441 * Conceptually declarations happen when code (global, eval, function)
85442 * is entered, before any user code is executed. In practice, register-
85443 * bound identifiers are 'declared' automatically (by virtue of being
85444 * allocated to registers with the initial value 'undefined'). Other
85445 * identifiers are declared in the function prologue with this primitive.
85446 *
85447 * Since non-register bindings eventually back to an internal object's
85448 * properties, the 'prop_flags' argument is used to specify binding
85449 * type:
85450 *
85451 * - Immutable binding: set DUK_PROPDESC_FLAG_WRITABLE to false
85452 * - Non-deletable binding: set DUK_PROPDESC_FLAG_CONFIGURABLE to false
85453 * - The flag DUK_PROPDESC_FLAG_ENUMERABLE should be set, although it
85454 * doesn't really matter for internal objects
85455 *
85456 * All bindings are non-deletable mutable bindings except:
85457 *
85458 * - Declarations in eval code (mutable, deletable)
85459 * - 'arguments' binding in strict function code (immutable)
85460 * - Function name binding of a function expression (immutable)
85461 *
85462 * Declarations may go to declarative environment records (always
85463 * so for functions), but may also go to object environment records
85464 * (e.g. global code). The global object environment has special
85465 * behavior when re-declaring a function (but not a variable); see
85466 * E5.1 specification, Section 10.5, step 5.e.
85467 *
85468 * Declarations always go to the 'top-most' environment record, i.e.
85469 * we never check the record chain. It's not an error even if a
85470 * property (even an immutable or non-deletable one) of the same name
85471 * already exists.
85472 *
85473 * If a declared variable already exists, its value needs to be updated
85474 * (if possible). Returns 1 if a PUTVAR needs to be done by the caller;
85475 * otherwise returns 0.
85476 */
85477
85480 duk_hobject *env,
85481 duk_hstring *name,
85482 duk_tval *val,
85483 duk_small_uint_t prop_flags,
85484 duk_bool_t is_func_decl) {
85485 duk_hobject *holder;
85486 duk_bool_t parents;
85488 duk_tval *tv;
85489
85490 DUK_DDD(DUK_DDDPRINT("declvar: thr=%p, env=%p, name=%!O, val=%!T, prop_flags=0x%08lx, is_func_decl=%ld "
85491 "(env -> %!iO)",
85492 (void *) thr,
85493 (void *) env,
85494 (duk_heaphdr *) name,
85495 (duk_tval *) val,
85496 (unsigned long) prop_flags,
85497 (unsigned int) is_func_decl,
85498 (duk_heaphdr *) env));
85499
85500 DUK_ASSERT(thr != NULL);
85501 DUK_ASSERT(env != NULL);
85502 DUK_ASSERT(name != NULL);
85503 DUK_ASSERT(val != NULL);
85504
85505 /* Note: in strict mode the compiler should reject explicit
85506 * declaration of 'eval' or 'arguments'. However, internal
85507 * bytecode may declare 'arguments' in the function prologue.
85508 * We don't bother checking (or asserting) for these now.
85509 */
85510
85511 /* Note: val is a stable duk_tval pointer. The caller makes
85512 * a value copy into its stack frame, so 'tv_val' is not subject
85513 * to side effects here.
85514 */
85515
85516 /*
85517 * Check whether already declared.
85518 *
85519 * We need to check whether the binding exists in the environment
85520 * without walking its parents. However, we still need to check
85521 * register-bound identifiers and the prototype chain of an object
85522 * environment target object.
85523 */
85524
85525 parents = 0; /* just check 'env' */
85526 if (duk__get_identifier_reference(thr, env, name, NULL, parents, &ref)) {
85527 duk_int_t e_idx;
85528 duk_int_t h_idx;
85529 duk_small_uint_t flags;
85530
85531 /*
85532 * Variable already declared, ignore re-declaration.
85533 * The only exception is the updated behavior of E5.1 for
85534 * global function declarations, E5.1 Section 10.5, step 5.e.
85535 * This behavior does not apply to global variable declarations.
85536 */
85537
85538 if (!(is_func_decl && env == thr->builtins[DUK_BIDX_GLOBAL_ENV])) {
85539 DUK_DDD(DUK_DDDPRINT("re-declare a binding, ignoring"));
85540 return 1; /* 1 -> needs a PUTVAR */
85541 }
85542
85543 /*
85544 * Special behavior in E5.1.
85545 *
85546 * Note that even though parents == 0, the conflicting property
85547 * may be an inherited property (currently our global object's
85548 * prototype is Object.prototype). Step 5.e first operates on
85549 * the existing property (which is potentially in an ancestor)
85550 * and then defines a new property in the global object (and
85551 * never modifies the ancestor).
85552 *
85553 * Also note that this logic would become even more complicated
85554 * if the conflicting property might be a virtual one. Object
85555 * prototype has no virtual properties, though.
85556 *
85557 * XXX: this is now very awkward, rework.
85558 */
85559
85560 DUK_DDD(DUK_DDDPRINT("re-declare a function binding in global object, "
85561 "updated E5.1 processing"));
85562
85563 DUK_ASSERT(ref.holder != NULL);
85564 holder = ref.holder;
85565
85566 /* holder will be set to the target object, not the actual object
85567 * where the property was found (see duk__get_identifier_reference()).
85568 */
85570 DUK_ASSERT(!DUK_HOBJECT_HAS_EXOTIC_ARRAY(holder)); /* global object doesn't have array part */
85571
85572 /* XXX: use a helper for prototype traversal; no loop check here */
85573 /* must be found: was found earlier, and cannot be inherited */
85574 for (;;) {
85575 DUK_ASSERT(holder != NULL);
85576 if (duk_hobject_find_entry(thr->heap, holder, name, &e_idx, &h_idx)) {
85577 DUK_ASSERT(e_idx >= 0);
85578 break;
85579 }
85580 /* SCANBUILD: NULL pointer dereference, doesn't actually trigger,
85581 * asserted above.
85582 */
85583 holder = DUK_HOBJECT_GET_PROTOTYPE(thr->heap, holder);
85584 }
85585 DUK_ASSERT(holder != NULL);
85586 DUK_ASSERT(e_idx >= 0);
85587 /* SCANBUILD: scan-build produces a NULL pointer dereference warning
85588 * below; it never actually triggers because holder is actually never
85589 * NULL.
85590 */
85591
85592 /* ref.holder is global object, holder is the object with the
85593 * conflicting property.
85594 */
85595
85596 flags = DUK_HOBJECT_E_GET_FLAGS(thr->heap, holder, e_idx);
85597 if (!(flags & DUK_PROPDESC_FLAG_CONFIGURABLE)) {
85598 if (flags & DUK_PROPDESC_FLAG_ACCESSOR) {
85599 DUK_DDD(DUK_DDDPRINT("existing property is a non-configurable "
85600 "accessor -> reject"));
85601 goto fail_existing_attributes;
85602 }
85603 if (!((flags & DUK_PROPDESC_FLAG_WRITABLE) && (flags & DUK_PROPDESC_FLAG_ENUMERABLE))) {
85604 DUK_DDD(DUK_DDDPRINT("existing property is a non-configurable "
85605 "plain property which is not writable and "
85606 "enumerable -> reject"));
85607 goto fail_existing_attributes;
85608 }
85609
85610 DUK_DDD(DUK_DDDPRINT("existing property is not configurable but "
85611 "is plain, enumerable, and writable -> "
85612 "allow redeclaration"));
85613 }
85614
85615 if (holder == ref.holder) {
85616 /* XXX: if duk_hobject_define_property_internal() was updated
85617 * to handle a pre-existing accessor property, this would be
85618 * a simple call (like for the ancestor case).
85619 */
85620 DUK_DDD(DUK_DDDPRINT("redefine, offending property in global object itself"));
85621
85622 if (flags & DUK_PROPDESC_FLAG_ACCESSOR) {
85623 duk_hobject *tmp;
85624
85625 tmp = DUK_HOBJECT_E_GET_VALUE_GETTER(thr->heap, holder, e_idx);
85626 DUK_HOBJECT_E_SET_VALUE_GETTER(thr->heap, holder, e_idx, NULL);
85628 DUK_UNREF(tmp);
85629 tmp = DUK_HOBJECT_E_GET_VALUE_SETTER(thr->heap, holder, e_idx);
85630 DUK_HOBJECT_E_SET_VALUE_SETTER(thr->heap, holder, e_idx, NULL);
85632 DUK_UNREF(tmp);
85633 } else {
85634 tv = DUK_HOBJECT_E_GET_VALUE_TVAL_PTR(thr->heap, holder, e_idx);
85636 }
85637
85638 /* Here val would be potentially invalid if we didn't make
85639 * a value copy at the caller.
85640 */
85641
85642 tv = DUK_HOBJECT_E_GET_VALUE_TVAL_PTR(thr->heap, holder, e_idx);
85643 DUK_TVAL_SET_TVAL(tv, val);
85644 DUK_TVAL_INCREF(thr, tv);
85645 DUK_HOBJECT_E_SET_FLAGS(thr->heap, holder, e_idx, prop_flags);
85646
85647 DUK_DDD(DUK_DDDPRINT("updated global binding, final result: "
85648 "value -> %!T, prop_flags=0x%08lx",
85649 (duk_tval *) DUK_HOBJECT_E_GET_VALUE_TVAL_PTR(thr->heap, holder, e_idx),
85650 (unsigned long) prop_flags));
85651 } else {
85652 DUK_DDD(DUK_DDDPRINT("redefine, offending property in ancestor"));
85653
85655 duk_push_tval(thr, val);
85656 duk_hobject_define_property_internal(thr, ref.holder, name, prop_flags);
85657 }
85658
85659 return 0;
85660 }
85661
85662 /*
85663 * Not found (in registers or record objects). Declare
85664 * to current variable environment.
85665 */
85666
85667 /*
85668 * Get holder object
85669 */
85670
85673 holder = env;
85674 } else {
85676 holder = ((duk_hobjenv *) env)->target;
85677 DUK_ASSERT(holder != NULL);
85678 }
85679
85680 /*
85681 * Define new property
85682 *
85683 * Note: this may fail if the holder is not extensible.
85684 */
85685
85686 /* XXX: this is awkward as we use an internal method which doesn't handle
85687 * extensibility etc correctly. Basically we'd want to do a [[DefineOwnProperty]]
85688 * or Object.defineProperty() here.
85689 */
85690
85691 if (!DUK_HOBJECT_HAS_EXTENSIBLE(holder)) {
85692 goto fail_not_extensible;
85693 }
85694
85695 duk_push_hobject(thr, holder);
85696 duk_push_hstring(thr, name);
85697 duk_push_tval(thr, val);
85698 duk_xdef_prop(thr, -3, prop_flags); /* [holder name val] -> [holder] */
85699 duk_pop_unsafe(thr);
85700
85701 return 0;
85702
85703fail_existing_attributes:
85704fail_not_extensible:
85705 DUK_ERROR_TYPE(thr, "declaration failed");
85706 DUK_WO_NORETURN(return 0;);
85707}
85708
85711 duk_activation *act,
85712 duk_hstring *name,
85713 duk_tval *val,
85714 duk_small_uint_t prop_flags,
85715 duk_bool_t is_func_decl) {
85716 duk_hobject *env;
85717 duk_tval tv_val_copy;
85718
85719 DUK_ASSERT(act != NULL);
85720
85721 /*
85722 * Make a value copy of the input val. This ensures that
85723 * side effects cannot invalidate the pointer.
85724 */
85725
85726 DUK_TVAL_SET_TVAL(&tv_val_copy, val);
85727 val = &tv_val_copy;
85728
85729 /*
85730 * Delayed env creation check
85731 */
85732
85733 if (!act->var_env) {
85734 DUK_ASSERT(act->lex_env == NULL);
85736 /* 'act' is a stable pointer, so still OK. */
85737 }
85738 DUK_ASSERT(act->lex_env != NULL);
85739 DUK_ASSERT(act->var_env != NULL);
85740
85741 env = act->var_env;
85742 DUK_ASSERT(env != NULL);
85744
85745 return duk__declvar_helper(thr, env, name, val, prop_flags, is_func_decl);
85746}
85747/*
85748 * Lexer for source files, ToNumber() string conversions, RegExp expressions,
85749 * and JSON.
85750 *
85751 * Provides a stream of ECMAScript tokens from an UTF-8/CESU-8 buffer. The
85752 * caller can also rewind the token stream into a certain position which is
85753 * needed by the compiler part for multi-pass scanning. Tokens are
85754 * represented as duk_token structures, and contain line number information.
85755 * Token types are identified with DUK_TOK_* defines.
85756 *
85757 * Characters are decoded into a fixed size lookup window consisting of
85758 * decoded Unicode code points, with window positions past the end of the
85759 * input filled with an invalid codepoint (-1). The tokenizer can thus
85760 * perform multiple character lookups efficiently and with few sanity
85761 * checks (such as access outside the end of the input), which keeps the
85762 * tokenization code small at the cost of performance.
85763 *
85764 * Character data in tokens, such as identifier names and string literals,
85765 * is encoded into CESU-8 format on-the-fly while parsing the token in
85766 * question. The string data is made reachable to garbage collection by
85767 * placing the token-related values in value stack entries allocated for
85768 * this purpose by the caller. The characters exist in Unicode code point
85769 * form only in the fixed size lookup window, which keeps character data
85770 * expansion (of especially ASCII data) low.
85771 *
85772 * Token parsing supports the full range of Unicode characters as described
85773 * in the E5 specification. Parsing has been optimized for ASCII characters
85774 * because ordinary ECMAScript code consists almost entirely of ASCII
85775 * characters. Matching of complex Unicode codepoint sets (such as in the
85776 * IdentifierStart and IdentifierPart productions) is optimized for size,
85777 * and is done using a linear scan of a bit-packed list of ranges. This is
85778 * very slow, but should never be entered unless the source code actually
85779 * contains Unicode characters.
85780 *
85781 * ECMAScript tokenization is partially context sensitive. First,
85782 * additional future reserved words are recognized in strict mode (see E5
85783 * Section 7.6.1.2). Second, a forward slash character ('/') can be
85784 * recognized either as starting a RegExp literal or as a division operator,
85785 * depending on context. The caller must provide necessary context flags
85786 * when requesting a new token.
85788 * Future work:
85789 *
85790 * * Make line number tracking optional, as it consumes space.
85792 * * Add a feature flag for disabling UTF-8 decoding of input, as most
85793 * source code is ASCII. Because of Unicode escapes written in ASCII,
85794 * this does not allow Unicode support to be removed from e.g.
85795 * duk_unicode_is_identifier_start() nor does it allow removal of CESU-8
85796 * encoding of e.g. string literals.
85798 * * Add a feature flag for disabling Unicode compliance of e.g. identifier
85799 * names. This allows for a build more than a kilobyte smaller, because
85800 * Unicode ranges needed by duk_unicode_is_identifier_start() and
85801 * duk_unicode_is_identifier_part() can be dropped. String literals
85802 * should still be allowed to contain escaped Unicode, so this still does
85803 * not allow removal of CESU-8 encoding of e.g. string literals.
85804 *
85805 * * Character lookup tables for codepoints above BMP could be stripped.
85807 * * Strictly speaking, E5 specification requires that source code consists
85808 * of 16-bit code units, and if not, must be conceptually converted to
85809 * that format first. The current lexer processes Unicode code points
85810 * and allows characters outside the BMP. These should be converted to
85811 * surrogate pairs while reading the source characters into the window,
85812 * not after tokens have been formed (as is done now). However, the fix
85813 * is not trivial because two characters are decoded from one codepoint.
85814 *
85815 * * Optimize for speed as well as size. Large if-else ladders are (at
85816 * least potentially) slow.
85817 */
85818
85819/* #include duk_internal.h -> already included */
85820
85821/*
85822 * Various defines and file specific helper macros
85823 */
85824
85825#define DUK__MAX_RE_DECESC_DIGITS 9
85826#define DUK__MAX_RE_QUANT_DIGITS 9 /* Does not allow e.g. 2**31-1, but one more would allow overflows of u32. */
85827
85828/* whether to use macros or helper function depends on call count */
85829#define DUK__ISDIGIT(x) ((x) >= DUK_ASC_0 && (x) <= DUK_ASC_9)
85830#define DUK__ISHEXDIGIT(x) duk__is_hex_digit((x))
85831#define DUK__ISOCTDIGIT(x) ((x) >= DUK_ASC_0 && (x) <= DUK_ASC_7)
85832#define DUK__ISDIGIT03(x) ((x) >= DUK_ASC_0 && (x) <= DUK_ASC_3)
85833#define DUK__ISDIGIT47(x) ((x) >= DUK_ASC_4 && (x) <= DUK_ASC_7)
85834
85835/* lexer character window helpers */
85836#define DUK__LOOKUP(lex_ctx, idx) ((lex_ctx)->window[(idx)].codepoint)
85837#define DUK__ADVANCECHARS(lex_ctx, count) duk__advance_chars((lex_ctx), (count))
85838#define DUK__ADVANCEBYTES(lex_ctx, count) duk__advance_bytes((lex_ctx), (count))
85839#define DUK__INITBUFFER(lex_ctx) duk__initbuffer((lex_ctx))
85840#define DUK__APPENDBUFFER(lex_ctx, x) duk__appendbuffer((lex_ctx), (duk_codepoint_t) (x))
85841#define DUK__APPENDBUFFER_ASCII(lex_ctx, x) duk__appendbuffer_ascii((lex_ctx), (duk_codepoint_t) (x))
85842
85843/* lookup shorthands (note: assume context variable is named 'lex_ctx') */
85844#define DUK__L0() DUK__LOOKUP(lex_ctx, 0)
85845#define DUK__L1() DUK__LOOKUP(lex_ctx, 1)
85846#define DUK__L2() DUK__LOOKUP(lex_ctx, 2)
85847#define DUK__L3() DUK__LOOKUP(lex_ctx, 3)
85848#define DUK__L4() DUK__LOOKUP(lex_ctx, 4)
85849#define DUK__L5() DUK__LOOKUP(lex_ctx, 5)
85850
85851/* packed advance/token number macro used by multiple functions */
85852#define DUK__ADVTOK(advbytes, tok) ((((advbytes) * sizeof(duk_lexer_codepoint)) << 8) + (tok))
85853
85854/*
85855 * Advance lookup window by N characters, filling in new characters as
85856 * necessary. After returning caller is guaranteed a character window of
85857 * at least DUK_LEXER_WINDOW_SIZE characters.
85858 *
85859 * The main function duk__advance_bytes() is called at least once per every
85860 * token so it has a major lexer/compiler performance impact. There are two
85861 * variants for the main duk__advance_bytes() algorithm: a sliding window
85862 * approach which is slightly faster at the cost of larger code footprint,
85863 * and a simple copying one.
85864 *
85865 * Decoding directly from the source string would be another lexing option.
85866 * But the lookup window based approach has the advantage of hiding the
85867 * source string and its encoding effectively which gives more flexibility
85868 * going forward to e.g. support chunked streaming of source from flash.
85869 *
85870 * Decodes UTF-8/CESU-8 leniently with support for code points from U+0000 to
85871 * U+10FFFF, causing an error if the input is unparseable. Leniency means:
85872 *
85873 * * Unicode code point validation is intentionally not performed,
85874 * except to check that the codepoint does not exceed 0x10ffff.
85875 *
85876 * * In particular, surrogate pairs are allowed and not combined, which
85877 * allows source files to represent all SourceCharacters with CESU-8.
85878 * Broken surrogate pairs are allowed, as ECMAScript does not mandate
85879 * their validation.
85880 *
85881 * * Allow non-shortest UTF-8 encodings.
85882 *
85883 * Leniency here causes few security concerns because all character data is
85884 * decoded into Unicode codepoints before lexer processing, and is then
85885 * re-encoded into CESU-8. The source can be parsed as strict UTF-8 with
85886 * a compiler option. However, ECMAScript source characters include -all-
85887 * 16-bit unsigned integer codepoints, so leniency seems to be appropriate.
85888 *
85889 * Note that codepoints above the BMP are not strictly SourceCharacters,
85890 * but the lexer still accepts them as such. Before ending up in a string
85891 * or an identifier name, codepoints above BMP are converted into surrogate
85892 * pairs and then CESU-8 encoded, resulting in 16-bit Unicode data as
85893 * expected by ECMAScript.
85894 *
85895 * An alternative approach to dealing with invalid or partial sequences
85896 * would be to skip them and replace them with e.g. the Unicode replacement
85897 * character U+FFFD. This has limited utility because a replacement character
85898 * will most likely cause a parse error, unless it occurs inside a string.
85899 * Further, ECMAScript source is typically pure ASCII.
85900 *
85901 * See:
85902 *
85903 * http://en.wikipedia.org/wiki/UTF-8
85904 * http://en.wikipedia.org/wiki/CESU-8
85905 * http://tools.ietf.org/html/rfc3629
85906 * http://en.wikipedia.org/wiki/UTF-8#Invalid_byte_sequences
85907 *
85908 * Future work:
85909 *
85910 * * Reject other invalid Unicode sequences (see Wikipedia entry for examples)
85911 * in strict UTF-8 mode.
85912 *
85913 * * Size optimize. An attempt to use a 16-byte lookup table for the first
85914 * byte resulted in a code increase though.
85915 *
85916 * * Is checking against maximum 0x10ffff really useful? 4-byte encoding
85917 * imposes a certain limit anyway.
85918 *
85919 * * Support chunked streaming of source code. Can be implemented either
85920 * by streaming chunks of bytes or chunks of codepoints.
85921 */
85922
85923#if defined(DUK_USE_LEXER_SLIDING_WINDOW)
85924DUK_LOCAL void duk__fill_lexer_buffer(duk_lexer_ctx *lex_ctx, duk_small_uint_t start_offset_bytes) {
85925 duk_lexer_codepoint *cp, *cp_end;
85927 duk_small_uint_t contlen;
85928 const duk_uint8_t *p, *p_end;
85929#if defined(DUK_USE_STRICT_UTF8_SOURCE)
85930 duk_ucodepoint_t mincp;
85931#endif
85932 duk_int_t input_line;
85933
85934 /* Use temporaries and update lex_ctx only when finished. */
85935 input_line = lex_ctx->input_line;
85936 p = lex_ctx->input + lex_ctx->input_offset;
85937 p_end = lex_ctx->input + lex_ctx->input_length;
85938
85939 cp = (duk_lexer_codepoint *) (void *) ((duk_uint8_t *) lex_ctx->buffer + start_offset_bytes);
85940 cp_end = lex_ctx->buffer + DUK_LEXER_BUFFER_SIZE;
85941
85942 for (; cp != cp_end; cp++) {
85943 cp->offset = (duk_size_t) (p - lex_ctx->input);
85944 cp->line = input_line;
85945
85946 /* XXX: potential issue with signed pointers, p_end < p. */
85947 if (DUK_UNLIKELY(p >= p_end)) {
85948 /* If input_offset were assigned a negative value, it would
85949 * result in a large positive value. Most likely it would be
85950 * larger than input_length and be caught here. In any case
85951 * no memory unsafe behavior would happen.
85952 */
85953 cp->codepoint = -1;
85954 continue;
85955 }
85956
85957 x = (duk_ucodepoint_t) (*p++);
85958
85959 /* Fast path. */
85960
85961 if (DUK_LIKELY(x < 0x80UL)) {
85962 DUK_ASSERT(x != 0x2028UL && x != 0x2029UL); /* not LS/PS */
85963 if (DUK_UNLIKELY(x <= 0x000dUL)) {
85964 if ((x == 0x000aUL) || ((x == 0x000dUL) && (p >= p_end || *p != 0x000aUL))) {
85965 /* lookup for 0x000a above assumes shortest encoding now */
85966
85967 /* E5 Section 7.3, treat the following as newlines:
85968 * LF
85969 * CR [not followed by LF]
85970 * LS
85971 * PS
85972 *
85973 * For CR LF, CR is ignored if it is followed by LF, and the LF will bump
85974 * the line number.
85975 */
85976 input_line++;
85977 }
85978 }
85979
85980 cp->codepoint = (duk_codepoint_t) x;
85981 continue;
85982 }
85983
85984 /* Slow path. */
85985
85986 if (x < 0xc0UL) {
85987 /* 10xx xxxx -> invalid */
85988 goto error_encoding;
85989 } else if (x < 0xe0UL) {
85990 /* 110x xxxx 10xx xxxx */
85991 contlen = 1;
85992#if defined(DUK_USE_STRICT_UTF8_SOURCE)
85993 mincp = 0x80UL;
85994#endif
85995 x = x & 0x1fUL;
85996 } else if (x < 0xf0UL) {
85997 /* 1110 xxxx 10xx xxxx 10xx xxxx */
85998 contlen = 2;
85999#if defined(DUK_USE_STRICT_UTF8_SOURCE)
86000 mincp = 0x800UL;
86001#endif
86002 x = x & 0x0fUL;
86003 } else if (x < 0xf8UL) {
86004 /* 1111 0xxx 10xx xxxx 10xx xxxx 10xx xxxx */
86005 contlen = 3;
86006#if defined(DUK_USE_STRICT_UTF8_SOURCE)
86007 mincp = 0x10000UL;
86008#endif
86009 x = x & 0x07UL;
86010 } else {
86011 /* no point in supporting encodings of 5 or more bytes */
86012 goto error_encoding;
86013 }
86014
86015 DUK_ASSERT(p_end >= p);
86016 if ((duk_size_t) contlen > (duk_size_t) (p_end - p)) {
86017 goto error_clipped;
86018 }
86019
86020 while (contlen > 0) {
86022 y = *p++;
86023 if ((y & 0xc0U) != 0x80U) {
86024 /* check that byte has the form 10xx xxxx */
86025 goto error_encoding;
86026 }
86027 x = x << 6;
86028 x += y & 0x3fUL;
86029 contlen--;
86030 }
86031
86032 /* check final character validity */
86033
86034 if (x > 0x10ffffUL) {
86035 goto error_encoding;
86036 }
86037#if defined(DUK_USE_STRICT_UTF8_SOURCE)
86038 if (x < mincp || (x >= 0xd800UL && x <= 0xdfffUL) || x == 0xfffeUL) {
86039 goto error_encoding;
86040 }
86041#endif
86042
86043 DUK_ASSERT(x != 0x000aUL && x != 0x000dUL);
86044 if ((x == 0x2028UL) || (x == 0x2029UL)) {
86045 input_line++;
86046 }
86047
86048 cp->codepoint = (duk_codepoint_t) x;
86049 }
86050
86051 lex_ctx->input_offset = (duk_size_t) (p - lex_ctx->input);
86052 lex_ctx->input_line = input_line;
86053 return;
86054
86055error_clipped: /* clipped codepoint */
86056error_encoding: /* invalid codepoint encoding or codepoint */
86057 lex_ctx->input_offset = (duk_size_t) (p - lex_ctx->input);
86058 lex_ctx->input_line = input_line;
86059
86061 DUK_WO_NORETURN(return;);
86062}
86063
86064DUK_LOCAL void duk__advance_bytes(duk_lexer_ctx *lex_ctx, duk_small_uint_t count_bytes) {
86065 duk_small_uint_t used_bytes, avail_bytes;
86066
86067 DUK_ASSERT_DISABLE(count_bytes >= 0); /* unsigned */
86069 DUK_ASSERT(lex_ctx->window >= lex_ctx->buffer);
86070 DUK_ASSERT(lex_ctx->window < lex_ctx->buffer + DUK_LEXER_BUFFER_SIZE);
86071 DUK_ASSERT((duk_uint8_t *) lex_ctx->window + count_bytes <=
86072 (duk_uint8_t *) lex_ctx->buffer + DUK_LEXER_BUFFER_SIZE * sizeof(duk_lexer_codepoint));
86073
86074 /* Zero 'count' is also allowed to make call sites easier.
86075 * Arithmetic in bytes generates better code in GCC.
86076 */
86077
86078 lex_ctx->window = (duk_lexer_codepoint *) (void *) ((duk_uint8_t *) lex_ctx->window + count_bytes); /* avoid multiply */
86079 used_bytes = (duk_small_uint_t) ((duk_uint8_t *) lex_ctx->window - (duk_uint8_t *) lex_ctx->buffer);
86080 avail_bytes = DUK_LEXER_BUFFER_SIZE * sizeof(duk_lexer_codepoint) - used_bytes;
86081 if (avail_bytes < (duk_small_uint_t) (DUK_LEXER_WINDOW_SIZE * sizeof(duk_lexer_codepoint))) {
86082 /* Not enough data to provide a full window, so "scroll" window to
86083 * start of buffer and fill up the rest.
86084 */
86085 duk_memmove((void *) lex_ctx->buffer, (const void *) lex_ctx->window, (size_t) avail_bytes);
86086 lex_ctx->window = lex_ctx->buffer;
86087 duk__fill_lexer_buffer(lex_ctx, avail_bytes);
86088 }
86089}
86090
86092 lex_ctx->window = lex_ctx->buffer;
86093 duk__fill_lexer_buffer(lex_ctx, 0);
86094}
86095#else /* DUK_USE_LEXER_SLIDING_WINDOW */
86096DUK_LOCAL duk_codepoint_t duk__read_char(duk_lexer_ctx *lex_ctx) {
86098 duk_small_uint_t len;
86100 const duk_uint8_t *p;
86101#if defined(DUK_USE_STRICT_UTF8_SOURCE)
86102 duk_ucodepoint_t mincp;
86103#endif
86104 duk_size_t input_offset;
86105
86106 input_offset = lex_ctx->input_offset;
86107 if (DUK_UNLIKELY(input_offset >= lex_ctx->input_length)) {
86108 /* If input_offset were assigned a negative value, it would
86109 * result in a large positive value. Most likely it would be
86110 * larger than input_length and be caught here. In any case
86111 * no memory unsafe behavior would happen.
86112 */
86113 return -1;
86114 }
86115
86116 p = lex_ctx->input + input_offset;
86117 x = (duk_ucodepoint_t) (*p);
86118
86119 if (DUK_LIKELY(x < 0x80UL)) {
86120 /* 0xxx xxxx -> fast path */
86121
86122 /* input offset tracking */
86123 lex_ctx->input_offset++;
86124
86125 DUK_ASSERT(x != 0x2028UL && x != 0x2029UL); /* not LS/PS */
86126 if (DUK_UNLIKELY(x <= 0x000dUL)) {
86127 if ((x == 0x000aUL) || ((x == 0x000dUL) && (lex_ctx->input_offset >= lex_ctx->input_length ||
86128 lex_ctx->input[lex_ctx->input_offset] != 0x000aUL))) {
86129 /* lookup for 0x000a above assumes shortest encoding now */
86130
86131 /* E5 Section 7.3, treat the following as newlines:
86132 * LF
86133 * CR [not followed by LF]
86134 * LS
86135 * PS
86136 *
86137 * For CR LF, CR is ignored if it is followed by LF, and the LF will bump
86138 * the line number.
86139 */
86140 lex_ctx->input_line++;
86141 }
86142 }
86143
86144 return (duk_codepoint_t) x;
86145 }
86146
86147 /* Slow path. */
86148
86149 if (x < 0xc0UL) {
86150 /* 10xx xxxx -> invalid */
86151 goto error_encoding;
86152 } else if (x < 0xe0UL) {
86153 /* 110x xxxx 10xx xxxx */
86154 len = 2;
86155#if defined(DUK_USE_STRICT_UTF8_SOURCE)
86156 mincp = 0x80UL;
86157#endif
86158 x = x & 0x1fUL;
86159 } else if (x < 0xf0UL) {
86160 /* 1110 xxxx 10xx xxxx 10xx xxxx */
86161 len = 3;
86162#if defined(DUK_USE_STRICT_UTF8_SOURCE)
86163 mincp = 0x800UL;
86164#endif
86165 x = x & 0x0fUL;
86166 } else if (x < 0xf8UL) {
86167 /* 1111 0xxx 10xx xxxx 10xx xxxx 10xx xxxx */
86168 len = 4;
86169#if defined(DUK_USE_STRICT_UTF8_SOURCE)
86170 mincp = 0x10000UL;
86171#endif
86172 x = x & 0x07UL;
86173 } else {
86174 /* no point in supporting encodings of 5 or more bytes */
86175 goto error_encoding;
86176 }
86177
86178 DUK_ASSERT(lex_ctx->input_length >= lex_ctx->input_offset);
86179 if ((duk_size_t) len > (duk_size_t) (lex_ctx->input_length - lex_ctx->input_offset)) {
86180 goto error_clipped;
86181 }
86182
86183 p++;
86184 for (i = 1; i < len; i++) {
86186 y = *p++;
86187 if ((y & 0xc0U) != 0x80U) {
86188 /* check that byte has the form 10xx xxxx */
86189 goto error_encoding;
86190 }
86191 x = x << 6;
86192 x += y & 0x3fUL;
86193 }
86194
86195 /* check final character validity */
86196
86197 if (x > 0x10ffffUL) {
86198 goto error_encoding;
86199 }
86200#if defined(DUK_USE_STRICT_UTF8_SOURCE)
86201 if (x < mincp || (x >= 0xd800UL && x <= 0xdfffUL) || x == 0xfffeUL) {
86202 goto error_encoding;
86203 }
86204#endif
86205
86206 /* input offset tracking */
86207 lex_ctx->input_offset += len;
86208
86209 /* line tracking */
86210 DUK_ASSERT(x != 0x000aUL && x != 0x000dUL);
86211 if ((x == 0x2028UL) || (x == 0x2029UL)) {
86212 lex_ctx->input_line++;
86213 }
86214
86215 return (duk_codepoint_t) x;
86216
86217error_clipped: /* clipped codepoint */
86218error_encoding: /* invalid codepoint encoding or codepoint */
86221}
86222
86223DUK_LOCAL void duk__advance_bytes(duk_lexer_ctx *lex_ctx, duk_small_uint_t count_bytes) {
86224 duk_small_uint_t keep_bytes;
86225 duk_lexer_codepoint *cp, *cp_end;
86226
86227 DUK_ASSERT_DISABLE(count_bytes >= 0); /* unsigned */
86229
86230 /* Zero 'count' is also allowed to make call sites easier. */
86231
86232 keep_bytes = DUK_LEXER_WINDOW_SIZE * sizeof(duk_lexer_codepoint) - count_bytes;
86233 duk_memmove((void *) lex_ctx->window, (const void *) ((duk_uint8_t *) lex_ctx->window + count_bytes), (size_t) keep_bytes);
86234
86235 cp = (duk_lexer_codepoint *) ((duk_uint8_t *) lex_ctx->window + keep_bytes);
86236 cp_end = lex_ctx->window + DUK_LEXER_WINDOW_SIZE;
86237 for (; cp != cp_end; cp++) {
86238 cp->offset = lex_ctx->input_offset;
86239 cp->line = lex_ctx->input_line;
86240 cp->codepoint = duk__read_char(lex_ctx);
86241 }
86242}
86243
86245 /* Call with count == DUK_LEXER_WINDOW_SIZE to fill buffer initially. */
86246 duk__advance_bytes(lex_ctx, DUK_LEXER_WINDOW_SIZE * sizeof(duk_lexer_codepoint)); /* fill window */
86247}
86248#endif /* DUK_USE_LEXER_SLIDING_WINDOW */
86249
86250DUK_LOCAL void duk__advance_chars(duk_lexer_ctx *lex_ctx, duk_small_uint_t count_chars) {
86251 duk__advance_bytes(lex_ctx, count_chars * sizeof(duk_lexer_codepoint));
86253
86254/*
86255 * (Re)initialize the temporary byte buffer. May be called extra times
86256 * with little impact.
86257 */
86258
86260 /* Reuse buffer as is unless buffer has grown large. */
86262 /* Keep current size */
86263 } else {
86265 }
86267 DUK_BW_INIT_WITHBUF(lex_ctx->thr, &lex_ctx->bw, lex_ctx->buf);
86268}
86269
86270/*
86271 * Append a Unicode codepoint to the temporary byte buffer. Performs
86272 * CESU-8 surrogate pair encoding for codepoints above the BMP.
86273 * Existing surrogate pairs are allowed and also encoded into CESU-8.
86274 */
86275
86277 /*
86278 * Since character data is only generated by decoding the source or by
86279 * the compiler itself, we rely on the input codepoints being correct
86280 * and avoid a check here.
86281 *
86282 * Character data can also come here through decoding of Unicode
86283 * escapes ("\udead\ubeef") so all 16-but unsigned values can be
86284 * present, even when the source file itself is strict UTF-8.
86285 */
86286 DUK_ASSERT(x >= 0 && x <= 0x10ffffL);
86287
86288 DUK_BW_WRITE_ENSURE_CESU8(lex_ctx->thr, &lex_ctx->bw, (duk_ucodepoint_t) x);
86289}
86290
86292 /* ASCII characters can be emitted as a single byte without encoding
86293 * which matters for some fast paths.
86294 */
86295 DUK_ASSERT(x >= 0 && x <= 0x7f);
86297 DUK_BW_WRITE_ENSURE_U8(lex_ctx->thr, &lex_ctx->bw, (duk_uint8_t) x);
86298}
86299
86300/*
86301 * Intern the temporary byte buffer into a valstack slot
86302 * (in practice, slot1 or slot2).
86303 */
86304
86306 DUK_ASSERT(valstack_idx == lex_ctx->slot1_idx || valstack_idx == lex_ctx->slot2_idx);
86307
86308 DUK_BW_PUSH_AS_STRING(lex_ctx->thr, &lex_ctx->bw);
86309 duk_replace(lex_ctx->thr, valstack_idx);
86310 return duk_known_hstring(lex_ctx->thr, valstack_idx);
86311}
86312
86313/*
86314 * Init lexer context
86315 */
86318 DUK_ASSERT(lex_ctx != NULL);
86319
86320 duk_memzero(lex_ctx, sizeof(*lex_ctx));
86321#if defined(DUK_USE_EXPLICIT_NULL_INIT)
86322#if defined(DUK_USE_LEXER_SLIDING_WINDOW)
86323 lex_ctx->window = NULL;
86324#endif
86325 lex_ctx->thr = NULL;
86326 lex_ctx->input = NULL;
86327 lex_ctx->buf = NULL;
86328#endif
86329}
86330
86331/*
86332 * Set lexer input position and reinitialize lookup window.
86334
86336 pt->offset = lex_ctx->window[0].offset;
86337 pt->line = lex_ctx->window[0].line;
86338}
86339
86341 DUK_ASSERT_DISABLE(pt->offset >= 0); /* unsigned */
86342 DUK_ASSERT(pt->line >= 1);
86343 lex_ctx->input_offset = pt->offset;
86344 lex_ctx->input_line = pt->line;
86345 duk__init_lexer_window(lex_ctx);
86346}
86347
86348/*
86349 * Lexing helpers
86350 */
86351
86352/* Numeric value of a hex digit (also covers octal and decimal digits) or
86353 * -1 if not a valid hex digit.
86357
86358 /* Here 'x' is a Unicode codepoint */
86359 if (DUK_LIKELY(x >= 0 && x <= 0xff)) {
86360 t = duk_hex_dectab[x];
86361 if (DUK_LIKELY(t >= 0)) {
86362 return t;
86363 }
86364 }
86365
86366 return -1;
86367}
86368
86369/* Just a wrapper for call sites where 'x' is known to be valid so
86370 * we assert for it before decoding.
86371 */
86373 duk_codepoint_t ret;
86374
86375 DUK_ASSERT((x >= DUK_ASC_0 && x <= DUK_ASC_9) || (x >= DUK_ASC_LC_A && x <= DUK_ASC_LC_F) ||
86376 (x >= DUK_ASC_UC_A && x <= DUK_ASC_UC_F));
86377 ret = duk__hexval_validate(x);
86378 DUK_ASSERT(ret >= 0 && ret <= 15);
86379 return ret;
86380}
86381
86382/* having this as a separate function provided a size benefit */
86384 if (DUK_LIKELY(x >= 0 && x <= 0xff)) {
86385 return (duk_hex_dectab[x] >= 0);
86386 }
86387 return 0;
86388}
86389
86390/* Parse a Unicode escape of the form \xHH, \uHHHH, or \u{H+}. Shared by
86391 * source and RegExp parsing.
86392 */
86394 duk_small_int_t digits; /* Initial value 2 or 4 for fixed length escapes, 0 for ES2015 \u{H+}. */
86395 duk_codepoint_t escval;
86397 duk_small_uint_t adv;
86398
86399 DUK_ASSERT(DUK__L0() == DUK_ASC_BACKSLASH); /* caller responsibilities */
86401 DUK_UNREF(allow_es6);
86402
86403 adv = 2;
86404 digits = 2;
86405 if (DUK__L1() == DUK_ASC_LC_U) {
86406 digits = 4;
86407#if defined(DUK_USE_ES6_UNICODE_ESCAPE)
86408 if (DUK__L2() == DUK_ASC_LCURLY && allow_es6) {
86409 digits = 0;
86410 adv = 3;
86411 }
86412#endif
86413 }
86414 DUK__ADVANCECHARS(lex_ctx, adv);
86415
86416 escval = 0;
86417 for (;;) {
86418 /* One of the escape forms: \xHH, \uHHHH, \u{H+}.
86419 * The 'digits' variable tracks parsing state and is
86420 * initialized to:
86421 *
86422 * \xHH 2
86423 * \uHH 4
86424 * \u{H+} 0 first time, updated to -1 to indicate
86425 * at least one digit has been parsed
86426 *
86427 * Octal parsing is handled separately because it can be
86428 * done with fixed lookahead and also has validation
86429 * rules which depend on the escape length (which is
86430 * variable).
86431 *
86432 * We don't need a specific check for x < 0 (end of
86433 * input) or duk_unicode_is_line_terminator(x)
86434 * because the 'dig' decode will fail and lead to a
86435 * SyntaxError.
86436 */
86437 duk_codepoint_t dig;
86438
86439 x = DUK__L0();
86440 DUK__ADVANCECHARS(lex_ctx, 1);
86441
86442 dig = duk__hexval_validate(x);
86443 if (digits > 0) {
86444 digits--;
86445 if (dig < 0) {
86446 goto fail_escape;
86447 }
86448 DUK_ASSERT(dig >= 0x00 && dig <= 0x0f);
86449 escval = (escval << 4) + dig;
86450 if (digits == 0) {
86451 DUK_ASSERT(escval >= 0 && escval <= 0xffffL);
86452 break;
86454 } else {
86455#if defined(DUK_USE_ES6_UNICODE_ESCAPE)
86456 DUK_ASSERT(digits == 0 /* first time */ || digits == -1 /* others */);
86457 if (dig >= 0) {
86458 DUK_ASSERT(dig >= 0x00 && dig <= 0x0f);
86459 escval = (escval << 4) + dig;
86460 if (escval > 0x10ffffL) {
86461 goto fail_escape;
86462 }
86463 } else if (x == DUK_ASC_RCURLY) {
86464 if (digits == 0) {
86465 /* Empty escape, \u{}. */
86466 goto fail_escape;
86467 }
86468 DUK_ASSERT(escval >= 0 && escval <= 0x10ffffL);
86469 break;
86470 } else {
86471 goto fail_escape;
86472 }
86473 digits = -1; /* Indicate we have at least one digit. */
86474#else /* DUK_USE_ES6_UNICODE_ESCAPE */
86475 DUK_ASSERT(0); /* Never happens if \u{H+} support disabled. */
86476#endif /* DUK_USE_ES6_UNICODE_ESCAPE */
86477 }
86478 }
86479
86480 return escval;
86481
86482fail_escape:
86484 DUK_WO_NORETURN(return 0;);
86485}
86486
86487/* Parse legacy octal escape of the form \N{1,3}, e.g. \0, \5, \0377. Maximum
86488 * allowed value is \0377 (U+00FF), longest match is used. Used for both string
86489 * RegExp octal escape parsing. Window[0] must be the slash '\' and the first
86490 * digit must already be validated to be in [0-9] by the caller.
86491 */
86493 duk_small_uint_t *out_adv,
86494 duk_bool_t reject_annex_b) {
86495 duk_codepoint_t cp;
86496 duk_small_uint_t lookup_idx;
86497 duk_small_uint_t adv;
86498 duk_codepoint_t tmp;
86499
86500 DUK_ASSERT(out_adv != NULL);
86502 DUK_ASSERT(DUK__LOOKUP(lex_ctx, 1) >= DUK_ASC_0 && DUK__LOOKUP(lex_ctx, 1) <= DUK_ASC_9);
86503
86504 cp = 0;
86505 tmp = 0;
86506 for (lookup_idx = 1; lookup_idx <= 3; lookup_idx++) {
86507 DUK_DDD(DUK_DDDPRINT("lookup_idx=%ld, cp=%ld", (long) lookup_idx, (long) cp));
86508 tmp = DUK__LOOKUP(lex_ctx, lookup_idx);
86509 if (tmp < DUK_ASC_0 || tmp > DUK_ASC_7) {
86510 /* No more valid digits. */
86511 break;
86512 }
86513 tmp = (cp << 3) + (tmp - DUK_ASC_0);
86514 if (tmp > 0xff) {
86515 /* Three digit octal escapes above \377 (= 0xff)
86516 * are not allowed.
86517 */
86518 break;
86519 }
86520 cp = tmp;
86521 }
86522 DUK_DDD(DUK_DDDPRINT("final lookup_idx=%ld, cp=%ld", (long) lookup_idx, (long) cp));
86523
86524 adv = lookup_idx;
86525 if (lookup_idx == 1) {
86526 DUK_DDD(DUK_DDDPRINT("\\8 or \\9 -> treat as literal, accept in strict mode too"));
86527 DUK_ASSERT(tmp == DUK_ASC_8 || tmp == DUK_ASC_9);
86528 cp = tmp;
86529 adv++; /* correction to above, eat offending character */
86530 } else if (lookup_idx == 2 && cp == 0) {
86531 /* Note: 'foo\0bar' is OK in strict mode, but 'foo\00bar' is not.
86532 * It won't be interpreted as 'foo\u{0}0bar' but as a SyntaxError.
86533 */
86534 DUK_DDD(DUK_DDDPRINT("\\0 -> accept in strict mode too"));
86535 } else {
86536 /* This clause also handles non-shortest zero, e.g. \00. */
86537 if (reject_annex_b) {
86538 DUK_DDD(DUK_DDDPRINT("non-zero octal literal %ld -> reject in strict-mode", (long) cp));
86539 cp = -1;
86540 } else {
86541 DUK_DDD(DUK_DDDPRINT("non-zero octal literal %ld -> accepted", (long) cp));
86542 DUK_ASSERT(cp >= 0 && cp <= 0xff);
86543 }
86544 }
86545
86546 *out_adv = adv;
86547
86548 DUK_ASSERT((cp >= 0 && cp <= 0xff) || (cp == -1 && reject_annex_b));
86549 return cp;
86550}
86551
86552/* XXX: move strict mode to lex_ctx? */
86554 duk_token *out_token,
86555 duk_small_int_t quote,
86556 duk_bool_t strict_mode) {
86557 duk_small_uint_t adv;
86558
86559 for (adv = 1 /* initial quote */;;) {
86561
86562 DUK__ADVANCECHARS(lex_ctx, adv); /* eat opening quote on first loop */
86563 x = DUK__L0();
86564
86565 adv = 1;
86566 if (x == quote) {
86567 DUK__ADVANCECHARS(lex_ctx, 1); /* eat closing quote */
86568 break;
86569 } else if (x == '\\') {
86570 /* DUK__L0 -> '\' char
86571 * DUK__L1 ... DUK__L5 -> more lookup
86572 */
86573 duk_small_int_t emitcp = -1;
86574
86575 x = DUK__L1();
86576
86577 /* How much to advance before next loop. */
86578 adv = 2; /* note: long live range */
86579
86580 switch (x) {
86581 case '\'':
86582 emitcp = 0x0027;
86583 break;
86584 case '"':
86585 emitcp = 0x0022;
86586 break;
86587 case '\\':
86588 emitcp = 0x005c;
86589 break;
86590 case 'b':
86591 emitcp = 0x0008;
86592 break;
86593 case 'f':
86594 emitcp = 0x000c;
86595 break;
86596 case 'n':
86597 emitcp = 0x000a;
86598 break;
86599 case 'r':
86600 emitcp = 0x000d;
86601 break;
86602 case 't':
86603 emitcp = 0x0009;
86604 break;
86605 case 'v':
86606 emitcp = 0x000b;
86607 break;
86608 case 'x':
86609 case 'u': {
86610 duk_codepoint_t esc_cp;
86611 esc_cp = duk__lexer_parse_escape(lex_ctx, 1 /*allow_es6*/);
86612 DUK__APPENDBUFFER(lex_ctx, esc_cp);
86613 adv = 0;
86614 break;
86615 }
86616 default: {
86618 /* line continuation */
86619 if (x == 0x000d && DUK__L2() == 0x000a) {
86620 /* CR LF again a special case */
86621 adv = 3; /* line terminator, CR, LF */
86622 }
86623 } else if (DUK__ISDIGIT(x)) {
86624 /*
86625 * Octal escape or zero escape:
86626 * \0 (lookahead not OctalDigit)
86627 * \1 ... \7 (lookahead not OctalDigit)
86628 * \ZeroToThree OctalDigit (lookahead not OctalDigit)
86629 * \FourToSeven OctalDigit (no lookahead restrictions)
86630 * \ZeroToThree OctalDigit OctalDigit (no lookahead restrictions)
86631 *
86632 * Zero escape is part of the standard syntax. Octal escapes are
86633 * defined in E5 Section B.1.2, and are only allowed in non-strict mode.
86634 * Any other productions starting with a decimal digit are invalid
86635 * but are in practice treated like identity escapes.
86636 *
86637 * Parse octal (up to 3 digits) from the lookup window.
86638 */
86639
86640 emitcp = duk__lexer_parse_legacy_octal(lex_ctx, &adv, strict_mode /*reject_annex_b*/);
86641 if (emitcp < 0) {
86642 goto fail_escape;
86643 }
86644 } else if (x < 0) {
86645 goto fail_unterminated;
86646 } else {
86647 /* escaped NonEscapeCharacter */
86648 DUK__APPENDBUFFER(lex_ctx, x);
86649 }
86650 } /* end default clause */
86651 } /* end switch */
86652
86653 /* Shared handling for single codepoint escapes. */
86654 if (emitcp >= 0) {
86655 DUK__APPENDBUFFER(lex_ctx, emitcp);
86656 }
86657
86658 /* Track number of escapes; count not really needed but directive
86659 * prologues need to detect whether there were any escapes or line
86660 * continuations or not.
86661 */
86662 out_token->num_escapes++;
86663 } else if (x >= 0x20 && x <= 0x7f) {
86664 /* Fast path for ASCII case, avoids line terminator
86665 * check and CESU-8 encoding.
86666 */
86667 DUK_ASSERT(x >= 0);
86669 DUK_ASSERT(x != quote);
86671 DUK__APPENDBUFFER_ASCII(lex_ctx, x);
86672 } else if (x < 0 || duk_unicode_is_line_terminator(x)) {
86673 goto fail_unterminated;
86674 } else {
86675 /* Character which is part of the string but wasn't handled
86676 * by the fast path.
86677 */
86678 DUK__APPENDBUFFER(lex_ctx, x);
86679 }
86680 } /* string parse loop */
86681
86682 return;
86683
86684fail_escape:
86686 DUK_WO_NORETURN(return;);
86687
86688fail_unterminated:
86690 DUK_WO_NORETURN(return;);
86691}
86692
86693/* Skip to end-of-line (or end-of-file), used for single line comments. */
86695 for (;;) {
86697
86698 x = DUK__L0();
86699 if (x < 0 || duk_unicode_is_line_terminator(x)) {
86700 break;
86701 }
86702 DUK__ADVANCECHARS(lex_ctx, 1);
86703 }
86704}
86705
86706/*
86707 * Parse ECMAScript source InputElementDiv or InputElementRegExp
86708 * (E5 Section 7), skipping whitespace, comments, and line terminators.
86709 *
86710 * Possible results are:
86711 * (1) a token
86712 * (2) a line terminator (skipped)
86713 * (3) a comment (skipped)
86714 * (4) EOF
86715 *
86716 * White space is automatically skipped from the current position (but
86717 * not after the input element). If input has already ended, returns
86718 * DUK_TOK_EOF indefinitely. If a parse error occurs, uses an DUK_ERROR()
86719 * macro call (and hence a longjmp through current heap longjmp context).
86720 * Comments and line terminator tokens are automatically skipped.
86721 *
86722 * The input element being matched is determined by regexp_mode; if set,
86723 * parses a InputElementRegExp, otherwise a InputElementDiv. The
86724 * difference between these are handling of productions starting with a
86725 * forward slash.
86726 *
86727 * If strict_mode is set, recognizes additional future reserved words
86728 * specific to strict mode, and refuses to parse octal literals.
86729 *
86730 * The matching strategy below is to (currently) use a six character
86731 * lookup window to quickly determine which production is the -longest-
86732 * matching one, and then parse that. The top-level if-else clauses
86733 * match the first character, and the code blocks for each clause
86734 * handle -all- alternatives for that first character. ECMAScript
86735 * specification uses the "longest match wins" semantics, so the order
86736 * of the if-clauses matters.
86737 *
86738 * Misc notes:
86739 *
86740 * * ECMAScript numeric literals do not accept a sign character.
86741 * Consequently e.g. "-1.0" is parsed as two tokens: a negative
86742 * sign and a positive numeric literal. The compiler performs
86743 * the negation during compilation, so this has no adverse impact.
86744 *
86745 * * There is no token for "undefined": it is just a value available
86746 * from the global object (or simply established by doing a reference
86747 * to an undefined value).
86748 *
86749 * * Some contexts want Identifier tokens, which are IdentifierNames
86750 * excluding reserved words, while some contexts want IdentifierNames
86751 * directly. In the latter case e.g. "while" is interpreted as an
86752 * identifier name, not a DUK_TOK_WHILE token. The solution here is
86753 * to provide both token types: DUK_TOK_WHILE goes to 't' while
86754 * DUK_TOK_IDENTIFIER goes to 't_nores', and 'slot1' always contains
86755 * the identifier / keyword name.
86756 *
86757 * * Directive prologue needs to identify string literals such as
86758 * "use strict" and 'use strict', which are sensitive to line
86759 * continuations and escape sequences. For instance, "use\u0020strict"
86760 * is a valid directive but is distinct from "use strict". The solution
86761 * here is to decode escapes while tokenizing, but to keep track of the
86762 * number of escapes. Directive detection can then check that the
86763 * number of escapes is zero.
86764 *
86765 * * Multi-line comments with one or more internal LineTerminator are
86766 * treated like a line terminator to comply with automatic semicolon
86767 * insertion.
86768 */
86769
86772 duk_token *out_token,
86773 duk_bool_t strict_mode,
86774 duk_bool_t regexp_mode) {
86775 duk_codepoint_t x; /* temporary, must be signed and 32-bit to hold Unicode code points */
86776 duk_small_uint_t advtok = 0; /* (advance << 8) + token_type, updated at function end,
86777 * init is unnecessary but suppresses "may be used uninitialized" warnings.
86778 */
86779 duk_bool_t got_lineterm = 0; /* got lineterm preceding non-whitespace, non-lineterm token */
86780
86781 if (++lex_ctx->token_count >= lex_ctx->token_limit) {
86782 goto fail_token_limit;
86783 }
86784
86785 out_token->t = DUK_TOK_EOF;
86786 out_token->t_nores = DUK_TOK_INVALID; /* marker: copy t if not changed */
86787#if 0 /* not necessary to init, disabled for faster parsing */
86788 out_token->num = DUK_DOUBLE_NAN;
86789 out_token->str1 = NULL;
86790 out_token->str2 = NULL;
86791#endif
86792 out_token->num_escapes = 0;
86793 /* out_token->lineterm set by caller */
86794
86795 /* This would be nice, but parsing is faster without resetting the
86796 * value slots. The only side effect is that references to temporary
86797 * string values may linger until lexing is finished; they're then
86798 * freed normally.
86799 */
86800#if 0
86801 duk_to_undefined(lex_ctx->thr, lex_ctx->slot1_idx);
86802 duk_to_undefined(lex_ctx->thr, lex_ctx->slot2_idx);
86803#endif
86804
86805 /* 'advtok' indicates how much to advance and which token id to assign
86806 * at the end. This shared functionality minimizes code size. All
86807 * code paths are required to set 'advtok' to some value, so no default
86808 * init value is used. Code paths calling DUK_ERROR() never return so
86809 * they don't need to set advtok.
86810 */
86811
86812 /*
86813 * Matching order:
86814 *
86815 * Punctuator first chars, also covers comments, regexps
86816 * LineTerminator
86817 * Identifier or reserved word, also covers null/true/false literals
86818 * NumericLiteral
86819 * StringLiteral
86820 * EOF
86821 *
86822 * The order does not matter as long as the longest match is
86823 * always correctly identified. There are order dependencies
86824 * in the clauses, so it's not trivial to convert to a switch.
86825 */
86826
86827restart_lineupdate:
86828 out_token->start_line = lex_ctx->window[0].line;
86829
86830restart:
86831 out_token->start_offset = lex_ctx->window[0].offset;
86832
86833 x = DUK__L0();
86834
86835 switch (x) {
86836 case DUK_ASC_SPACE:
86837 case DUK_ASC_HT: /* fast paths for space and tab */
86838 DUK__ADVANCECHARS(lex_ctx, 1);
86839 goto restart;
86840 case DUK_ASC_LF: /* LF line terminator; CR LF and Unicode lineterms are handled in slow path */
86841 DUK__ADVANCECHARS(lex_ctx, 1);
86842 got_lineterm = 1;
86843 goto restart_lineupdate;
86844#if defined(DUK_USE_SHEBANG_COMMENTS)
86845 case DUK_ASC_HASH: /* '#' */
86846 if (DUK__L1() == DUK_ASC_EXCLAMATION && lex_ctx->window[0].offset == 0 && (lex_ctx->flags & DUK_COMPILE_SHEBANG)) {
86847 /* "Shebang" comment ('#! ...') on first line. */
86848 /* DUK__ADVANCECHARS(lex_ctx, 2) would be correct here, but not necessary */
86850 goto restart; /* line terminator will be handled on next round */
86851 }
86852 goto fail_token;
86853#endif /* DUK_USE_SHEBANG_COMMENTS */
86854 case DUK_ASC_SLASH: /* '/' */
86855 if (DUK__L1() == DUK_ASC_SLASH) {
86856 /*
86857 * E5 Section 7.4, allow SourceCharacter (which is any 16-bit
86858 * code point).
86859 */
86860
86861 /* DUK__ADVANCECHARS(lex_ctx, 2) would be correct here, but not necessary */
86863 goto restart; /* line terminator will be handled on next round */
86864 } else if (DUK__L1() == DUK_ASC_STAR) {
86865 /*
86866 * E5 Section 7.4. If the multi-line comment contains a newline,
86867 * it is treated like a single line terminator for automatic
86868 * semicolon insertion.
86869 */
86870
86871 duk_bool_t last_asterisk = 0;
86872 DUK__ADVANCECHARS(lex_ctx, 2);
86873 for (;;) {
86874 x = DUK__L0();
86875 if (x < 0) {
86876 goto fail_unterm_comment;
86877 }
86878 DUK__ADVANCECHARS(lex_ctx, 1);
86879 if (last_asterisk && x == DUK_ASC_SLASH) {
86880 break;
86881 }
86883 got_lineterm = 1;
86884 }
86885 last_asterisk = (x == DUK_ASC_STAR);
86886 }
86887 goto restart_lineupdate;
86888 } else if (regexp_mode) {
86889#if defined(DUK_USE_REGEXP_SUPPORT)
86890 /*
86891 * "/" followed by something in regexp mode. See E5 Section 7.8.5.
86892 *
86893 * RegExp parsing is a bit complex. First, the regexp body is delimited
86894 * by forward slashes, but the body may also contain forward slashes as
86895 * part of an escape sequence or inside a character class (delimited by
86896 * square brackets). A mini state machine is used to implement these.
86897 *
86898 * Further, an early (parse time) error must be thrown if the regexp
86899 * would cause a run-time error when used in the expression new RegExp(...).
86900 * Parsing here simply extracts the (candidate) regexp, and also accepts
86901 * invalid regular expressions (which are delimited properly). The caller
86902 * (compiler) must perform final validation and regexp compilation.
86903 *
86904 * RegExp first char may not be '/' (single line comment) or '*' (multi-
86905 * line comment). These have already been checked above, so there is no
86906 * need below for special handling of the first regexp character as in
86907 * the E5 productions.
86908 *
86909 * About unicode escapes within regexp literals:
86910 *
86911 * E5 Section 7.8.5 grammar does NOT accept \uHHHH escapes.
86912 * However, Section 6 states that regexps accept the escapes,
86913 * see paragraph starting with "In string literals...".
86914 * The regexp grammar, which sees the decoded regexp literal
86915 * (after lexical parsing) DOES have a \uHHHH unicode escape.
86916 * So, for instance:
86917 *
86918 * /\u1234/
86919 *
86920 * should first be parsed by the lexical grammar as:
86921 *
86922 * '\' 'u' RegularExpressionBackslashSequence
86923 * '1' RegularExpressionNonTerminator
86924 * '2' RegularExpressionNonTerminator
86925 * '3' RegularExpressionNonTerminator
86926 * '4' RegularExpressionNonTerminator
86927 *
86928 * and the escape itself is then parsed by the regexp engine.
86929 * This is the current implementation.
86930 *
86931 * Minor spec inconsistency:
86932 *
86933 * E5 Section 7.8.5 RegularExpressionBackslashSequence is:
86934 *
86935 * \ RegularExpressionNonTerminator
86936 *
86937 * while Section A.1 RegularExpressionBackslashSequence is:
86938 *
86939 * \ NonTerminator
86940 *
86941 * The latter is not normative and a typo.
86942 *
86943 */
86944
86945 /* first, parse regexp body roughly */
86946
86947 duk_small_int_t state = 0; /* 0=base, 1=esc, 2=class, 3=class+esc */
86948
86949 DUK__INITBUFFER(lex_ctx);
86950 for (;;) {
86951 DUK__ADVANCECHARS(lex_ctx, 1); /* skip opening slash on first loop */
86952 x = DUK__L0();
86953 if (x < 0 || duk_unicode_is_line_terminator(x)) {
86954 goto fail_unterm_regexp;
86955 }
86956 x = DUK__L0(); /* re-read to avoid spill / fetch */
86957 if (state == 0) {
86958 if (x == DUK_ASC_SLASH) {
86959 DUK__ADVANCECHARS(lex_ctx, 1); /* eat closing slash */
86960 break;
86961 } else if (x == DUK_ASC_BACKSLASH) {
86962 state = 1;
86963 } else if (x == DUK_ASC_LBRACKET) {
86964 state = 2;
86965 }
86966 } else if (state == 1) {
86967 state = 0;
86968 } else if (state == 2) {
86969 if (x == DUK_ASC_RBRACKET) {
86970 state = 0;
86971 } else if (x == DUK_ASC_BACKSLASH) {
86972 state = 3;
86973 }
86974 } else { /* state == 3 */
86975 state = 2;
86976 }
86977 DUK__APPENDBUFFER(lex_ctx, x);
86978 }
86979 out_token->str1 = duk__internbuffer(lex_ctx, lex_ctx->slot1_idx);
86980
86981 /* second, parse flags */
86982
86983 DUK__INITBUFFER(lex_ctx);
86984 for (;;) {
86985 x = DUK__L0();
86987 break;
86988 }
86989 x = DUK__L0(); /* re-read to avoid spill / fetch */
86990 DUK__APPENDBUFFER(lex_ctx, x);
86991 DUK__ADVANCECHARS(lex_ctx, 1);
86992 }
86993 out_token->str2 = duk__internbuffer(lex_ctx, lex_ctx->slot2_idx);
86994
86995 DUK__INITBUFFER(lex_ctx); /* free some memory */
86996
86997 /* validation of the regexp is caller's responsibility */
86998
86999 advtok = DUK__ADVTOK(0, DUK_TOK_REGEXP);
87000#else /* DUK_USE_REGEXP_SUPPORT */
87001 goto fail_regexp_support;
87002#endif /* DUK_USE_REGEXP_SUPPORT */
87003 } else if (DUK__L1() == DUK_ASC_EQUALS) {
87004 /* "/=" and not in regexp mode */
87005 advtok = DUK__ADVTOK(2, DUK_TOK_DIV_EQ);
87006 } else {
87007 /* "/" and not in regexp mode */
87008 advtok = DUK__ADVTOK(1, DUK_TOK_DIV);
87009 }
87010 break;
87011 case DUK_ASC_LCURLY: /* '{' */
87012 advtok = DUK__ADVTOK(1, DUK_TOK_LCURLY);
87013 break;
87014 case DUK_ASC_RCURLY: /* '}' */
87015 advtok = DUK__ADVTOK(1, DUK_TOK_RCURLY);
87016 break;
87017 case DUK_ASC_LPAREN: /* '(' */
87018 advtok = DUK__ADVTOK(1, DUK_TOK_LPAREN);
87019 break;
87020 case DUK_ASC_RPAREN: /* ')' */
87021 advtok = DUK__ADVTOK(1, DUK_TOK_RPAREN);
87022 break;
87023 case DUK_ASC_LBRACKET: /* '[' */
87024 advtok = DUK__ADVTOK(1, DUK_TOK_LBRACKET);
87025 break;
87026 case DUK_ASC_RBRACKET: /* ']' */
87027 advtok = DUK__ADVTOK(1, DUK_TOK_RBRACKET);
87028 break;
87029 case DUK_ASC_PERIOD: /* '.' */
87030 if (DUK__ISDIGIT(DUK__L1())) {
87031 /* Period followed by a digit can only start DecimalLiteral
87032 * (handled in slow path). We could jump straight into the
87033 * DecimalLiteral handling but should avoid goto to inside
87034 * a block.
87035 */
87036 goto slow_path;
87037 }
87038 advtok = DUK__ADVTOK(1, DUK_TOK_PERIOD);
87039 break;
87040 case DUK_ASC_SEMICOLON: /* ';' */
87041 advtok = DUK__ADVTOK(1, DUK_TOK_SEMICOLON);
87042 break;
87043 case DUK_ASC_COMMA: /* ',' */
87044 advtok = DUK__ADVTOK(1, DUK_TOK_COMMA);
87045 break;
87046 case DUK_ASC_LANGLE: /* '<' */
87047#if defined(DUK_USE_HTML_COMMENTS)
87049 /*
87050 * ES2015: B.1.3, handle "<!--" SingleLineHTMLOpenComment
87051 */
87052
87053 /* DUK__ADVANCECHARS(lex_ctx, 4) would be correct here, but not necessary */
87055 goto restart; /* line terminator will be handled on next round */
87056 } else
87057#endif /* DUK_USE_HTML_COMMENTS */
87058 if (DUK__L1() == DUK_ASC_LANGLE && DUK__L2() == DUK_ASC_EQUALS) {
87059 advtok = DUK__ADVTOK(3, DUK_TOK_ALSHIFT_EQ);
87060 } else if (DUK__L1() == DUK_ASC_EQUALS) {
87061 advtok = DUK__ADVTOK(2, DUK_TOK_LE);
87062 } else if (DUK__L1() == DUK_ASC_LANGLE) {
87063 advtok = DUK__ADVTOK(2, DUK_TOK_ALSHIFT);
87064 } else {
87065 advtok = DUK__ADVTOK(1, DUK_TOK_LT);
87066 }
87067 break;
87068 case DUK_ASC_RANGLE: /* '>' */
87070 advtok = DUK__ADVTOK(4, DUK_TOK_RSHIFT_EQ);
87071 } else if (DUK__L1() == DUK_ASC_RANGLE && DUK__L2() == DUK_ASC_RANGLE) {
87072 advtok = DUK__ADVTOK(3, DUK_TOK_RSHIFT);
87073 } else if (DUK__L1() == DUK_ASC_RANGLE && DUK__L2() == DUK_ASC_EQUALS) {
87074 advtok = DUK__ADVTOK(3, DUK_TOK_ARSHIFT_EQ);
87075 } else if (DUK__L1() == DUK_ASC_EQUALS) {
87076 advtok = DUK__ADVTOK(2, DUK_TOK_GE);
87077 } else if (DUK__L1() == DUK_ASC_RANGLE) {
87078 advtok = DUK__ADVTOK(2, DUK_TOK_ARSHIFT);
87079 } else {
87080 advtok = DUK__ADVTOK(1, DUK_TOK_GT);
87081 }
87082 break;
87083 case DUK_ASC_EQUALS: /* '=' */
87084 if (DUK__L1() == DUK_ASC_EQUALS && DUK__L2() == DUK_ASC_EQUALS) {
87085 advtok = DUK__ADVTOK(3, DUK_TOK_SEQ);
87086 } else if (DUK__L1() == DUK_ASC_EQUALS) {
87087 advtok = DUK__ADVTOK(2, DUK_TOK_EQ);
87088 } else {
87089 advtok = DUK__ADVTOK(1, DUK_TOK_EQUALSIGN);
87090 }
87091 break;
87092 case DUK_ASC_EXCLAMATION: /* '!' */
87093 if (DUK__L1() == DUK_ASC_EQUALS && DUK__L2() == DUK_ASC_EQUALS) {
87094 advtok = DUK__ADVTOK(3, DUK_TOK_SNEQ);
87095 } else if (DUK__L1() == DUK_ASC_EQUALS) {
87096 advtok = DUK__ADVTOK(2, DUK_TOK_NEQ);
87097 } else {
87098 advtok = DUK__ADVTOK(1, DUK_TOK_LNOT);
87099 }
87100 break;
87101 case DUK_ASC_PLUS: /* '+' */
87102 if (DUK__L1() == DUK_ASC_PLUS) {
87103 advtok = DUK__ADVTOK(2, DUK_TOK_INCREMENT);
87104 } else if (DUK__L1() == DUK_ASC_EQUALS) {
87105 advtok = DUK__ADVTOK(2, DUK_TOK_ADD_EQ);
87106 } else {
87107 advtok = DUK__ADVTOK(1, DUK_TOK_ADD);
87108 }
87109 break;
87110 case DUK_ASC_MINUS: /* '-' */
87111#if defined(DUK_USE_HTML_COMMENTS)
87112 if (got_lineterm && DUK__L1() == DUK_ASC_MINUS && DUK__L2() == DUK_ASC_RANGLE) {
87113 /*
87114 * ES2015: B.1.3, handle "-->" SingleLineHTMLCloseComment
87115 * Only allowed:
87116 * - on new line
87117 * - preceded only by whitespace
87118 * - preceded by end of multiline comment and optional whitespace
87119 *
87120 * Since whitespace generates no tokens, and multiline comments
87121 * are treated as a line ending, consulting `got_lineterm` is
87122 * sufficient to test for these three options.
87123 */
87124
87125 /* DUK__ADVANCECHARS(lex_ctx, 3) would be correct here, but not necessary */
87127 goto restart; /* line terminator will be handled on next round */
87128 } else
87129#endif /* DUK_USE_HTML_COMMENTS */
87130 if (DUK__L1() == DUK_ASC_MINUS) {
87131 advtok = DUK__ADVTOK(2, DUK_TOK_DECREMENT);
87132 } else if (DUK__L1() == DUK_ASC_EQUALS) {
87133 advtok = DUK__ADVTOK(2, DUK_TOK_SUB_EQ);
87134 } else {
87135 advtok = DUK__ADVTOK(1, DUK_TOK_SUB);
87136 }
87137 break;
87138 case DUK_ASC_STAR: /* '*' */
87139#if defined(DUK_USE_ES7_EXP_OPERATOR)
87140 if (DUK__L1() == DUK_ASC_STAR && DUK__L2() == DUK_ASC_EQUALS) {
87141 advtok = DUK__ADVTOK(3, DUK_TOK_EXP_EQ);
87142 } else if (DUK__L1() == DUK_ASC_STAR) {
87143 advtok = DUK__ADVTOK(2, DUK_TOK_EXP);
87144 } else
87145#endif
87146 if (DUK__L1() == DUK_ASC_EQUALS) {
87147 advtok = DUK__ADVTOK(2, DUK_TOK_MUL_EQ);
87148 } else {
87149 advtok = DUK__ADVTOK(1, DUK_TOK_MUL);
87150 }
87151 break;
87152 case DUK_ASC_PERCENT: /* '%' */
87153 if (DUK__L1() == DUK_ASC_EQUALS) {
87154 advtok = DUK__ADVTOK(2, DUK_TOK_MOD_EQ);
87155 } else {
87156 advtok = DUK__ADVTOK(1, DUK_TOK_MOD);
87157 }
87158 break;
87159 case DUK_ASC_AMP: /* '&' */
87160 if (DUK__L1() == DUK_ASC_AMP) {
87161 advtok = DUK__ADVTOK(2, DUK_TOK_LAND);
87162 } else if (DUK__L1() == DUK_ASC_EQUALS) {
87163 advtok = DUK__ADVTOK(2, DUK_TOK_BAND_EQ);
87164 } else {
87165 advtok = DUK__ADVTOK(1, DUK_TOK_BAND);
87166 }
87167 break;
87168 case DUK_ASC_PIPE: /* '|' */
87169 if (DUK__L1() == DUK_ASC_PIPE) {
87170 advtok = DUK__ADVTOK(2, DUK_TOK_LOR);
87171 } else if (DUK__L1() == DUK_ASC_EQUALS) {
87172 advtok = DUK__ADVTOK(2, DUK_TOK_BOR_EQ);
87173 } else {
87174 advtok = DUK__ADVTOK(1, DUK_TOK_BOR);
87175 }
87176 break;
87177 case DUK_ASC_CARET: /* '^' */
87178 if (DUK__L1() == DUK_ASC_EQUALS) {
87179 advtok = DUK__ADVTOK(2, DUK_TOK_BXOR_EQ);
87180 } else {
87181 advtok = DUK__ADVTOK(1, DUK_TOK_BXOR);
87182 }
87183 break;
87184 case DUK_ASC_TILDE: /* '~' */
87185 advtok = DUK__ADVTOK(1, DUK_TOK_BNOT);
87186 break;
87187 case DUK_ASC_QUESTION: /* '?' */
87188 advtok = DUK__ADVTOK(1, DUK_TOK_QUESTION);
87189 break;
87190 case DUK_ASC_COLON: /* ':' */
87191 advtok = DUK__ADVTOK(1, DUK_TOK_COLON);
87192 break;
87193 case DUK_ASC_DOUBLEQUOTE: /* '"' */
87194 case DUK_ASC_SINGLEQUOTE: { /* '\'' */
87195 DUK__INITBUFFER(lex_ctx);
87196 duk__lexer_parse_string_literal(lex_ctx, out_token, x /*quote*/, strict_mode);
87197 duk__internbuffer(lex_ctx, lex_ctx->slot1_idx);
87198 out_token->str1 = duk_known_hstring(lex_ctx->thr, lex_ctx->slot1_idx);
87199
87200 DUK__INITBUFFER(lex_ctx); /* free some memory */
87201
87202 advtok = DUK__ADVTOK(0, DUK_TOK_STRING);
87203 break;
87204 }
87205 default:
87206 goto slow_path;
87207 } /* switch */
87208
87209 goto skip_slow_path;
87210
87211slow_path:
87213 if (x == 0x000d && DUK__L1() == 0x000a) {
87214 /*
87215 * E5 Section 7.3: CR LF is detected as a single line terminator for
87216 * line numbers. Here we also detect it as a single line terminator
87217 * token.
87218 */
87219 DUK__ADVANCECHARS(lex_ctx, 2);
87220 } else {
87221 DUK__ADVANCECHARS(lex_ctx, 1);
87222 }
87223 got_lineterm = 1;
87224 goto restart_lineupdate;
87225 } else if (duk_unicode_is_identifier_start(x) || x == DUK_ASC_BACKSLASH) {
87226 /*
87227 * Parse an identifier and then check whether it is:
87228 * - reserved word (keyword or other reserved word)
87229 * - "null" (NullLiteral)
87230 * - "true" (BooleanLiteral)
87231 * - "false" (BooleanLiteral)
87232 * - anything else => identifier
87233 *
87234 * This does not follow the E5 productions cleanly, but is
87235 * useful and compact.
87236 *
87237 * Note that identifiers may contain Unicode escapes,
87238 * see E5 Sections 6 and 7.6. They must be decoded first,
87239 * and the result checked against allowed characters.
87240 * The above if-clause accepts an identifier start and an
87241 * '\' character -- no other token can begin with a '\'.
87242 *
87243 * Note that "get" and "set" are not reserved words in E5
87244 * specification so they are recognized as plain identifiers
87245 * (the tokens DUK_TOK_GET and DUK_TOK_SET are actually not
87246 * used now). The compiler needs to work around this.
87247 *
87248 * Strictly speaking, following ECMAScript longest match
87249 * specification, an invalid escape for the first character
87250 * should cause a syntax error. However, an invalid escape
87251 * for IdentifierParts should just terminate the identifier
87252 * early (longest match), and let the next tokenization
87253 * fail. For instance Rhino croaks with 'foo\z' when
87254 * parsing the identifier. This has little practical impact.
87255 */
87256
87257 duk_small_uint_t i, i_end;
87258 duk_bool_t first = 1;
87259 duk_hstring *str;
87260
87261 DUK__INITBUFFER(lex_ctx);
87262 for (;;) {
87263 /* re-lookup first char on first loop */
87264 if (DUK__L0() == DUK_ASC_BACKSLASH) {
87265 duk_codepoint_t esc_cp;
87266 if (DUK__L1() != DUK_ASC_LC_U) {
87267 goto fail_escape;
87268 }
87269 esc_cp = duk__lexer_parse_escape(lex_ctx, 1 /*allow_es6*/);
87270 DUK__APPENDBUFFER(lex_ctx, esc_cp);
87271
87272 /* IdentifierStart is stricter than IdentifierPart, so if the first
87273 * character is escaped, must have a stricter check here.
87274 */
87275 if (!(first ? duk_unicode_is_identifier_start(esc_cp) : duk_unicode_is_identifier_part(esc_cp))) {
87276 goto fail_escape;
87277 }
87278
87279 /* Track number of escapes: necessary for proper keyword
87280 * detection.
87281 */
87282 out_token->num_escapes++;
87283 } else {
87284 /* Note: first character is checked against this. But because
87285 * IdentifierPart includes all IdentifierStart characters, and
87286 * the first character (if unescaped) has already been checked
87287 * in the if condition, this is OK.
87288 */
87290 break;
87291 }
87292 DUK__APPENDBUFFER(lex_ctx, DUK__L0());
87293 DUK__ADVANCECHARS(lex_ctx, 1);
87294 }
87295 first = 0;
87296 }
87297
87298 out_token->str1 = duk__internbuffer(lex_ctx, lex_ctx->slot1_idx);
87299 str = out_token->str1;
87300 out_token->t_nores = DUK_TOK_IDENTIFIER;
87301
87302 DUK__INITBUFFER(lex_ctx); /* free some memory */
87303
87304 /*
87305 * Interned identifier is compared against reserved words, which are
87306 * currently interned into the heap context. See genbuiltins.py.
87307 *
87308 * Note that an escape in the identifier disables recognition of
87309 * keywords; e.g. "\u0069f = 1;" is a valid statement (assigns to
87310 * identifier named "if"). This is not necessarily compliant,
87311 * see test-dec-escaped-char-in-keyword.js.
87312 *
87313 * Note: "get" and "set" are awkward. They are not officially
87314 * ReservedWords (and indeed e.g. "var set = 1;" is valid), and
87315 * must come out as DUK_TOK_IDENTIFIER. The compiler needs to
87316 * work around this a bit.
87317 */
87318
87319 /* XXX: optimize by adding the token numbers directly into the
87320 * always interned duk_hstring objects (there should be enough
87321 * flag bits free for that)?
87322 */
87323
87325
87326 advtok = DUK__ADVTOK(0, DUK_TOK_IDENTIFIER);
87327 if (out_token->num_escapes == 0) {
87328 for (i = DUK_STRIDX_START_RESERVED; i < i_end; i++) {
87329 DUK_ASSERT_DISABLE(i >= 0); /* unsigned */
87331 if (DUK_HTHREAD_GET_STRING(lex_ctx->thr, i) == str) {
87332 advtok = DUK__ADVTOK(0, DUK_STRIDX_TO_TOK(i));
87333 break;
87334 }
87335 }
87336 }
87337 } else if (DUK__ISDIGIT(x) || (x == DUK_ASC_PERIOD)) {
87338 /* Note: decimal number may start with a period, but must be followed by a digit */
87339
87340 /*
87341 * Pre-parsing for decimal, hex, octal (both legacy and ES2015),
87342 * and binary literals, followed by an actual parser step
87343 * provided by numconv.
87344 *
87345 * Note: the leading sign character ('+' or '-') is -not- part of
87346 * the production in E5 grammar, and that the a DecimalLiteral
87347 * starting with a '0' must be followed by a non-digit.
87348 *
87349 * XXX: the two step parsing process is quite awkward, it would
87350 * be more straightforward to allow numconv to parse the longest
87351 * valid prefix (it already does that, it only needs to indicate
87352 * where the input ended). However, the lexer decodes characters
87353 * using a limited lookup window, so this is not a trivial change.
87354 */
87355
87356 /* XXX: because of the final check below (that the literal is not
87357 * followed by a digit), this could maybe be simplified, if we bail
87358 * out early from a leading zero (and if there are no periods etc).
87359 * Maybe too complex.
87360 */
87361
87362 duk_double_t val;
87363 duk_bool_t legacy_oct = 0;
87364 duk_small_int_t state; /* 0=before period/exp,
87365 * 1=after period, before exp
87366 * 2=after exp, allow '+' or '-'
87367 * 3=after exp and exp sign
87368 */
87369 duk_small_uint_t s2n_flags;
87370 duk_codepoint_t y, z;
87371 duk_small_int_t s2n_radix = 10;
87372 duk_small_uint_t pre_adv = 0;
87373
87374 DUK__INITBUFFER(lex_ctx);
87375 y = DUK__L1();
87376
87377 if (x == DUK_ASC_0) {
87379
87380 pre_adv = 2; /* default for 0xNNN, 0oNNN, 0bNNN. */
87381 if (z == DUK_ASC_LC_X) {
87382 s2n_radix = 16;
87383 } else if (z == DUK_ASC_LC_O) {
87384 s2n_radix = 8;
87385 } else if (z == DUK_ASC_LC_B) {
87386 s2n_radix = 2;
87387 } else {
87388 pre_adv = 0;
87389 if (DUK__ISDIGIT(y)) {
87390 if (strict_mode) {
87391 /* Reject octal like \07 but also octal-lookalike
87392 * decimal like \08 in strict mode.
87393 */
87394 goto fail_number_literal;
87395 } else {
87396 /* Legacy OctalIntegerLiteral or octal-lookalice
87397 * decimal. Deciding between the two happens below
87398 * in digit scanning.
87399 */
87400 DUK__APPENDBUFFER(lex_ctx, x);
87401 pre_adv = 1;
87402 legacy_oct = 1;
87403 s2n_radix = 8; /* tentative unless conflicting digits found */
87404 }
87405 }
87406 }
87407 }
87408
87409 DUK__ADVANCECHARS(lex_ctx, pre_adv);
87410
87411 /* XXX: we could parse integers here directly, and fall back
87412 * to numconv only when encountering a fractional expression
87413 * or when an octal literal turned out to be decimal (0778 etc).
87414 */
87415 state = 0;
87416 for (;;) {
87417 x = DUK__L0(); /* re-lookup curr char on first round */
87418 if (DUK__ISDIGIT(x)) {
87419 /* Note: intentionally allow leading zeroes here, as the
87420 * actual parser will check for them.
87421 */
87422 if (state == 0 && legacy_oct && (x == DUK_ASC_8 || x == DUK_ASC_9)) {
87423 /* Started out as an octal-lookalike
87424 * but interpreted as decimal, e.g.
87425 * '0779' -> 779. This also means
87426 * that fractions are allowed, e.g.
87427 * '0779.123' is allowed but '0777.123'
87428 * is not!
87429 */
87430 s2n_radix = 10;
87431 }
87432 if (state == 2) {
87433 state = 3;
87434 }
87435 } else if (s2n_radix == 16 && DUK__ISHEXDIGIT(x)) {
87436 /* Note: 'e' and 'E' are also accepted here. */
87437 ;
87438 } else if (x == DUK_ASC_PERIOD) {
87439 if (state >= 1 || s2n_radix != 10) {
87440 break;
87441 } else {
87442 state = 1;
87443 }
87444 } else if (x == DUK_ASC_LC_E || x == DUK_ASC_UC_E) {
87445 if (state >= 2 || s2n_radix != 10) {
87446 break;
87447 } else {
87448 state = 2;
87449 }
87450 } else if (x == DUK_ASC_MINUS || x == DUK_ASC_PLUS) {
87451 if (state != 2) {
87452 break;
87453 } else {
87454 state = 3;
87455 }
87456 } else {
87457 break;
87458 }
87459 DUK__APPENDBUFFER(lex_ctx, x);
87460 DUK__ADVANCECHARS(lex_ctx, 1);
87461 }
87462
87463 /* XXX: better coercion */
87464 (void) duk__internbuffer(lex_ctx, lex_ctx->slot1_idx);
87465
87466 if (s2n_radix != 10) {
87467 /* For bases other than 10, integer only. */
87469 } else {
87472 }
87473
87474 duk_dup(lex_ctx->thr, lex_ctx->slot1_idx);
87475 duk_numconv_parse(lex_ctx->thr, s2n_radix, s2n_flags);
87476 val = duk_to_number_m1(lex_ctx->thr);
87477 if (DUK_ISNAN(val)) {
87478 goto fail_number_literal;
87479 }
87480 duk_replace(lex_ctx->thr, lex_ctx->slot1_idx); /* could also just pop? */
87481
87482 DUK__INITBUFFER(lex_ctx); /* free some memory */
87483
87484 /* Section 7.8.3 (note): NumericLiteral must be followed by something other than
87485 * IdentifierStart or DecimalDigit.
87486 */
87487
87489 goto fail_number_literal;
87490 }
87491
87492 out_token->num = val;
87493 advtok = DUK__ADVTOK(0, DUK_TOK_NUMBER);
87494 } else if (duk_unicode_is_whitespace(DUK__LOOKUP(lex_ctx, 0))) {
87495 DUK__ADVANCECHARS(lex_ctx, 1);
87496 goto restart;
87497 } else if (x < 0) {
87498 advtok = DUK__ADVTOK(0, DUK_TOK_EOF);
87499 } else {
87500 goto fail_token;
87501 }
87502skip_slow_path:
87503
87504 /*
87505 * Shared exit path
87506 */
87507
87508 DUK__ADVANCEBYTES(lex_ctx, advtok >> 8);
87509 out_token->t = advtok & 0xff;
87510 if (out_token->t_nores == DUK_TOK_INVALID) {
87511 out_token->t_nores = out_token->t;
87512 }
87513 out_token->lineterm = got_lineterm;
87514
87515 /* Automatic semicolon insertion is allowed if a token is preceded
87516 * by line terminator(s), or terminates a statement list (right curly
87517 * or EOF).
87518 */
87519 if (got_lineterm || out_token->t == DUK_TOK_RCURLY || out_token->t == DUK_TOK_EOF) {
87520 out_token->allow_auto_semi = 1;
87521 } else {
87522 out_token->allow_auto_semi = 0;
87523 }
87524
87525 return;
87526
87527fail_token_limit:
87529 DUK_WO_NORETURN(return;);
87531fail_token:
87533 DUK_WO_NORETURN(return;);
87534
87535fail_number_literal:
87537 DUK_WO_NORETURN(return;);
87538
87539fail_escape:
87541 DUK_WO_NORETURN(return;);
87542
87543fail_unterm_regexp:
87545 DUK_WO_NORETURN(return;);
87546
87547fail_unterm_comment:
87549 DUK_WO_NORETURN(return;);
87550
87551#if !defined(DUK_USE_REGEXP_SUPPORT)
87552fail_regexp_support:
87554 DUK_WO_NORETURN(return;);
87555#endif
87556}
87557
87558#if defined(DUK_USE_REGEXP_SUPPORT)
87559
87560/*
87561 * Parse a RegExp token. The grammar is described in E5 Section 15.10.
87562 * Terminal constructions (such as quantifiers) are parsed directly here.
87563 *
87564 * 0xffffffffU is used as a marker for "infinity" in quantifiers. Further,
87565 * DUK__MAX_RE_QUANT_DIGITS limits the maximum number of digits that
87566 * will be accepted for a quantifier.
87567 */
87568
87570 duk_small_uint_t advtok = 0; /* init is unnecessary but suppresses "may be used uninitialized" warnings */
87571 duk_codepoint_t x, y;
87572
87573 if (++lex_ctx->token_count >= lex_ctx->token_limit) {
87574 goto fail_token_limit;
87575 }
87576
87577 duk_memzero(out_token, sizeof(*out_token));
87578
87579 x = DUK__L0();
87580 y = DUK__L1();
87581
87582 DUK_DDD(DUK_DDDPRINT("parsing regexp token, L0=%ld, L1=%ld", (long) x, (long) y));
87583
87584 switch (x) {
87585 case DUK_ASC_PIPE: {
87587 break;
87588 }
87589 case DUK_ASC_CARET: {
87591 break;
87592 }
87593 case DUK_ASC_DOLLAR: {
87594 advtok = DUK__ADVTOK(1, DUK_RETOK_ASSERT_END);
87595 break;
87596 }
87597 case DUK_ASC_QUESTION: {
87598 out_token->qmin = 0;
87599 out_token->qmax = 1;
87600 if (y == DUK_ASC_QUESTION) {
87601 advtok = DUK__ADVTOK(2, DUK_RETOK_QUANTIFIER);
87602 out_token->greedy = 0;
87603 } else {
87604 advtok = DUK__ADVTOK(1, DUK_RETOK_QUANTIFIER);
87605 out_token->greedy = 1;
87606 }
87607 break;
87608 }
87609 case DUK_ASC_STAR: {
87610 out_token->qmin = 0;
87611 out_token->qmax = DUK_RE_QUANTIFIER_INFINITE;
87612 if (y == DUK_ASC_QUESTION) {
87613 advtok = DUK__ADVTOK(2, DUK_RETOK_QUANTIFIER);
87614 out_token->greedy = 0;
87615 } else {
87616 advtok = DUK__ADVTOK(1, DUK_RETOK_QUANTIFIER);
87617 out_token->greedy = 1;
87618 }
87619 break;
87620 }
87621 case DUK_ASC_PLUS: {
87622 out_token->qmin = 1;
87623 out_token->qmax = DUK_RE_QUANTIFIER_INFINITE;
87624 if (y == DUK_ASC_QUESTION) {
87625 advtok = DUK__ADVTOK(2, DUK_RETOK_QUANTIFIER);
87626 out_token->greedy = 0;
87627 } else {
87628 advtok = DUK__ADVTOK(1, DUK_RETOK_QUANTIFIER);
87629 out_token->greedy = 1;
87630 }
87631 break;
87632 }
87633 case DUK_ASC_LCURLY: {
87634 /* Production allows 'DecimalDigits', including leading zeroes */
87635 duk_uint32_t val1 = 0;
87636 duk_uint32_t val2 = DUK_RE_QUANTIFIER_INFINITE;
87637 duk_small_int_t digits = 0;
87638#if defined(DUK_USE_ES6_REGEXP_SYNTAX)
87639 duk_lexer_point lex_pt;
87640#endif
87641
87642#if defined(DUK_USE_ES6_REGEXP_SYNTAX)
87643 /* Store lexer position, restoring if quantifier is invalid. */
87644 DUK_LEXER_GETPOINT(lex_ctx, &lex_pt);
87645#endif
87646
87647 for (;;) {
87648 DUK__ADVANCECHARS(lex_ctx, 1); /* eat '{' on entry */
87649 x = DUK__L0();
87650 if (DUK__ISDIGIT(x)) {
87651 digits++;
87652 val1 = val1 * 10 + (duk_uint32_t) duk__hexval(x);
87653 } else if (x == DUK_ASC_COMMA) {
87654 if (digits > DUK__MAX_RE_QUANT_DIGITS) {
87655 goto invalid_quantifier;
87656 }
87657 if (val2 != DUK_RE_QUANTIFIER_INFINITE) {
87658 goto invalid_quantifier;
87659 }
87660 if (DUK__L1() == DUK_ASC_RCURLY) {
87661 /* form: { DecimalDigits , }, val1 = min count */
87662 if (digits == 0) {
87663 goto invalid_quantifier;
87664 }
87665 out_token->qmin = val1;
87666 out_token->qmax = DUK_RE_QUANTIFIER_INFINITE;
87667 DUK__ADVANCECHARS(lex_ctx, 2);
87668 break;
87669 }
87670 val2 = val1;
87671 val1 = 0;
87672 digits = 0; /* not strictly necessary because of lookahead '}' above */
87673 } else if (x == DUK_ASC_RCURLY) {
87674 if (digits > DUK__MAX_RE_QUANT_DIGITS) {
87675 goto invalid_quantifier;
87676 }
87677 if (digits == 0) {
87678 goto invalid_quantifier;
87679 }
87680 if (val2 != DUK_RE_QUANTIFIER_INFINITE) {
87681 /* val2 = min count, val1 = max count */
87682 out_token->qmin = val2;
87683 out_token->qmax = val1;
87684 } else {
87685 /* val1 = count */
87686 out_token->qmin = val1;
87687 out_token->qmax = val1;
87688 }
87689 DUK__ADVANCECHARS(lex_ctx, 1);
87690 break;
87691 } else {
87692 goto invalid_quantifier;
87693 }
87694 }
87695 if (DUK__L0() == DUK_ASC_QUESTION) {
87696 out_token->greedy = 0;
87697 DUK__ADVANCECHARS(lex_ctx, 1);
87698 } else {
87699 out_token->greedy = 1;
87700 }
87701 advtok = DUK__ADVTOK(0, DUK_RETOK_QUANTIFIER);
87702 break;
87703 invalid_quantifier:
87704#if defined(DUK_USE_ES6_REGEXP_SYNTAX)
87705 /* Failed to match the quantifier, restore lexer and parse
87706 * opening brace as a literal.
87707 */
87708 DUK_LEXER_SETPOINT(lex_ctx, &lex_pt);
87709 advtok = DUK__ADVTOK(1, DUK_RETOK_ATOM_CHAR);
87710 out_token->num = DUK_ASC_LCURLY;
87711#else
87712 goto fail_quantifier;
87713#endif
87714 break;
87715 }
87716 case DUK_ASC_PERIOD: {
87718 break;
87719 }
87720 case DUK_ASC_BACKSLASH: {
87721 /* The E5.1 specification does not seem to allow IdentifierPart characters
87722 * to be used as identity escapes. Unfortunately this includes '$', which
87723 * cannot be escaped as '\$'; it needs to be escaped e.g. as '\u0024'.
87724 * Many other implementations (including V8 and Rhino, for instance) do
87725 * accept '\$' as a valid identity escape, which is quite pragmatic, and
87726 * ES2015 Annex B relaxes the rules to allow these (and other) real world forms.
87727 */
87728
87729 advtok = DUK__ADVTOK(2, DUK_RETOK_ATOM_CHAR); /* default: char escape (two chars) */
87730 if (y == DUK_ASC_LC_B) {
87732 } else if (y == DUK_ASC_UC_B) {
87734 } else if (y == DUK_ASC_LC_F) {
87735 out_token->num = 0x000c;
87736 } else if (y == DUK_ASC_LC_N) {
87737 out_token->num = 0x000a;
87738 } else if (y == DUK_ASC_LC_T) {
87739 out_token->num = 0x0009;
87740 } else if (y == DUK_ASC_LC_R) {
87741 out_token->num = 0x000d;
87742 } else if (y == DUK_ASC_LC_V) {
87743 out_token->num = 0x000b;
87744 } else if (y == DUK_ASC_LC_C) {
87745 x = DUK__L2();
87746 if ((x >= DUK_ASC_LC_A && x <= DUK_ASC_LC_Z) || (x >= DUK_ASC_UC_A && x <= DUK_ASC_UC_Z)) {
87747 out_token->num = (duk_uint32_t) (x % 32);
87748 advtok = DUK__ADVTOK(3, DUK_RETOK_ATOM_CHAR);
87749 } else {
87750 goto fail_escape;
87751 }
87752 } else if (y == DUK_ASC_LC_X || y == DUK_ASC_LC_U) {
87753 /* The token value is the Unicode codepoint without
87754 * it being decode into surrogate pair characters
87755 * here. The \u{H+} is only allowed in Unicode mode
87756 * which we don't support yet.
87757 */
87758 out_token->num = (duk_uint32_t) duk__lexer_parse_escape(lex_ctx, 0 /*allow_es6*/);
87759 advtok = DUK__ADVTOK(0, DUK_RETOK_ATOM_CHAR);
87760 } else if (y == DUK_ASC_LC_D) {
87761 advtok = DUK__ADVTOK(2, DUK_RETOK_ATOM_DIGIT);
87762 } else if (y == DUK_ASC_UC_D) {
87764 } else if (y == DUK_ASC_LC_S) {
87765 advtok = DUK__ADVTOK(2, DUK_RETOK_ATOM_WHITE);
87766 } else if (y == DUK_ASC_UC_S) {
87768 } else if (y == DUK_ASC_LC_W) {
87770 } else if (y == DUK_ASC_UC_W) {
87772 } else if (DUK__ISDIGIT(y)) {
87773 /* E5 Section 15.10.2.11 */
87774 if (y == DUK_ASC_0) {
87775 if (DUK__ISDIGIT(DUK__L2())) {
87776 goto fail_escape;
87777 }
87778 out_token->num = 0x0000;
87779 advtok = DUK__ADVTOK(2, DUK_RETOK_ATOM_CHAR);
87780 } else {
87781 /* XXX: shared parsing? */
87782 duk_uint32_t val = 0;
87784 for (i = 0;; i++) {
87785 if (i >= DUK__MAX_RE_DECESC_DIGITS) {
87786 goto fail_escape;
87787 }
87788 DUK__ADVANCECHARS(lex_ctx, 1); /* eat backslash on entry */
87789 x = DUK__L0();
87790 if (!DUK__ISDIGIT(x)) {
87791 break;
87792 }
87793 val = val * 10 + (duk_uint32_t) duk__hexval(x);
87794 }
87795 /* DUK__L0() cannot be a digit, because the loop doesn't terminate if it is */
87797 out_token->num = val;
87798 }
87799#if defined(DUK_USE_ES6_REGEXP_SYNTAX)
87800 } else if (y >= 0) {
87801 /* For ES2015 Annex B, accept any source character as identity
87802 * escape except 'c' which is used for control characters.
87803 * http://www.ecma-international.org/ecma-262/6.0/#sec-regular-expressions-patterns
87804 * Careful not to match end-of-buffer (<0) here.
87805 * This is not yet full ES2015 Annex B because cases above
87806 * (like hex escape) won't backtrack.
87807 */
87808 DUK_ASSERT(y != DUK_ASC_LC_C); /* covered above */
87809#else /* DUK_USE_ES6_REGEXP_SYNTAX */
87810 } else if ((y >= 0 && !duk_unicode_is_identifier_part(y)) || y == DUK_UNICODE_CP_ZWNJ || y == DUK_UNICODE_CP_ZWJ) {
87811 /* For ES5.1 identity escapes are not allowed for identifier
87812 * parts. This conflicts with a lot of real world code as this
87813 * doesn't e.g. allow escaping a dollar sign as /\$/, see
87814 * test-regexp-identity-escape-dollar.js.
87815 */
87816#endif /* DUK_USE_ES6_REGEXP_SYNTAX */
87817 out_token->num = (duk_uint32_t) y;
87818 } else {
87819 goto fail_escape;
87820 }
87821 break;
87822 }
87823 case DUK_ASC_LPAREN: {
87824 /* XXX: naming is inconsistent: ATOM_END_GROUP ends an ASSERT_START_LOOKAHEAD */
87825
87826 if (y == DUK_ASC_QUESTION) {
87827 if (DUK__L2() == DUK_ASC_EQUALS) {
87828 /* (?= */
87830 } else if (DUK__L2() == DUK_ASC_EXCLAMATION) {
87831 /* (?! */
87833 } else if (DUK__L2() == DUK_ASC_COLON) {
87834 /* (?: */
87836 } else {
87837 goto fail_group;
87838 }
87839 } else {
87840 /* ( */
87842 }
87843 break;
87844 }
87845 case DUK_ASC_RPAREN: {
87847 break;
87848 }
87849 case DUK_ASC_LBRACKET: {
87850 /*
87851 * To avoid creating a heavy intermediate value for the list of ranges,
87852 * only the start token ('[' or '[^') is parsed here. The regexp
87853 * compiler parses the ranges itself.
87854 */
87855
87856 /* XXX: with DUK_USE_ES6_REGEXP_SYNTAX we should allow left bracket
87857 * literal too, but it's not easy to parse without backtracking.
87858 */
87859
87861 if (y == DUK_ASC_CARET) {
87863 }
87864 break;
87865 }
87866#if !defined(DUK_USE_ES6_REGEXP_SYNTAX)
87867 case DUK_ASC_RCURLY:
87868 case DUK_ASC_RBRACKET: {
87869 /* Although these could be parsed as PatternCharacters unambiguously (here),
87870 * E5 Section 15.10.1 grammar explicitly forbids these as PatternCharacters.
87871 */
87872 goto fail_invalid_char;
87873 break;
87874 }
87875#endif
87876 case -1: {
87877 /* EOF */
87878 advtok = DUK__ADVTOK(0, DUK_TOK_EOF);
87879 break;
87880 }
87881 default: {
87882 /* PatternCharacter, all excluded characters are matched by cases above */
87883 advtok = DUK__ADVTOK(1, DUK_RETOK_ATOM_CHAR);
87884 out_token->num = (duk_uint32_t) x;
87885 break;
87886 }
87887 }
87888
87889 /*
87890 * Shared exit path
87891 */
87892
87893 DUK__ADVANCEBYTES(lex_ctx, advtok >> 8);
87894 out_token->t = advtok & 0xff;
87895 return;
87896
87897fail_token_limit:
87899 DUK_WO_NORETURN(return;);
87900
87901fail_escape:
87903 DUK_WO_NORETURN(return;);
87904
87905fail_group:
87907 DUK_WO_NORETURN(return;);
87908
87909#if !defined(DUK_USE_ES6_REGEXP_SYNTAX)
87910fail_invalid_char:
87912 DUK_WO_NORETURN(return;);
87913
87914fail_quantifier:
87916 DUK_WO_NORETURN(return;);
87917#endif
87918}
87920/*
87921 * Special parser for character classes; calls callback for every
87922 * range parsed and returns the number of ranges present.
87923 */
87924
87925/* XXX: this duplicates functionality in duk_regexp.c where a similar loop is
87926 * required anyway. We could use that BUT we need to update the regexp compiler
87927 * 'nranges' too. Work this out a bit more cleanly to save space.
87928 */
87929
87930/* XXX: the handling of character range detection is a bit convoluted.
87931 * Try to simplify and make smaller.
87932 */
87933
87934/* XXX: logic for handling character ranges is now incorrect, it will accept
87935 * e.g. [\d-z] whereas it should croak from it? SMJS accepts this too, though.
87936 *
87937 * Needs a read through and a lot of additional tests.
87938 */
87939
87942 duk_re_range_callback gen_range,
87943 void *userdata,
87944 const duk_uint16_t *ranges,
87945 duk_small_int_t num) {
87946 const duk_uint16_t *ranges_end;
87947
87948 DUK_UNREF(lex_ctx);
87949
87950 ranges_end = ranges + num;
87951 while (ranges < ranges_end) {
87952 /* mark range 'direct', bypass canonicalization (see Wiki) */
87953 gen_range(userdata, (duk_codepoint_t) ranges[0], (duk_codepoint_t) ranges[1], 1);
87954 ranges += 2;
87955 }
87956}
87957
87958DUK_INTERNAL void duk_lexer_parse_re_ranges(duk_lexer_ctx *lex_ctx, duk_re_range_callback gen_range, void *userdata) {
87959 duk_codepoint_t start = -1;
87960 duk_codepoint_t ch;
87962 duk_bool_t dash = 0;
87963 duk_small_uint_t adv = 0;
87964
87965 DUK_DD(DUK_DDPRINT("parsing regexp ranges"));
87966
87967 for (;;) {
87968 DUK__ADVANCECHARS(lex_ctx, adv);
87969 adv = 1;
87970
87971 x = DUK__L0();
87972
87973 ch = -1; /* not strictly necessary, but avoids "uninitialized variable" warnings */
87974 DUK_UNREF(ch);
87975
87976 if (x < 0) {
87977 goto fail_unterm_charclass;
87978 } else if (x == DUK_ASC_RBRACKET) {
87979 if (start >= 0) {
87980 gen_range(userdata, start, start, 0);
87981 }
87982 DUK__ADVANCECHARS(lex_ctx, 1); /* eat ']' before finishing */
87983 break;
87984 } else if (x == DUK_ASC_MINUS) {
87985 if (start >= 0 && !dash && DUK__L1() != DUK_ASC_RBRACKET) {
87986 /* '-' as a range indicator */
87987 dash = 1;
87988 continue;
87989 } else {
87990 /* '-' verbatim */
87991 ch = x;
87992 }
87993 } else if (x == DUK_ASC_BACKSLASH) {
87994 /*
87995 * The escapes are same as outside a character class, except that \b has a
87996 * different meaning, and \B and backreferences are prohibited (see E5
87997 * Section 15.10.2.19). However, it's difficult to share code because we
87998 * handle e.g. "\n" very differently: here we generate a single character
87999 * range for it.
88000 */
88001
88002 /* XXX: ES2015 surrogate pair handling. */
88003
88004 x = DUK__L1();
88005
88006 adv = 2;
88007
88008 if (x == DUK_ASC_LC_B) {
88009 /* Note: '\b' in char class is different than outside (assertion),
88010 * '\B' is not allowed and is caught by the duk_unicode_is_identifier_part()
88011 * check below.
88012 */
88013 ch = 0x0008;
88014 } else if (x == DUK_ASC_LC_F) {
88015 ch = 0x000c;
88016 } else if (x == DUK_ASC_LC_N) {
88017 ch = 0x000a;
88018 } else if (x == DUK_ASC_LC_T) {
88019 ch = 0x0009;
88020 } else if (x == DUK_ASC_LC_R) {
88021 ch = 0x000d;
88022 } else if (x == DUK_ASC_LC_V) {
88023 ch = 0x000b;
88024 } else if (x == DUK_ASC_LC_C) {
88025 x = DUK__L2();
88026 adv = 3;
88027 if ((x >= DUK_ASC_LC_A && x <= DUK_ASC_LC_Z) || (x >= DUK_ASC_UC_A && x <= DUK_ASC_UC_Z)) {
88028 ch = (x % 32);
88029 } else {
88030 goto fail_escape;
88031 }
88032 } else if (x == DUK_ASC_LC_X || x == DUK_ASC_LC_U) {
88033 /* The \u{H+} form is only allowed in Unicode mode which
88034 * we don't support yet.
88035 */
88036 ch = duk__lexer_parse_escape(lex_ctx, 0 /*allow_es6*/);
88037 adv = 0;
88038 } else if (x == DUK_ASC_LC_D) {
88040 gen_range,
88041 userdata,
88043 sizeof(duk_unicode_re_ranges_digit) / sizeof(duk_uint16_t));
88044 ch = -1;
88045 } else if (x == DUK_ASC_UC_D) {
88047 gen_range,
88048 userdata,
88050 sizeof(duk_unicode_re_ranges_not_digit) / sizeof(duk_uint16_t));
88051 ch = -1;
88052 } else if (x == DUK_ASC_LC_S) {
88054 gen_range,
88055 userdata,
88057 sizeof(duk_unicode_re_ranges_white) / sizeof(duk_uint16_t));
88058 ch = -1;
88059 } else if (x == DUK_ASC_UC_S) {
88061 gen_range,
88062 userdata,
88064 sizeof(duk_unicode_re_ranges_not_white) / sizeof(duk_uint16_t));
88065 ch = -1;
88066 } else if (x == DUK_ASC_LC_W) {
88068 gen_range,
88069 userdata,
88071 sizeof(duk_unicode_re_ranges_wordchar) / sizeof(duk_uint16_t));
88072 ch = -1;
88073 } else if (x == DUK_ASC_UC_W) {
88075 gen_range,
88076 userdata,
88078 sizeof(duk_unicode_re_ranges_not_wordchar) / sizeof(duk_uint16_t));
88079 ch = -1;
88080 } else if (DUK__ISDIGIT(x)) {
88081 /* DecimalEscape, only \0 is allowed, no leading
88082 * zeroes are allowed.
88083 *
88084 * ES2015 Annex B also allows (maximal match) legacy
88085 * octal escapes up to \377 and \8 and \9 are
88086 * accepted as literal '8' and '9', also in strict mode.
88087 */
88088
88089#if defined(DUK_USE_ES6_REGEXP_SYNTAX)
88090 ch = duk__lexer_parse_legacy_octal(lex_ctx, &adv, 0 /*reject_annex_b*/);
88091 DUK_ASSERT(ch >= 0); /* no rejections */
88092#else
88093 if (x == DUK_ASC_0 && !DUK__ISDIGIT(DUK__L2())) {
88094 ch = 0x0000;
88095 } else {
88096 goto fail_escape;
88097 }
88098#endif
88099#if defined(DUK_USE_ES6_REGEXP_SYNTAX)
88100 } else if (x >= 0) {
88101 /* IdentityEscape: ES2015 Annex B allows almost all
88102 * source characters here. Match anything except
88103 * EOF here.
88104 */
88105 ch = x;
88106#else /* DUK_USE_ES6_REGEXP_SYNTAX */
88107 } else if (!duk_unicode_is_identifier_part(x)) {
88108 /* IdentityEscape: ES5.1 doesn't allow identity escape
88109 * for identifier part characters, which conflicts with
88110 * some real world code. For example, it doesn't allow
88111 * /[\$]/ which is awkward.
88112 */
88113 ch = x;
88114#endif /* DUK_USE_ES6_REGEXP_SYNTAX */
88115 } else {
88116 goto fail_escape;
88117 }
88118 } else {
88119 /* character represents itself */
88120 ch = x;
88121 }
88122
88123 /* ch is a literal character here or -1 if parsed entity was
88124 * an escape such as "\s".
88125 */
88126
88127 if (ch < 0) {
88128 /* multi-character sets not allowed as part of ranges, see
88129 * E5 Section 15.10.2.15, abstract operation CharacterRange.
88130 */
88131 if (start >= 0) {
88132 if (dash) {
88133 goto fail_range;
88134 } else {
88135 gen_range(userdata, start, start, 0);
88136 start = -1;
88137 /* dash is already 0 */
88138 }
88139 }
88140 } else {
88141 if (start >= 0) {
88142 if (dash) {
88143 if (start > ch) {
88144 goto fail_range;
88145 }
88146 gen_range(userdata, start, ch, 0);
88147 start = -1;
88148 dash = 0;
88149 } else {
88150 gen_range(userdata, start, start, 0);
88151 start = ch;
88152 /* dash is already 0 */
88153 }
88154 } else {
88155 start = ch;
88156 }
88157 }
88158 }
88159
88160 return;
88161
88162fail_escape:
88164 DUK_WO_NORETURN(return;);
88165
88166fail_range:
88168 DUK_WO_NORETURN(return;);
88169
88170fail_unterm_charclass:
88172 DUK_WO_NORETURN(return;);
88175#endif /* DUK_USE_REGEXP_SUPPORT */
88177/* automatic undefs */
88178#undef DUK__ADVANCEBYTES
88179#undef DUK__ADVANCECHARS
88180#undef DUK__ADVTOK
88181#undef DUK__APPENDBUFFER
88182#undef DUK__APPENDBUFFER_ASCII
88183#undef DUK__INITBUFFER
88184#undef DUK__ISDIGIT
88185#undef DUK__ISDIGIT03
88186#undef DUK__ISDIGIT47
88187#undef DUK__ISHEXDIGIT
88188#undef DUK__ISOCTDIGIT
88189#undef DUK__L0
88190#undef DUK__L1
88191#undef DUK__L2
88192#undef DUK__L3
88193#undef DUK__L4
88194#undef DUK__L5
88195#undef DUK__LOOKUP
88196#undef DUK__MAX_RE_DECESC_DIGITS
88197#undef DUK__MAX_RE_QUANT_DIGITS
88198/*
88199 * Number-to-string and string-to-number conversions.
88201 * Slow path number-to-string and string-to-number conversion is based on
88202 * a Dragon4 variant, with fast paths for small integers. Big integer
88203 * arithmetic is needed for guaranteeing that the conversion is correct
88204 * and uses a minimum number of digits. The big number arithmetic has a
88205 * fixed maximum size and does not require dynamic allocations.
88206 *
88207 * See: doc/number-conversion.rst.
88208 */
88209
88210/* #include duk_internal.h -> already included */
88211
88212#define DUK__IEEE_DOUBLE_EXP_BIAS 1023
88213#define DUK__IEEE_DOUBLE_EXP_MIN (-1022) /* biased exp == 0 -> denormal, exp -1022 */
88214
88215#define DUK__DIGITCHAR(x) duk_lc_digits[(x)]
88216
88217/*
88218 * Tables generated with util/gennumdigits.py.
88219 *
88220 * duk__str2num_digits_for_radix indicates, for each radix, how many input
88221 * digits should be considered significant for string-to-number conversion.
88222 * The input is also padded to this many digits to give the Dragon4
88223 * conversion enough (apparent) precision to work with.
88224 *
88225 * duk__str2num_exp_limits indicates, for each radix, the radix-specific
88226 * minimum/maximum exponent values (for a Dragon4 integer mantissa)
88227 * below and above which the number is guaranteed to underflow to zero
88228 * or overflow to Infinity. This allows parsing to keep bigint values
88229 * bounded.
88230 */
88231
88232DUK_LOCAL const duk_uint8_t duk__str2num_digits_for_radix[] = {
88233 69, 44, 35, 30, 27, 25, 23, 22, 20, 20, /* 2 to 11 */
88234 20, 19, 19, 18, 18, 17, 17, 17, 16, 16, /* 12 to 21 */
88235 16, 16, 16, 15, 15, 15, 15, 15, 15, 14, /* 22 to 31 */
88236 14, 14, 14, 14, 14 /* 31 to 36 */
88239typedef struct {
88240 duk_int16_t upper;
88241 duk_int16_t lower;
88243
88245 { 957, -1147 }, { 605, -725 }, { 479, -575 }, { 414, -496 }, { 372, -446 }, { 342, -411 }, { 321, -384 },
88246 { 304, -364 }, { 291, -346 }, { 279, -334 }, { 268, -323 }, { 260, -312 }, { 252, -304 }, { 247, -296 },
88247 { 240, -289 }, { 236, -283 }, { 231, -278 }, { 227, -273 }, { 223, -267 }, { 220, -263 }, { 216, -260 },
88248 { 213, -256 }, { 210, -253 }, { 208, -249 }, { 205, -246 }, { 203, -244 }, { 201, -241 }, { 198, -239 },
88249 { 196, -237 }, { 195, -234 }, { 193, -232 }, { 191, -230 }, { 190, -228 }, { 188, -226 }, { 187, -225 },
88250};
88251
88252/*
88253 * Limited functionality bigint implementation.
88254 *
88255 * Restricted to non-negative numbers with less than 32 * DUK__BI_MAX_PARTS bits,
88256 * with the caller responsible for ensuring this is never exceeded. No memory
88257 * allocation (except stack) is needed for bigint computation. Operations
88258 * have been tailored for number conversion needs.
88259 *
88260 * Argument order is "assignment order", i.e. target first, then arguments:
88261 * x <- y * z --> duk__bi_mul(x, y, z);
88262 */
88263
88264/* This upper value has been experimentally determined; debug build will check
88265 * bigint size with assertions.
88266 */
88267#define DUK__BI_MAX_PARTS 37 /* 37x32 = 1184 bits */
88268
88269#if defined(DUK_USE_DEBUG_LEVEL) && (DUK_USE_DEBUG_LEVEL >= 2)
88270#define DUK__BI_PRINT(name, x) duk__bi_print((name), (x))
88271#else
88272#define DUK__BI_PRINT(name, x)
88273#endif
88274
88275/* Current size is about 152 bytes. */
88276typedef struct {
88278 duk_uint32_t v[DUK__BI_MAX_PARTS]; /* low to high */
88279} duk__bigint;
88280
88281#if defined(DUK_USE_DEBUG_LEVEL) && (DUK_USE_DEBUG_LEVEL >= 2)
88282DUK_LOCAL void duk__bi_print(const char *name, duk__bigint *x) {
88283 /* Overestimate required size; debug code so not critical to be tight. */
88284 char buf[DUK__BI_MAX_PARTS * 9 + 64];
88285 char *p = buf;
88287
88288 /* No NUL term checks in this debug code. */
88289 p += DUK_SPRINTF(p, "%p n=%ld", (void *) x, (long) x->n);
88290 if (x->n == 0) {
88291 p += DUK_SPRINTF(p, " 0");
88292 }
88293 for (i = x->n - 1; i >= 0; i--) {
88294 p += DUK_SPRINTF(p, " %08lx", (unsigned long) x->v[i]);
88295 }
88296
88297 DUK_DDD(DUK_DDDPRINT("%s: %s", (const char *) name, (const char *) buf));
88298}
88299#endif
88300
88301#if defined(DUK_USE_ASSERTIONS)
88302DUK_LOCAL duk_small_int_t duk__bi_is_valid(duk__bigint *x) {
88303 return (duk_small_int_t) (((x->n >= 0) && (x->n <= DUK__BI_MAX_PARTS)) /* is valid size */ &&
88304 ((x->n == 0) || (x->v[x->n - 1] != 0)) /* is normalized */);
88305}
88306#endif
88310
88311 for (i = x->n - 1; i >= 0; i--) {
88312 if (x->v[i] != 0) {
88313 break;
88314 }
88315 }
88316
88317 /* Note: if 'x' is zero, x->n becomes 0 here */
88318 x->n = i + 1;
88319 DUK_ASSERT(duk__bi_is_valid(x));
88320}
88321
88322/* x <- y */
88325
88326 n = y->n;
88327 x->n = n;
88328 /* No need to special case n == 0. */
88329 duk_memcpy((void *) x->v, (const void *) y->v, (size_t) (sizeof(duk_uint32_t) * (size_t) n));
88330}
88331
88332DUK_LOCAL void duk__bi_set_small(duk__bigint *x, duk_uint32_t v) {
88333 if (v == 0U) {
88334 x->n = 0;
88335 } else {
88336 x->n = 1;
88337 x->v[0] = v;
88338 }
88339 DUK_ASSERT(duk__bi_is_valid(x));
88340}
88341
88342/* Return value: <0 <=> x < y
88343 * 0 <=> x == y
88344 * >0 <=> x > y
88345 */
88347 duk_small_int_t i, nx, ny;
88348 duk_uint32_t tx, ty;
88349
88350 DUK_ASSERT(duk__bi_is_valid(x));
88351 DUK_ASSERT(duk__bi_is_valid(y));
88352
88353 nx = x->n;
88354 ny = y->n;
88355 if (nx > ny) {
88356 goto ret_gt;
88357 }
88358 if (nx < ny) {
88359 goto ret_lt;
88360 }
88361 for (i = nx - 1; i >= 0; i--) {
88362 tx = x->v[i];
88363 ty = y->v[i];
88364
88365 if (tx > ty) {
88366 goto ret_gt;
88367 }
88368 if (tx < ty) {
88369 goto ret_lt;
88370 }
88371 }
88372
88373 return 0;
88374
88375ret_gt:
88376 return 1;
88377
88378ret_lt:
88379 return -1;
88380}
88381
88382/* x <- y + z */
88383#if defined(DUK_USE_64BIT_OPS)
88385 duk_uint64_t tmp;
88386 duk_small_int_t i, ny, nz;
88387
88388 DUK_ASSERT(duk__bi_is_valid(y));
88389 DUK_ASSERT(duk__bi_is_valid(z));
88390
88391 if (z->n > y->n) {
88392 duk__bigint *t;
88393 t = y;
88394 y = z;
88395 z = t;
88396 }
88397 DUK_ASSERT(y->n >= z->n);
88398
88399 ny = y->n;
88400 nz = z->n;
88401 tmp = 0U;
88402 for (i = 0; i < ny; i++) {
88404 tmp += y->v[i];
88405 if (i < nz) {
88406 tmp += z->v[i];
88407 }
88408 x->v[i] = (duk_uint32_t) (tmp & 0xffffffffUL);
88409 tmp = tmp >> 32;
88410 }
88411 if (tmp != 0U) {
88413 x->v[i++] = (duk_uint32_t) tmp;
88414 }
88415 x->n = i;
88417
88418 /* no need to normalize */
88419 DUK_ASSERT(duk__bi_is_valid(x));
88420}
88421#else /* DUK_USE_64BIT_OPS */
88423 duk_uint32_t carry, tmp1, tmp2;
88424 duk_small_int_t i, ny, nz;
88425
88426 DUK_ASSERT(duk__bi_is_valid(y));
88427 DUK_ASSERT(duk__bi_is_valid(z));
88428
88429 if (z->n > y->n) {
88430 duk__bigint *t;
88431 t = y;
88432 y = z;
88433 z = t;
88434 }
88435 DUK_ASSERT(y->n >= z->n);
88436
88437 ny = y->n;
88438 nz = z->n;
88439 carry = 0U;
88440 for (i = 0; i < ny; i++) {
88441 /* Carry is detected based on wrapping which relies on exact 32-bit
88442 * types.
88443 */
88445 tmp1 = y->v[i];
88446 tmp2 = tmp1;
88447 if (i < nz) {
88448 tmp2 += z->v[i];
88449 }
88450
88451 /* Careful with carry condition:
88452 * - If carry not added: 0x12345678 + 0 + 0xffffffff = 0x12345677 (< 0x12345678)
88453 * - If carry added: 0x12345678 + 1 + 0xffffffff = 0x12345678 (== 0x12345678)
88454 */
88455 if (carry) {
88456 tmp2++;
88457 carry = (tmp2 <= tmp1 ? 1U : 0U);
88458 } else {
88459 carry = (tmp2 < tmp1 ? 1U : 0U);
88460 }
88461
88462 x->v[i] = tmp2;
88463 }
88464 if (carry) {
88466 DUK_ASSERT(carry == 1U);
88467 x->v[i++] = carry;
88468 }
88469 x->n = i;
88471
88472 /* no need to normalize */
88473 DUK_ASSERT(duk__bi_is_valid(x));
88474}
88475#endif /* DUK_USE_64BIT_OPS */
88476
88477/* x <- y + z */
88478DUK_LOCAL void duk__bi_add_small(duk__bigint *x, duk__bigint *y, duk_uint32_t z) {
88479 duk__bigint tmp;
88480
88481 DUK_ASSERT(duk__bi_is_valid(y));
88482
88483 /* XXX: this could be optimized; there is only one call site now though */
88484 duk__bi_set_small(&tmp, z);
88485 duk__bi_add(x, y, &tmp);
88486
88487 DUK_ASSERT(duk__bi_is_valid(x));
88488}
88489
88490#if 0 /* unused */
88491/* x <- x + y, use t as temp */
88492DUK_LOCAL void duk__bi_add_copy(duk__bigint *x, duk__bigint *y, duk__bigint *t) {
88493 duk__bi_add(t, x, y);
88494 duk__bi_copy(x, t);
88495}
88496#endif
88497
88498/* x <- y - z, require x >= y => z >= 0, i.e. y >= z */
88499#if defined(DUK_USE_64BIT_OPS)
88501 duk_small_int_t i, ny, nz;
88502 duk_uint32_t ty, tz;
88503 duk_int64_t tmp;
88504
88505 DUK_ASSERT(duk__bi_is_valid(y));
88506 DUK_ASSERT(duk__bi_is_valid(z));
88507 DUK_ASSERT(duk__bi_compare(y, z) >= 0);
88508 DUK_ASSERT(y->n >= z->n);
88509
88510 ny = y->n;
88511 nz = z->n;
88512 tmp = 0;
88513 for (i = 0; i < ny; i++) {
88514 ty = y->v[i];
88515 if (i < nz) {
88516 tz = z->v[i];
88517 } else {
88518 tz = 0;
88519 }
88520 tmp = (duk_int64_t) ty - (duk_int64_t) tz + tmp;
88521 x->v[i] = (duk_uint32_t) ((duk_uint64_t) tmp & 0xffffffffUL);
88522 tmp = tmp >> 32; /* 0 or -1 */
88523 }
88524 DUK_ASSERT(tmp == 0);
88525
88526 x->n = i;
88527 duk__bi_normalize(x); /* need to normalize, may even cancel to 0 */
88528 DUK_ASSERT(duk__bi_is_valid(x));
88529}
88530#else
88532 duk_small_int_t i, ny, nz;
88533 duk_uint32_t tmp1, tmp2, borrow;
88534
88535 DUK_ASSERT(duk__bi_is_valid(y));
88536 DUK_ASSERT(duk__bi_is_valid(z));
88537 DUK_ASSERT(duk__bi_compare(y, z) >= 0);
88538 DUK_ASSERT(y->n >= z->n);
88539
88540 ny = y->n;
88541 nz = z->n;
88542 borrow = 0U;
88543 for (i = 0; i < ny; i++) {
88544 /* Borrow is detected based on wrapping which relies on exact 32-bit
88545 * types.
88546 */
88547 tmp1 = y->v[i];
88548 tmp2 = tmp1;
88549 if (i < nz) {
88550 tmp2 -= z->v[i];
88552
88553 /* Careful with borrow condition:
88554 * - If borrow not subtracted: 0x12345678 - 0 - 0xffffffff = 0x12345679 (> 0x12345678)
88555 * - If borrow subtracted: 0x12345678 - 1 - 0xffffffff = 0x12345678 (== 0x12345678)
88556 */
88557 if (borrow) {
88558 tmp2--;
88559 borrow = (tmp2 >= tmp1 ? 1U : 0U);
88560 } else {
88561 borrow = (tmp2 > tmp1 ? 1U : 0U);
88562 }
88563
88564 x->v[i] = tmp2;
88565 }
88566 DUK_ASSERT(borrow == 0U);
88567
88568 x->n = i;
88569 duk__bi_normalize(x); /* need to normalize, may even cancel to 0 */
88570 DUK_ASSERT(duk__bi_is_valid(x));
88571}
88572#endif
88573
88574#if 0 /* unused */
88575/* x <- y - z */
88576DUK_LOCAL void duk__bi_sub_small(duk__bigint *x, duk__bigint *y, duk_uint32_t z) {
88577 duk__bigint tmp;
88578
88579 DUK_ASSERT(duk__bi_is_valid(y));
88580
88581 /* XXX: this could be optimized */
88582 duk__bi_set_small(&tmp, z);
88583 duk__bi_sub(x, y, &tmp);
88584
88585 DUK_ASSERT(duk__bi_is_valid(x));
88586}
88587#endif
88588
88589/* x <- x - y, use t as temp */
88591 duk__bi_sub(t, x, y);
88592 duk__bi_copy(x, t);
88593}
88594
88595/* x <- y * z */
88597 duk_small_int_t i, j, nx, nz;
88598
88599 DUK_ASSERT(duk__bi_is_valid(y));
88600 DUK_ASSERT(duk__bi_is_valid(z));
88601
88602 nx = y->n + z->n; /* max possible */
88604
88605 if (nx == 0) {
88606 /* Both inputs are zero; cases where only one is zero can go
88607 * through main algorithm.
88608 */
88609 x->n = 0;
88610 return;
88611 }
88612
88613 duk_memzero((void *) x->v, (size_t) (sizeof(duk_uint32_t) * (size_t) nx));
88614 x->n = nx;
88615
88616 nz = z->n;
88617 for (i = 0; i < y->n; i++) {
88618#if defined(DUK_USE_64BIT_OPS)
88619 duk_uint64_t tmp = 0U;
88620 for (j = 0; j < nz; j++) {
88621 tmp += (duk_uint64_t) y->v[i] * (duk_uint64_t) z->v[j] + x->v[i + j];
88622 x->v[i + j] = (duk_uint32_t) (tmp & 0xffffffffUL);
88623 tmp = tmp >> 32;
88624 }
88625 if (tmp > 0) {
88626 DUK_ASSERT(i + j < nx);
88628 DUK_ASSERT(x->v[i + j] == 0U);
88629 x->v[i + j] = (duk_uint32_t) tmp;
88630 }
88631#else
88632 /*
88633 * Multiply + add + carry for 32-bit components using only 16x16->32
88634 * multiplies and carry detection based on unsigned overflow.
88635 *
88636 * 1st mult, 32-bit: (A*2^16 + B)
88637 * 2nd mult, 32-bit: (C*2^16 + D)
88638 * 3rd add, 32-bit: E
88639 * 4th add, 32-bit: F
88640 *
88641 * (AC*2^16 + B) * (C*2^16 + D) + E + F
88642 * = AC*2^32 + AD*2^16 + BC*2^16 + BD + E + F
88643 * = AC*2^32 + (AD + BC)*2^16 + (BD + E + F)
88644 * = AC*2^32 + AD*2^16 + BC*2^16 + (BD + E + F)
88645 */
88646 duk_uint32_t a, b, c, d, e, f;
88647 duk_uint32_t r, s, t;
88648
88649 a = y->v[i];
88650 b = a & 0xffffUL;
88651 a = a >> 16;
88652
88653 f = 0;
88654 for (j = 0; j < nz; j++) {
88655 c = z->v[j];
88656 d = c & 0xffffUL;
88657 c = c >> 16;
88658 e = x->v[i + j];
88659
88660 /* build result as: (r << 32) + s: start with (BD + E + F) */
88661 r = 0;
88662 s = b * d;
88663
88664 /* add E */
88665 t = s + e;
88666 if (t < s) {
88667 r++;
88668 } /* carry */
88669 s = t;
88670
88671 /* add F */
88672 t = s + f;
88673 if (t < s) {
88674 r++;
88675 } /* carry */
88676 s = t;
88677
88678 /* add BC*2^16 */
88679 t = b * c;
88680 r += (t >> 16);
88681 t = s + ((t & 0xffffUL) << 16);
88682 if (t < s) {
88683 r++;
88684 } /* carry */
88685 s = t;
88686
88687 /* add AD*2^16 */
88688 t = a * d;
88689 r += (t >> 16);
88690 t = s + ((t & 0xffffUL) << 16);
88691 if (t < s) {
88692 r++;
88693 } /* carry */
88694 s = t;
88695
88696 /* add AC*2^32 */
88697 t = a * c;
88698 r += t;
88699
88700 DUK_DDD(DUK_DDDPRINT("ab=%08lx cd=%08lx ef=%08lx -> rs=%08lx %08lx",
88701 (unsigned long) y->v[i],
88702 (unsigned long) z->v[j],
88703 (unsigned long) x->v[i + j],
88704 (unsigned long) r,
88705 (unsigned long) s));
88706
88707 x->v[i + j] = s;
88708 f = r;
88710 if (f > 0U) {
88711 DUK_ASSERT(i + j < nx);
88713 DUK_ASSERT(x->v[i + j] == 0U);
88714 x->v[i + j] = (duk_uint32_t) f;
88715 }
88716#endif /* DUK_USE_64BIT_OPS */
88717 }
88718
88720 DUK_ASSERT(duk__bi_is_valid(x));
88721}
88722
88723/* x <- y * z */
88724DUK_LOCAL void duk__bi_mul_small(duk__bigint *x, duk__bigint *y, duk_uint32_t z) {
88726
88727 DUK_ASSERT(duk__bi_is_valid(y));
88728
88729 /* XXX: this could be optimized */
88730 duk__bi_set_small(&tmp, z);
88731 duk__bi_mul(x, y, &tmp);
88732
88733 DUK_ASSERT(duk__bi_is_valid(x));
88734}
88735
88736/* x <- x * y, use t as temp */
88738 duk__bi_mul(t, x, y);
88739 duk__bi_copy(x, t);
88740}
88741
88742/* x <- x * y, use t as temp */
88744 duk__bi_mul_small(t, x, y);
88745 duk__bi_copy(x, t);
88746}
88747
88749 DUK_ASSERT(duk__bi_is_valid(x));
88750 return (x->n == 0) || ((x->v[0] & 0x01) == 0);
88751}
88752
88754 DUK_ASSERT(duk__bi_is_valid(x));
88755 return (x->n == 0); /* this is the case for normalized numbers */
88756}
88757
88758/* Bigint is 2^52. Used to detect normalized IEEE double mantissa values
88759 * which are at the lowest edge (next floating point value downwards has
88760 * a different exponent). The lowest mantissa has the form:
88761 *
88762 * 1000........000 (52 zeroes; only "hidden bit" is set)
88763 */
88765 DUK_ASSERT(duk__bi_is_valid(x));
88766 return (duk_small_int_t) (x->n == 2) && (x->v[0] == 0U) && (x->v[1] == (1U << (52 - 32)));
88767}
88768
88769/* x <- (1<<y) */
88771 duk_small_int_t n, r;
88772
88773 n = (y / 32) + 1;
88774 DUK_ASSERT(n > 0);
88775 r = y % 32;
88776 duk_memzero((void *) x->v, sizeof(duk_uint32_t) * (size_t) n);
88777 x->n = n;
88778 x->v[n - 1] = (((duk_uint32_t) 1) << r);
88779}
88780
88781/* x <- b^y; use t1 and t2 as temps */
88783 /* Fast path the binary case */
88784
88785 DUK_ASSERT(x != t1 && x != t2 && t1 != t2); /* distinct bignums, easy mistake to make */
88786 DUK_ASSERT(b >= 0);
88787 DUK_ASSERT(y >= 0);
88788
88789 if (b == 2) {
88790 duk__bi_twoexp(x, y);
88791 return;
88792 }
88793
88794 /* http://en.wikipedia.org/wiki/Exponentiation_by_squaring */
88795
88796 DUK_DDD(DUK_DDDPRINT("exp_small: b=%ld, y=%ld", (long) b, (long) y));
88797
88798 duk__bi_set_small(x, 1);
88799 duk__bi_set_small(t1, (duk_uint32_t) b);
88800 for (;;) {
88801 /* Loop structure ensures that we don't compute t1^2 unnecessarily
88802 * on the final round, as that might create a bignum exceeding the
88803 * current DUK__BI_MAX_PARTS limit.
88805 if (y & 0x01) {
88806 duk__bi_mul_copy(x, t1, t2);
88808 y = y >> 1;
88809 if (y == 0) {
88810 break;
88811 }
88812 duk__bi_mul_copy(t1, t1, t2);
88813 }
88814
88815 DUK__BI_PRINT("exp_small result", x);
88817
88819 * A Dragon4 number-to-string variant, based on:
88821 * Guy L. Steele Jr., Jon L. White: "How to Print Floating-Point Numbers
88822 * Accurately"
88824 * Robert G. Burger, R. Kent Dybvig: "Printing Floating-Point Numbers
88825 * Quickly and Accurately"
88827 * The current algorithm is based on Figure 1 of the Burger-Dybvig paper,
88828 * i.e. the base implementation without logarithm estimation speedups
88829 * (these would increase code footprint considerably). Fixed-format output
88830 * does not follow the suggestions in the paper; instead, we generate an
88831 * extra digit and round-with-carry.
88833 * The same algorithm is used for number parsing (with b=10 and B=2)
88834 * by generating one extra digit and doing rounding manually.
88835 *
88836 * See doc/number-conversion.rst for limitations.
88837 */
88838
88839/* Maximum number of digits generated. */
88840#define DUK__MAX_OUTPUT_DIGITS 1040 /* (Number.MAX_VALUE).toString(2).length == 1024, + slack */
88841
88842/* Maximum number of characters in formatted value. */
88843#define DUK__MAX_FORMATTED_LENGTH 1040 /* (-Number.MAX_VALUE).toString(2).length == 1025, + slack */
88844
88845/* Number and (minimum) size of bigints in the nc_ctx structure. */
88846#define DUK__NUMCONV_CTX_NUM_BIGINTS 7
88847#define DUK__NUMCONV_CTX_BIGINTS_SIZE (sizeof(duk__bigint) * DUK__NUMCONV_CTX_NUM_BIGINTS)
88848
88849typedef struct {
88850 /* Currently about 7*152 = 1064 bytes. The space for these
88851 * duk__bigints is used also as a temporary buffer for generating
88852 * the final string. This is a bit awkard; a union would be
88853 * more correct.
88854 */
88855 duk__bigint f, r, s, mp, mm, t1, t2;
88856
88857 duk_small_int_t is_s2n; /* if 1, doing a string-to-number; else doing a number-to-string */
88858 duk_small_int_t is_fixed; /* if 1, doing a fixed format output (not free format) */
88859 duk_small_int_t req_digits; /* requested number of output digits; 0 = free-format */
88860 duk_small_int_t abs_pos; /* digit position is absolute, not relative */
88861 duk_small_int_t e; /* exponent for 'f' */
88862 duk_small_int_t b; /* input radix */
88863 duk_small_int_t B; /* output radix */
88864 duk_small_int_t k; /* see algorithm */
88865 duk_small_int_t low_ok; /* see algorithm */
88866 duk_small_int_t high_ok; /* see algorithm */
88867 duk_small_int_t unequal_gaps; /* m+ != m- (very rarely) */
88868
88869 /* Buffer used for generated digits, values are in the range [0,B-1]. */
88870 duk_uint8_t digits[DUK__MAX_OUTPUT_DIGITS];
88871 duk_small_int_t count; /* digit count */
88873
88874/* Note: computes with 'idx' in assertions, so caller beware.
88875 * 'idx' is preincremented, i.e. '1' on first call, because it
88876 * is more convenient for the caller.
88877 */
88878#define DUK__DRAGON4_OUTPUT_PREINC(nc_ctx, preinc_idx, x) \
88879 do { \
88880 DUK_ASSERT((preinc_idx) -1 >= 0); \
88881 DUK_ASSERT((preinc_idx) -1 < DUK__MAX_OUTPUT_DIGITS); \
88882 ((nc_ctx)->digits[(preinc_idx) -1]) = (duk_uint8_t) (x); \
88883 } while (0)
88884
88885DUK_LOCAL duk_size_t duk__dragon4_format_uint32(duk_uint8_t *buf, duk_uint32_t x, duk_small_int_t radix) {
88886 duk_uint8_t *p;
88887 duk_size_t len;
88888 duk_small_int_t dig;
88889 duk_uint32_t t;
88890
88891 DUK_ASSERT(buf != NULL);
88892 DUK_ASSERT(radix >= 2 && radix <= 36);
88893
88894 /* A 32-bit unsigned integer formats to at most 32 digits (the
88895 * worst case happens with radix == 2). Output the digits backwards,
88896 * and use a memmove() to get them in the right place.
88897 */
88898
88899 p = buf + 32;
88900 for (;;) {
88901 t = x / (duk_uint32_t) radix;
88902 dig = (duk_small_int_t) (x - t * (duk_uint32_t) radix);
88903 x = t;
88904
88905 DUK_ASSERT(dig >= 0 && dig < 36);
88906 *(--p) = DUK__DIGITCHAR(dig);
88907
88908 if (x == 0) {
88909 break;
88910 }
88911 }
88912 len = (duk_size_t) ((buf + 32) - p);
88913
88914 duk_memmove((void *) buf, (const void *) p, (size_t) len);
88915
88916 return len;
88917}
88918
88920 duk_small_int_t lowest_mantissa;
88921
88922#if 1
88923 /* Assume IEEE round-to-even, so that shorter encoding can be used
88924 * when round-to-even would produce correct result. By removing
88925 * this check (and having low_ok == high_ok == 0) the results would
88926 * still be accurate but in some cases longer than necessary.
88927 */
88928 if (duk__bi_is_even(&nc_ctx->f)) {
88929 DUK_DDD(DUK_DDDPRINT("f is even"));
88930 nc_ctx->low_ok = 1;
88931 nc_ctx->high_ok = 1;
88932 } else {
88933 DUK_DDD(DUK_DDDPRINT("f is odd"));
88934 nc_ctx->low_ok = 0;
88935 nc_ctx->high_ok = 0;
88936 }
88937#else
88938 /* Note: not honoring round-to-even should work but now generates incorrect
88939 * results. For instance, 1e23 serializes to "a000...", i.e. the first digit
88940 * equals the radix (10). Scaling stops one step too early in this case.
88941 * Don't know why this is the case, but since this code path is unused, it
88942 * doesn't matter.
88943 */
88944 nc_ctx->low_ok = 0;
88945 nc_ctx->high_ok = 0;
88946#endif
88947
88948 /* For string-to-number, pretend we never have the lowest mantissa as there
88949 * is no natural "precision" for inputs. Having lowest_mantissa == 0, we'll
88950 * fall into the base cases for both e >= 0 and e < 0.
88951 */
88952 if (nc_ctx->is_s2n) {
88953 lowest_mantissa = 0;
88954 } else {
88955 lowest_mantissa = duk__bi_is_2to52(&nc_ctx->f);
88956 }
88957
88958 nc_ctx->unequal_gaps = 0;
88959 if (nc_ctx->e >= 0) {
88960 /* exponent non-negative (and thus not minimum exponent) */
88961
88962 if (lowest_mantissa) {
88963 /* (>= e 0) AND (= f (expt b (- p 1)))
88964 *
88965 * be <- (expt b e) == b^e
88966 * be1 <- (* be b) == (expt b (+ e 1)) == b^(e+1)
88967 * r <- (* f be1 2) == 2 * f * b^(e+1) [if b==2 -> f * b^(e+2)]
88968 * s <- (* b 2) [if b==2 -> 4]
88969 * m+ <- be1 == b^(e+1)
88970 * m- <- be == b^e
88971 * k <- 0
88972 * B <- B
88973 * low_ok <- round
88974 * high_ok <- round
88975 */
88976
88977 DUK_DDD(DUK_DDDPRINT("non-negative exponent (not smallest exponent); "
88978 "lowest mantissa value for this exponent -> "
88979 "unequal gaps"));
88980
88981 duk__bi_exp_small(&nc_ctx->mm, nc_ctx->b, nc_ctx->e, &nc_ctx->t1, &nc_ctx->t2); /* mm <- b^e */
88982 duk__bi_mul_small(&nc_ctx->mp, &nc_ctx->mm, (duk_uint32_t) nc_ctx->b); /* mp <- b^(e+1) */
88983 duk__bi_mul_small(&nc_ctx->t1, &nc_ctx->f, 2);
88984 duk__bi_mul(&nc_ctx->r, &nc_ctx->t1, &nc_ctx->mp); /* r <- (2 * f) * b^(e+1) */
88985 duk__bi_set_small(&nc_ctx->s, (duk_uint32_t) (nc_ctx->b * 2)); /* s <- 2 * b */
88986 nc_ctx->unequal_gaps = 1;
88987 } else {
88988 /* (>= e 0) AND (not (= f (expt b (- p 1))))
88989 *
88990 * be <- (expt b e) == b^e
88991 * r <- (* f be 2) == 2 * f * b^e [if b==2 -> f * b^(e+1)]
88992 * s <- 2
88993 * m+ <- be == b^e
88994 * m- <- be == b^e
88995 * k <- 0
88996 * B <- B
88997 * low_ok <- round
88998 * high_ok <- round
88999 */
89000
89001 DUK_DDD(DUK_DDDPRINT("non-negative exponent (not smallest exponent); "
89002 "not lowest mantissa for this exponent -> "
89003 "equal gaps"));
89004
89005 duk__bi_exp_small(&nc_ctx->mm, nc_ctx->b, nc_ctx->e, &nc_ctx->t1, &nc_ctx->t2); /* mm <- b^e */
89006 duk__bi_copy(&nc_ctx->mp, &nc_ctx->mm); /* mp <- b^e */
89007 duk__bi_mul_small(&nc_ctx->t1, &nc_ctx->f, 2);
89008 duk__bi_mul(&nc_ctx->r, &nc_ctx->t1, &nc_ctx->mp); /* r <- (2 * f) * b^e */
89009 duk__bi_set_small(&nc_ctx->s, 2); /* s <- 2 */
89010 }
89011 } else {
89012 /* When doing string-to-number, lowest_mantissa is always 0 so
89013 * the exponent check, while incorrect, won't matter.
89014 */
89015 if (nc_ctx->e > DUK__IEEE_DOUBLE_EXP_MIN /*not minimum exponent*/ &&
89016 lowest_mantissa /* lowest mantissa for this exponent*/) {
89017 /* r <- (* f b 2) [if b==2 -> (* f 4)]
89018 * s <- (* (expt b (- 1 e)) 2) == b^(1-e) * 2 [if b==2 -> b^(2-e)]
89019 * m+ <- b == 2
89020 * m- <- 1
89021 * k <- 0
89022 * B <- B
89023 * low_ok <- round
89024 * high_ok <- round
89025 */
89026
89027 DUK_DDD(DUK_DDDPRINT("negative exponent; not minimum exponent and "
89028 "lowest mantissa for this exponent -> "
89029 "unequal gaps"));
89031 duk__bi_mul_small(&nc_ctx->r, &nc_ctx->f, (duk_uint32_t) (nc_ctx->b * 2)); /* r <- (2 * b) * f */
89032 duk__bi_exp_small(&nc_ctx->t1,
89033 nc_ctx->b,
89034 1 - nc_ctx->e,
89035 &nc_ctx->s,
89036 &nc_ctx->t2); /* NB: use 's' as temp on purpose */
89037 duk__bi_mul_small(&nc_ctx->s, &nc_ctx->t1, 2); /* s <- b^(1-e) * 2 */
89038 duk__bi_set_small(&nc_ctx->mp, 2);
89039 duk__bi_set_small(&nc_ctx->mm, 1);
89040 nc_ctx->unequal_gaps = 1;
89041 } else {
89042 /* r <- (* f 2)
89043 * s <- (* (expt b (- e)) 2) == b^(-e) * 2 [if b==2 -> b^(1-e)]
89044 * m+ <- 1
89045 * m- <- 1
89046 * k <- 0
89047 * B <- B
89048 * low_ok <- round
89049 * high_ok <- round
89050 */
89051
89052 DUK_DDD(DUK_DDDPRINT("negative exponent; minimum exponent or not "
89053 "lowest mantissa for this exponent -> "
89054 "equal gaps"));
89055
89056 duk__bi_mul_small(&nc_ctx->r, &nc_ctx->f, 2); /* r <- 2 * f */
89057 duk__bi_exp_small(&nc_ctx->t1,
89058 nc_ctx->b,
89059 -nc_ctx->e,
89060 &nc_ctx->s,
89061 &nc_ctx->t2); /* NB: use 's' as temp on purpose */
89062 duk__bi_mul_small(&nc_ctx->s, &nc_ctx->t1, 2); /* s <- b^(-e) * 2 */
89063 duk__bi_set_small(&nc_ctx->mp, 1);
89064 duk__bi_set_small(&nc_ctx->mm, 1);
89065 }
89066 }
89067}
89068
89070 duk_small_int_t k = 0;
89071
89072 /* This is essentially the 'scale' algorithm, with recursion removed.
89073 * Note that 'k' is either correct immediately, or will move in one
89074 * direction in the loop. There's no need to do the low/high checks
89075 * on every round (like the Scheme algorithm does).
89076 *
89077 * The scheme algorithm finds 'k' and updates 's' simultaneously,
89078 * while the logical algorithm finds 'k' with 's' having its initial
89079 * value, after which 's' is updated separately (see the Burger-Dybvig
89080 * paper, Section 3.1, steps 2 and 3).
89081 *
89082 * The case where m+ == m- (almost always) is optimized for, because
89083 * it reduces the bigint operations considerably and almost always
89084 * applies. The scale loop only needs to work with m+, so this works.
89085 */
89086
89087 /* XXX: this algorithm could be optimized quite a lot by using e.g.
89088 * a logarithm based estimator for 'k' and performing B^n multiplication
89089 * using a lookup table or using some bit-representation based exp
89090 * algorithm. Currently we just loop, with significant performance
89091 * impact for very large and very small numbers.
89092 */
89093
89094 DUK_DDD(
89095 DUK_DDDPRINT("scale: B=%ld, low_ok=%ld, high_ok=%ld", (long) nc_ctx->B, (long) nc_ctx->low_ok, (long) nc_ctx->high_ok));
89096 DUK__BI_PRINT("r(init)", &nc_ctx->r);
89097 DUK__BI_PRINT("s(init)", &nc_ctx->s);
89098 DUK__BI_PRINT("mp(init)", &nc_ctx->mp);
89099 DUK__BI_PRINT("mm(init)", &nc_ctx->mm);
89100
89101 for (;;) {
89102 DUK_DDD(DUK_DDDPRINT("scale loop (inc k), k=%ld", (long) k));
89103 DUK__BI_PRINT("r", &nc_ctx->r);
89104 DUK__BI_PRINT("s", &nc_ctx->s);
89105 DUK__BI_PRINT("m+", &nc_ctx->mp);
89106 DUK__BI_PRINT("m-", &nc_ctx->mm);
89107
89108 duk__bi_add(&nc_ctx->t1, &nc_ctx->r, &nc_ctx->mp); /* t1 = (+ r m+) */
89109 if (duk__bi_compare(&nc_ctx->t1, &nc_ctx->s) >= (nc_ctx->high_ok ? 0 : 1)) {
89110 DUK_DDD(DUK_DDDPRINT("k is too low"));
89111 /* r <- r
89112 * s <- (* s B)
89113 * m+ <- m+
89114 * m- <- m-
89115 * k <- (+ k 1)
89116 */
89117
89118 duk__bi_mul_small_copy(&nc_ctx->s, (duk_uint32_t) nc_ctx->B, &nc_ctx->t1);
89119 k++;
89120 } else {
89121 break;
89122 }
89123 }
89124
89125 /* k > 0 -> k was too low, and cannot be too high */
89126 if (k > 0) {
89127 goto skip_dec_k;
89128 }
89129
89130 for (;;) {
89131 DUK_DDD(DUK_DDDPRINT("scale loop (dec k), k=%ld", (long) k));
89132 DUK__BI_PRINT("r", &nc_ctx->r);
89133 DUK__BI_PRINT("s", &nc_ctx->s);
89134 DUK__BI_PRINT("m+", &nc_ctx->mp);
89135 DUK__BI_PRINT("m-", &nc_ctx->mm);
89136
89137 duk__bi_add(&nc_ctx->t1, &nc_ctx->r, &nc_ctx->mp); /* t1 = (+ r m+) */
89138 duk__bi_mul_small(&nc_ctx->t2, &nc_ctx->t1, (duk_uint32_t) nc_ctx->B); /* t2 = (* (+ r m+) B) */
89139 if (duk__bi_compare(&nc_ctx->t2, &nc_ctx->s) <= (nc_ctx->high_ok ? -1 : 0)) {
89140 DUK_DDD(DUK_DDDPRINT("k is too high"));
89141 /* r <- (* r B)
89142 * s <- s
89143 * m+ <- (* m+ B)
89144 * m- <- (* m- B)
89145 * k <- (- k 1)
89146 */
89147 duk__bi_mul_small_copy(&nc_ctx->r, (duk_uint32_t) nc_ctx->B, &nc_ctx->t1);
89148 duk__bi_mul_small_copy(&nc_ctx->mp, (duk_uint32_t) nc_ctx->B, &nc_ctx->t1);
89149 if (nc_ctx->unequal_gaps) {
89150 DUK_DDD(DUK_DDDPRINT("m+ != m- -> need to update m- too"));
89151 duk__bi_mul_small_copy(&nc_ctx->mm, (duk_uint32_t) nc_ctx->B, &nc_ctx->t1);
89152 }
89153 k--;
89154 } else {
89155 break;
89156 }
89157 }
89158
89159skip_dec_k:
89160
89161 if (!nc_ctx->unequal_gaps) {
89162 DUK_DDD(DUK_DDDPRINT("equal gaps, copy m- from m+"));
89163 duk__bi_copy(&nc_ctx->mm, &nc_ctx->mp); /* mm <- mp */
89164 }
89165 nc_ctx->k = k;
89166
89167 DUK_DDD(DUK_DDDPRINT("final k: %ld", (long) k));
89168 DUK__BI_PRINT("r(final)", &nc_ctx->r);
89169 DUK__BI_PRINT("s(final)", &nc_ctx->s);
89170 DUK__BI_PRINT("mp(final)", &nc_ctx->mp);
89171 DUK__BI_PRINT("mm(final)", &nc_ctx->mm);
89172}
89173
89175 duk_small_int_t tc1, tc2; /* terminating conditions */
89176 duk_small_int_t d; /* current digit */
89177 duk_small_int_t count = 0; /* digit count */
89178
89179 /*
89180 * Digit generation loop.
89181 *
89182 * Different termination conditions:
89183 *
89184 * 1. Free format output. Terminate when shortest accurate
89185 * representation found.
89186 *
89187 * 2. Fixed format output, with specific number of digits.
89188 * Ignore termination conditions, terminate when digits
89189 * generated. Caller requests an extra digit and rounds.
89190 *
89191 * 3. Fixed format output, with a specific absolute cut-off
89192 * position (e.g. 10 digits after decimal point). Note
89193 * that we always generate at least one digit, even if
89194 * the digit is below the cut-off point already.
89195 */
89196
89197 for (;;) {
89198 DUK_DDD(DUK_DDDPRINT("generate loop, count=%ld, k=%ld, B=%ld, low_ok=%ld, high_ok=%ld",
89199 (long) count,
89200 (long) nc_ctx->k,
89201 (long) nc_ctx->B,
89202 (long) nc_ctx->low_ok,
89203 (long) nc_ctx->high_ok));
89204 DUK__BI_PRINT("r", &nc_ctx->r);
89205 DUK__BI_PRINT("s", &nc_ctx->s);
89206 DUK__BI_PRINT("m+", &nc_ctx->mp);
89207 DUK__BI_PRINT("m-", &nc_ctx->mm);
89208
89209 /* (quotient-remainder (* r B) s) using a dummy subtraction loop */
89210 duk__bi_mul_small(&nc_ctx->t1, &nc_ctx->r, (duk_uint32_t) nc_ctx->B); /* t1 <- (* r B) */
89211 d = 0;
89212 for (;;) {
89213 if (duk__bi_compare(&nc_ctx->t1, &nc_ctx->s) < 0) {
89214 break;
89215 }
89216 duk__bi_sub_copy(&nc_ctx->t1, &nc_ctx->s, &nc_ctx->t2); /* t1 <- t1 - s */
89217 d++;
89218 }
89219 duk__bi_copy(&nc_ctx->r, &nc_ctx->t1); /* r <- (remainder (* r B) s) */
89220 /* d <- (quotient (* r B) s) (in range 0...B-1) */
89221 DUK_DDD(DUK_DDDPRINT("-> d(quot)=%ld", (long) d));
89222 DUK__BI_PRINT("r(rem)", &nc_ctx->r);
89223
89224 duk__bi_mul_small_copy(&nc_ctx->mp, (duk_uint32_t) nc_ctx->B, &nc_ctx->t2); /* m+ <- (* m+ B) */
89225 duk__bi_mul_small_copy(&nc_ctx->mm, (duk_uint32_t) nc_ctx->B, &nc_ctx->t2); /* m- <- (* m- B) */
89226 DUK__BI_PRINT("mp(upd)", &nc_ctx->mp);
89227 DUK__BI_PRINT("mm(upd)", &nc_ctx->mm);
89228
89229 /* Terminating conditions. For fixed width output, we just ignore the
89230 * terminating conditions (and pretend that tc1 == tc2 == false). The
89231 * the current shortcut for fixed-format output is to generate a few
89232 * extra digits and use rounding (with carry) to finish the output.
89233 */
89234
89235 if (nc_ctx->is_fixed == 0) {
89236 /* free-form */
89237 tc1 = (duk__bi_compare(&nc_ctx->r, &nc_ctx->mm) <= (nc_ctx->low_ok ? 0 : -1));
89238
89239 duk__bi_add(&nc_ctx->t1, &nc_ctx->r, &nc_ctx->mp); /* t1 <- (+ r m+) */
89240 tc2 = (duk__bi_compare(&nc_ctx->t1, &nc_ctx->s) >= (nc_ctx->high_ok ? 0 : 1));
89241
89242 DUK_DDD(DUK_DDDPRINT("tc1=%ld, tc2=%ld", (long) tc1, (long) tc2));
89243 } else {
89244 /* fixed-format */
89245 tc1 = 0;
89246 tc2 = 0;
89247 }
89248
89249 /* Count is incremented before DUK__DRAGON4_OUTPUT_PREINC() call
89250 * on purpose, which is taken into account by the macro.
89251 */
89252 count++;
89253
89254 if (tc1) {
89255 if (tc2) {
89256 /* tc1 = true, tc2 = true */
89257 duk__bi_mul_small(&nc_ctx->t1, &nc_ctx->r, 2);
89258 if (duk__bi_compare(&nc_ctx->t1, &nc_ctx->s) < 0) { /* (< (* r 2) s) */
89259 DUK_DDD(DUK_DDDPRINT("tc1=true, tc2=true, 2r > s: output d --> %ld (k=%ld)",
89260 (long) d,
89261 (long) nc_ctx->k));
89263 } else {
89264 DUK_DDD(DUK_DDDPRINT("tc1=true, tc2=true, 2r <= s: output d+1 --> %ld (k=%ld)",
89265 (long) (d + 1),
89266 (long) nc_ctx->k));
89267 DUK__DRAGON4_OUTPUT_PREINC(nc_ctx, count, d + 1);
89268 }
89269 break;
89270 } else {
89271 /* tc1 = true, tc2 = false */
89272 DUK_DDD(DUK_DDDPRINT("tc1=true, tc2=false: output d --> %ld (k=%ld)", (long) d, (long) nc_ctx->k));
89274 break;
89275 }
89276 } else {
89277 if (tc2) {
89278 /* tc1 = false, tc2 = true */
89279 DUK_DDD(DUK_DDDPRINT("tc1=false, tc2=true: output d+1 --> %ld (k=%ld)",
89280 (long) (d + 1),
89281 (long) nc_ctx->k));
89282 DUK__DRAGON4_OUTPUT_PREINC(nc_ctx, count, d + 1);
89283 break;
89284 } else {
89285 /* tc1 = false, tc2 = false */
89286 DUK_DDD(DUK_DDDPRINT("tc1=false, tc2=false: output d --> %ld (k=%ld)", (long) d, (long) nc_ctx->k));
89288
89289 /* r <- r (updated above: r <- (remainder (* r B) s)
89290 * s <- s
89291 * m+ <- m+ (updated above: m+ <- (* m+ B)
89292 * m- <- m- (updated above: m- <- (* m- B)
89293 * B, low_ok, high_ok are fixed
89294 */
89295
89296 /* fall through and continue for-loop */
89297 }
89298 }
89299
89300 /* fixed-format termination conditions */
89301 if (nc_ctx->is_fixed) {
89302 if (nc_ctx->abs_pos) {
89303 int pos = nc_ctx->k - count + 1; /* count is already incremented, take into account */
89304 DUK_DDD(DUK_DDDPRINT("fixed format, absolute: abs pos=%ld, k=%ld, count=%ld, req=%ld",
89305 (long) pos,
89306 (long) nc_ctx->k,
89307 (long) count,
89308 (long) nc_ctx->req_digits));
89309 if (pos <= nc_ctx->req_digits) {
89310 DUK_DDD(DUK_DDDPRINT("digit position reached req_digits, end generate loop"));
89311 break;
89312 }
89313 } else {
89314 DUK_DDD(DUK_DDDPRINT("fixed format, relative: k=%ld, count=%ld, req=%ld",
89315 (long) nc_ctx->k,
89316 (long) count,
89317 (long) nc_ctx->req_digits));
89318 if (count >= nc_ctx->req_digits) {
89319 DUK_DDD(DUK_DDDPRINT("digit count reached req_digits, end generate loop"));
89320 break;
89321 }
89322 }
89323 }
89324 } /* for */
89325
89326 nc_ctx->count = count;
89327
89328 DUK_DDD(DUK_DDDPRINT("generate finished"));
89329
89330#if defined(DUK_USE_DEBUG_LEVEL) && (DUK_USE_DEBUG_LEVEL >= 2)
89331 {
89332 duk_uint8_t buf[2048];
89333 duk_small_int_t i, t;
89334 duk_memzero(buf, sizeof(buf));
89335 for (i = 0; i < nc_ctx->count; i++) {
89336 t = nc_ctx->digits[i];
89337 if (t < 0 || t > 36) {
89338 buf[i] = (duk_uint8_t) '?';
89339 } else {
89340 buf[i] = (duk_uint8_t) DUK__DIGITCHAR(t);
89341 }
89342 }
89343 DUK_DDD(DUK_DDDPRINT("-> generated digits; k=%ld, digits='%s'", (long) nc_ctx->k, (const char *) buf));
89344 }
89345#endif
89346}
89347
89348/* Round up digits to a given position. If position is out-of-bounds,
89349 * does nothing. If carry propagates over the first digit, a '1' is
89350 * prepended to digits and 'k' will be updated. Return value indicates
89351 * whether carry propagated over the first digit.
89352 *
89353 * Note that nc_ctx->count is NOT updated based on the rounding position
89354 * (it is updated only if carry overflows over the first digit and an
89355 * extra digit is prepended).
89356 */
89359 duk_uint8_t *p;
89360 duk_uint8_t roundup_limit;
89361 duk_small_int_t ret = 0;
89362
89363 /*
89364 * round_idx points to the digit which is considered for rounding; the
89365 * digit to its left is the final digit of the rounded value. If round_idx
89366 * is zero, rounding will be performed; the result will either be an empty
89367 * rounded value or if carry happens a '1' digit is generated.
89368 */
89369
89370 if (round_idx >= nc_ctx->count) {
89371 DUK_DDD(DUK_DDDPRINT("round_idx out of bounds (%ld >= %ld (count)) -> no rounding",
89372 (long) round_idx,
89373 (long) nc_ctx->count));
89374 return 0;
89375 } else if (round_idx < 0) {
89376 DUK_DDD(DUK_DDDPRINT("round_idx out of bounds (%ld < 0) -> no rounding", (long) round_idx));
89377 return 0;
89378 }
89379
89380 /*
89381 * Round-up limit.
89382 *
89383 * For even values, divides evenly, e.g. 10 -> roundup_limit=5.
89384 *
89385 * For odd values, rounds up, e.g. 3 -> roundup_limit=2.
89386 * If radix is 3, 0/3 -> down, 1/3 -> down, 2/3 -> up.
89387 */
89388 roundup_limit = (duk_uint8_t) ((nc_ctx->B + 1) / 2);
89389
89390 p = &nc_ctx->digits[round_idx];
89391 if (*p >= roundup_limit) {
89392 DUK_DDD(DUK_DDDPRINT("fixed-format rounding carry required"));
89393 /* carry */
89394 for (;;) {
89395 *p = 0;
89396 if (p == &nc_ctx->digits[0]) {
89397 DUK_DDD(DUK_DDDPRINT("carry propagated to first digit -> special case handling"));
89398 duk_memmove((void *) (&nc_ctx->digits[1]),
89399 (const void *) (&nc_ctx->digits[0]),
89400 (size_t) (sizeof(char) * (size_t) nc_ctx->count));
89401 nc_ctx->digits[0] = 1; /* don't increase 'count' */
89402 nc_ctx->k++; /* position of highest digit changed */
89403 nc_ctx->count++; /* number of digits changed */
89404 ret = 1;
89405 break;
89406 }
89407
89408 DUK_DDD(DUK_DDDPRINT("fixed-format rounding carry: B=%ld, roundup_limit=%ld, p=%p, digits=%p",
89409 (long) nc_ctx->B,
89410 (long) roundup_limit,
89411 (void *) p,
89412 (void *) nc_ctx->digits));
89413 p--;
89414 t = *p;
89415 DUK_DDD(DUK_DDDPRINT("digit before carry: %ld", (long) t));
89416 if (++t < nc_ctx->B) {
89417 DUK_DDD(DUK_DDDPRINT("rounding carry terminated"));
89418 *p = (duk_uint8_t) t;
89419 break;
89420 }
89421
89422 DUK_DDD(DUK_DDDPRINT("wraps, carry to next digit"));
89423 }
89424 }
89425
89426 return ret;
89427}
89428
89429#define DUK__NO_EXP (65536) /* arbitrary marker, outside valid exp range */
89430
89432 duk_hthread *thr,
89433 duk_small_int_t radix,
89434 duk_small_int_t digits,
89435 duk_small_uint_t flags,
89436 duk_small_int_t neg) {
89438 duk_small_int_t pos, pos_end;
89439 duk_small_int_t expt;
89440 duk_small_int_t dig;
89441 duk_uint8_t *q;
89442 duk_uint8_t *buf;
89443
89444 /*
89445 * The string conversion here incorporates all the necessary ECMAScript
89446 * semantics without attempting to be generic. nc_ctx->digits contains
89447 * nc_ctx->count digits (>= 1), with the topmost digit's 'position'
89448 * indicated by nc_ctx->k as follows:
89449 *
89450 * digits="123" count=3 k=0 --> 0.123
89451 * digits="123" count=3 k=1 --> 1.23
89452 * digits="123" count=3 k=5 --> 12300
89453 * digits="123" count=3 k=-1 --> 0.0123
89454 *
89455 * Note that the identifier names used for format selection are different
89456 * in Burger-Dybvig paper and ECMAScript specification (quite confusingly
89457 * so, because e.g. 'k' has a totally different meaning in each). See
89458 * documentation for discussion.
89459 *
89460 * ECMAScript doesn't specify any specific behavior for format selection
89461 * (e.g. when to use exponent notation) for non-base-10 numbers.
89462 *
89463 * The bigint space in the context is reused for string output, as there
89464 * is more than enough space for that (>1kB at the moment), and we avoid
89465 * allocating even more stack.
89466 */
89467
89469 DUK_ASSERT(nc_ctx->count >= 1);
89470
89471 k = nc_ctx->k;
89472 buf = (duk_uint8_t *) &nc_ctx->f; /* XXX: union would be more correct */
89473 q = buf;
89474
89475 /* Exponent handling: if exponent format is used, record exponent value and
89476 * fake k such that one leading digit is generated (e.g. digits=123 -> "1.23").
89477 *
89478 * toFixed() prevents exponent use; otherwise apply a set of criteria to
89479 * match the other API calls (toString(), toPrecision, etc).
89480 */
89481
89482 expt = DUK__NO_EXP;
89483 if (!nc_ctx->abs_pos /* toFixed() */) {
89484 if ((flags & DUK_N2S_FLAG_FORCE_EXP) || /* exponential notation forced */
89485 ((flags & DUK_N2S_FLAG_NO_ZERO_PAD) && /* fixed precision and zero padding would be required */
89486 (k - digits >= 1)) || /* (e.g. k=3, digits=2 -> "12X") */
89487 ((k > 21 || k <= -6) && (radix == 10))) { /* toString() conditions */
89488 DUK_DDD(DUK_DDDPRINT("use exponential notation: k=%ld -> expt=%ld", (long) k, (long) (k - 1)));
89489 expt = k - 1; /* e.g. 12.3 -> digits="123" k=2 -> 1.23e1 */
89490 k = 1; /* generate mantissa with a single leading whole number digit */
89491 }
89492 }
89493
89494 if (neg) {
89495 *q++ = '-';
89496 }
89497
89498 /* Start position (inclusive) and end position (exclusive) */
89499 pos = (k >= 1 ? k : 1);
89500 if (nc_ctx->is_fixed) {
89501 if (nc_ctx->abs_pos) {
89502 /* toFixed() */
89503 pos_end = -digits;
89504 } else {
89505 pos_end = k - digits;
89506 }
89507 } else {
89508 pos_end = k - nc_ctx->count;
89509 }
89510 if (pos_end > 0) {
89511 pos_end = 0;
89512 }
89513
89514 DUK_DDD(DUK_DDDPRINT("expt=%ld, k=%ld, count=%ld, pos=%ld, pos_end=%ld, is_fixed=%ld, "
89515 "digits=%ld, abs_pos=%ld",
89516 (long) expt,
89517 (long) k,
89518 (long) nc_ctx->count,
89519 (long) pos,
89520 (long) pos_end,
89521 (long) nc_ctx->is_fixed,
89522 (long) digits,
89523 (long) nc_ctx->abs_pos));
89524
89525 /* Digit generation */
89526 while (pos > pos_end) {
89527 DUK_DDD(DUK_DDDPRINT("digit generation: pos=%ld, pos_end=%ld", (long) pos, (long) pos_end));
89528 if (pos == 0) {
89529 *q++ = (duk_uint8_t) '.';
89530 }
89531 if (pos > k) {
89532 *q++ = (duk_uint8_t) '0';
89533 } else if (pos <= k - nc_ctx->count) {
89534 *q++ = (duk_uint8_t) '0';
89535 } else {
89536 dig = nc_ctx->digits[k - pos];
89537 DUK_ASSERT(dig >= 0 && dig < nc_ctx->B);
89538 *q++ = (duk_uint8_t) DUK__DIGITCHAR(dig);
89539 }
89540
89541 pos--;
89542 }
89543 DUK_ASSERT(pos <= 1);
89545 /* Exponent */
89546 if (expt != DUK__NO_EXP) {
89547 /*
89548 * Exponent notation for non-base-10 numbers isn't specified in ECMAScript
89549 * specification, as it never explicitly turns up: non-decimal numbers can
89550 * only be formatted with Number.prototype.toString([radix]) and for that,
89551 * behavior is not explicitly specified.
89552 *
89553 * Logical choices include formatting the exponent as decimal (e.g. binary
89554 * 100000 as 1e+5) or in current radix (e.g. binary 100000 as 1e+101).
89555 * The Dragon4 algorithm (in the original paper) prints the exponent value
89556 * in the target radix B. However, for radix values 15 and above, the
89557 * exponent separator 'e' is no longer easily parseable. Consider, for
89558 * instance, the number "1.faecee+1c".
89559 */
89560
89561 duk_size_t len;
89562 char expt_sign;
89563
89564 *q++ = 'e';
89565 if (expt >= 0) {
89566 expt_sign = '+';
89567 } else {
89568 expt_sign = '-';
89569 expt = -expt;
89570 }
89571 *q++ = (duk_uint8_t) expt_sign;
89572 len = duk__dragon4_format_uint32(q, (duk_uint32_t) expt, radix);
89573 q += len;
89574 }
89575
89576 duk_push_lstring(thr, (const char *) buf, (size_t) (q - buf));
89577}
89578
89579/*
89580 * Conversion helpers
89581 */
89582
89585 duk_uint32_t tmp;
89586 duk_small_int_t expt;
89587
89588 /*
89589 * seeeeeee eeeeffff ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff
89590 * A B C D E F G H
89591 *
89592 * s sign bit
89593 * eee... exponent field
89594 * fff... fraction
89595 *
89596 * ieee value = 1.ffff... * 2^(e - 1023) (normal)
89597 * = 0.ffff... * 2^(-1022) (denormal)
89598 *
89599 * algorithm v = f * b^e
89600 */
89601
89603
89604 nc_ctx->f.n = 2;
89605
89606 tmp = DUK_DBLUNION_GET_LOW32(&u);
89607 nc_ctx->f.v[0] = tmp;
89608 tmp = DUK_DBLUNION_GET_HIGH32(&u);
89609 nc_ctx->f.v[1] = tmp & 0x000fffffUL;
89610 expt = (duk_small_int_t) ((tmp >> 20) & 0x07ffUL);
89611
89612 if (expt == 0) {
89613 /* denormal */
89614 expt = DUK__IEEE_DOUBLE_EXP_MIN - 52;
89615 duk__bi_normalize(&nc_ctx->f);
89616 } else {
89617 /* normal: implicit leading 1-bit */
89618 nc_ctx->f.v[1] |= 0x00100000UL;
89619 expt = expt - DUK__IEEE_DOUBLE_EXP_BIAS - 52;
89620 DUK_ASSERT(duk__bi_is_valid(&nc_ctx->f)); /* true, because v[1] has at least one bit set */
89621 }
89622
89623 DUK_ASSERT(duk__bi_is_valid(&nc_ctx->f));
89624
89625 nc_ctx->e = expt;
89626}
89627
89630 duk_small_int_t expt;
89632 duk_small_int_t bitstart;
89633 duk_small_int_t bitround;
89634 duk_small_int_t bitidx;
89635 duk_small_int_t skip_round;
89636 duk_uint32_t t, v;
89637
89638 DUK_ASSERT(nc_ctx->count == 53 + 1);
89639
89640 /* Sometimes this assert is not true right now; it will be true after
89641 * rounding. See: test-bug-numconv-mantissa-assert.js.
89642 */
89643 DUK_ASSERT_DISABLE(nc_ctx->digits[0] == 1); /* zero handled by caller */
89644
89645 /* Should not be required because the code below always sets both high
89646 * and low parts, but at least gcc-4.4.5 fails to deduce this correctly
89647 * (perhaps because the low part is set (seemingly) conditionally in a
89648 * loop), so this is here to avoid the bogus warning.
89649 */
89650 duk_memzero((void *) &u, sizeof(u));
89651
89652 /*
89653 * Figure out how generated digits match up with the mantissa,
89654 * and then perform rounding. If mantissa overflows, need to
89655 * recompute the exponent (it is bumped and may overflow to
89656 * infinity).
89657 *
89658 * For normal numbers the leading '1' is hidden and ignored,
89659 * and the last bit is used for rounding:
89660 *
89661 * rounding pt
89662 * <--------52------->|
89663 * 1 x x x x ... x x x x|y ==> x x x x ... x x x x
89664 *
89665 * For denormals, the leading '1' is included in the number,
89666 * and the rounding point is different:
89667 *
89668 * rounding pt
89669 * <--52 or less--->|
89670 * 1 x x x x ... x x|x x y ==> 0 0 ... 1 x x ... x x
89671 *
89672 * The largest denormals will have a mantissa beginning with
89673 * a '1' (the explicit leading bit); smaller denormals will
89674 * have leading zero bits.
89675 *
89676 * If the exponent would become too high, the result becomes
89677 * Infinity. If the exponent is so small that the entire
89678 * mantissa becomes zero, the result becomes zero.
89679 *
89680 * Note: the Dragon4 'k' is off-by-one with respect to the IEEE
89681 * exponent. For instance, k==0 indicates that the leading '1'
89682 * digit is at the first binary fraction position (0.1xxx...);
89683 * the corresponding IEEE exponent would be -1.
89684 */
89685
89686 skip_round = 0;
89687
89688recheck_exp:
89689
89690 expt = nc_ctx->k - 1; /* IEEE exp without bias */
89691 if (expt > 1023) {
89692 /* Infinity */
89693 bitstart = -255; /* needed for inf: causes mantissa to become zero,
89694 * and rounding to be skipped.
89695 */
89696 expt = 2047;
89697 } else if (expt >= -1022) {
89698 /* normal */
89699 bitstart = 1; /* skip leading digit */
89701 DUK_ASSERT(expt >= 1 && expt <= 2046);
89702 } else {
89703 /* denormal or zero */
89704 bitstart = 1023 + expt; /* expt==-1023 -> bitstart=0 (leading 1);
89705 * expt==-1024 -> bitstart=-1 (one left of leading 1), etc
89706 */
89707 expt = 0;
89708 }
89709 bitround = bitstart + 52;
89710
89711 DUK_DDD(DUK_DDDPRINT("ieee expt=%ld, bitstart=%ld, bitround=%ld", (long) expt, (long) bitstart, (long) bitround));
89712
89713 if (!skip_round) {
89714 if (duk__dragon4_fixed_format_round(nc_ctx, bitround)) {
89715 /* Corner case: see test-numconv-parse-mant-carry.js. We could
89716 * just bump the exponent and update bitstart, but it's more robust
89717 * to recompute (but avoid rounding twice).
89718 */
89719 DUK_DDD(DUK_DDDPRINT("rounding caused exponent to be bumped, recheck exponent"));
89720 skip_round = 1;
89721 goto recheck_exp;
89722 }
89723 }
89724
89725 /*
89726 * Create mantissa
89727 */
89728
89729 t = 0;
89730 for (i = 0; i < 52; i++) {
89731 bitidx = bitstart + 52 - 1 - i;
89732 if (bitidx >= nc_ctx->count) {
89733 v = 0;
89734 } else if (bitidx < 0) {
89735 v = 0;
89736 } else {
89737 v = nc_ctx->digits[bitidx];
89738 }
89739 DUK_ASSERT(v == 0 || v == 1);
89740 t += v << (i % 32);
89741 if (i == 31) {
89742 /* low 32 bits is complete */
89744 t = 0;
89745 }
89746 }
89747 /* t has high mantissa */
89748
89749 DUK_DDD(DUK_DDDPRINT("mantissa is complete: %08lx %08lx", (unsigned long) t, (unsigned long) DUK_DBLUNION_GET_LOW32(&u)));
89750
89751 DUK_ASSERT(expt >= 0 && expt <= 0x7ffL);
89752 t += ((duk_uint32_t) expt) << 20;
89753#if 0 /* caller handles sign change */
89754 if (negative) {
89755 t |= 0x80000000U;
89756 }
89757#endif
89759
89760 DUK_DDD(DUK_DDDPRINT("number is complete: %08lx %08lx",
89761 (unsigned long) DUK_DBLUNION_GET_HIGH32(&u),
89762 (unsigned long) DUK_DBLUNION_GET_LOW32(&u)));
89763
89764 *x = DUK_DBLUNION_GET_DOUBLE(&u);
89765}
89766
89767/*
89768 * Exposed number-to-string API
89769 *
89770 * Input: [ number ]
89771 * Output: [ string ]
89772 */
89773
89775 duk_small_int_t radix,
89776 duk_small_int_t digits,
89777 duk_small_uint_t flags) {
89778 duk_double_t x;
89780 duk_small_int_t neg;
89781 duk_uint32_t uval;
89782 duk__numconv_stringify_ctx nc_ctx_alloc; /* large context; around 2kB now */
89783 duk__numconv_stringify_ctx *nc_ctx = &nc_ctx_alloc;
89784
89785 x = (duk_double_t) duk_require_number(thr, -1);
89786 duk_pop(thr);
89787
89788 /*
89789 * Handle special cases (NaN, infinity, zero).
89790 */
89791
89793 if (DUK_SIGNBIT((double) x)) {
89794 x = -x;
89795 neg = 1;
89796 } else {
89797 neg = 0;
89798 }
89799
89800 /* NaN sign bit is platform specific with unpacked, un-normalized NaNs */
89801 DUK_ASSERT(c == DUK_FP_NAN || DUK_SIGNBIT((double) x) == 0);
89802
89803 if (c == DUK_FP_NAN) {
89805 return;
89806 } else if (c == DUK_FP_INFINITE) {
89807 if (neg) {
89808 /* -Infinity */
89810 } else {
89811 /* Infinity */
89813 }
89814 return;
89815 } else if (c == DUK_FP_ZERO) {
89816 /* We can't shortcut zero here if it goes through special formatting
89817 * (such as forced exponential notation).
89818 */
89819 ;
89820 }
89821
89822 /*
89823 * Handle integers in 32-bit range (that is, [-(2**32-1),2**32-1])
89824 * specially, as they're very likely for embedded programs. This
89825 * is now done for all radix values. We must be careful not to use
89826 * the fast path when special formatting (e.g. forced exponential)
89827 * is in force.
89828 *
89829 * XXX: could save space by supporting radix 10 only and using
89830 * sprintf "%lu" for the fast path and for exponent formatting.
89831 */
89832
89833 uval = duk_double_to_uint32_t(x);
89834 if (duk_double_equals((double) uval, x) && /* integer number in range */
89835 flags == 0) { /* no special formatting */
89836 /* use bigint area as a temp */
89837 duk_uint8_t *buf = (duk_uint8_t *) (&nc_ctx->f);
89838 duk_uint8_t *p = buf;
89839
89840 DUK_ASSERT(DUK__NUMCONV_CTX_BIGINTS_SIZE >= 32 + 1); /* max size: radix=2 + sign */
89841 if (neg && uval != 0) {
89842 /* no negative sign for zero */
89843 *p++ = (duk_uint8_t) '-';
89844 }
89845 p += duk__dragon4_format_uint32(p, uval, radix);
89846 duk_push_lstring(thr, (const char *) buf, (duk_size_t) (p - buf));
89847 return;
89848 }
89849
89850 /*
89851 * Dragon4 setup.
89852 *
89853 * Convert double from IEEE representation for conversion;
89854 * normal finite values have an implicit leading 1-bit. The
89855 * slow path algorithm doesn't handle zero, so zero is special
89856 * cased here but still creates a valid nc_ctx, and goes
89857 * through normal formatting in case special formatting has
89858 * been requested (e.g. forced exponential format: 0 -> "0e+0").
89859 */
89860
89861 /* Would be nice to bulk clear the allocation, but the context
89862 * is 1-2 kilobytes and nothing should rely on it being zeroed.
89863 */
89864#if 0
89865 duk_memzero((void *) nc_ctx, sizeof(*nc_ctx)); /* slow init, do only for slow path cases */
89866#endif
89867
89868 nc_ctx->is_s2n = 0;
89869 nc_ctx->b = 2;
89870 nc_ctx->B = radix;
89871 nc_ctx->abs_pos = 0;
89872 if (flags & DUK_N2S_FLAG_FIXED_FORMAT) {
89873 nc_ctx->is_fixed = 1;
89874 if (flags & DUK_N2S_FLAG_FRACTION_DIGITS) {
89875 /* absolute req_digits; e.g. digits = 1 -> last digit is 0,
89876 * but add an extra digit for rounding.
89877 */
89878 nc_ctx->abs_pos = 1;
89879 nc_ctx->req_digits = (-digits + 1) - 1;
89880 } else {
89881 nc_ctx->req_digits = digits + 1;
89882 }
89883 } else {
89884 nc_ctx->is_fixed = 0;
89885 nc_ctx->req_digits = 0;
89886 }
89887
89888 if (c == DUK_FP_ZERO) {
89889 /* Zero special case: fake requested number of zero digits; ensure
89890 * no sign bit is printed. Relative and absolute fixed format
89891 * require separate handling.
89892 */
89894 if (nc_ctx->is_fixed) {
89895 if (nc_ctx->abs_pos) {
89896 count = digits + 2; /* lead zero + 'digits' fractions + 1 for rounding */
89897 } else {
89898 count = digits + 1; /* + 1 for rounding */
89899 }
89900 } else {
89901 count = 1;
89902 }
89903 DUK_DDD(DUK_DDDPRINT("count=%ld", (long) count));
89904 DUK_ASSERT(count >= 1);
89905 duk_memzero((void *) nc_ctx->digits, (size_t) count);
89906 nc_ctx->count = count;
89907 nc_ctx->k = 1; /* 0.000... */
89908 neg = 0;
89909 goto zero_skip;
89910 }
89911
89912 duk__dragon4_double_to_ctx(nc_ctx, x); /* -> sets 'f' and 'e' */
89913 DUK__BI_PRINT("f", &nc_ctx->f);
89914 DUK_DDD(DUK_DDDPRINT("e=%ld", (long) nc_ctx->e));
89915
89916 /*
89917 * Dragon4 slow path digit generation.
89918 */
89919
89920 duk__dragon4_prepare(nc_ctx); /* setup many variables in nc_ctx */
89921
89922 DUK_DDD(DUK_DDDPRINT("after prepare:"));
89923 DUK__BI_PRINT("r", &nc_ctx->r);
89924 DUK__BI_PRINT("s", &nc_ctx->s);
89925 DUK__BI_PRINT("mp", &nc_ctx->mp);
89926 DUK__BI_PRINT("mm", &nc_ctx->mm);
89927
89928 duk__dragon4_scale(nc_ctx);
89929
89930 DUK_DDD(DUK_DDDPRINT("after scale; k=%ld", (long) nc_ctx->k));
89931 DUK__BI_PRINT("r", &nc_ctx->r);
89932 DUK__BI_PRINT("s", &nc_ctx->s);
89933 DUK__BI_PRINT("mp", &nc_ctx->mp);
89934 DUK__BI_PRINT("mm", &nc_ctx->mm);
89935
89936 duk__dragon4_generate(nc_ctx);
89937
89938 /*
89939 * Convert and push final string.
89940 */
89941
89942zero_skip:
89943
89944 if (flags & DUK_N2S_FLAG_FIXED_FORMAT) {
89945 /* Perform fixed-format rounding. */
89946 duk_small_int_t roundpos;
89947 if (flags & DUK_N2S_FLAG_FRACTION_DIGITS) {
89948 /* 'roundpos' is relative to nc_ctx->k and increases to the right
89949 * (opposite of how 'k' changes).
89950 */
89951 roundpos = -digits; /* absolute position for digit considered for rounding */
89952 roundpos = nc_ctx->k - roundpos;
89953 } else {
89954 roundpos = digits;
89955 }
89956 DUK_DDD(DUK_DDDPRINT("rounding: k=%ld, count=%ld, digits=%ld, roundpos=%ld",
89957 (long) nc_ctx->k,
89958 (long) nc_ctx->count,
89959 (long) digits,
89960 (long) roundpos));
89961 (void) duk__dragon4_fixed_format_round(nc_ctx, roundpos);
89962
89963 /* Note: 'count' is currently not adjusted by rounding (i.e. the
89964 * digits are not "chopped off". That shouldn't matter because
89965 * the digit position (absolute or relative) is passed on to the
89966 * convert-and-push function.
89967 */
89968 }
89969
89970 duk__dragon4_convert_and_push(nc_ctx, thr, radix, digits, flags, neg);
89971}
89972
89975 duk__numconv_stringify_raw(thr, radix, digits, flags);
89976}
89977
89978/*
89979 * Exposed string-to-number API
89980 *
89981 * Input: [ string ]
89982 * Output: [ number ]
89983 *
89984 * If number parsing fails, a NaN is pushed as the result. If number parsing
89985 * fails due to an internal error, an InternalError is thrown.
89986 */
89987
89989 duk__numconv_stringify_ctx nc_ctx_alloc; /* large context; around 2kB now */
89990 duk__numconv_stringify_ctx *nc_ctx = &nc_ctx_alloc;
89991 duk_double_t res;
89992 duk_hstring *h_str;
89993 duk_int_t expt;
89994 duk_bool_t expt_neg;
89995 duk_small_int_t expt_adj;
89996 duk_small_int_t neg;
89997 duk_small_int_t dig;
89998 duk_small_int_t dig_whole;
89999 duk_small_int_t dig_lzero;
90000 duk_small_int_t dig_frac;
90001 duk_small_int_t dig_expt;
90002 duk_small_int_t dig_prec;
90003 const duk__exp_limits *explim;
90004 const duk_uint8_t *p;
90005 duk_small_int_t ch;
90006
90007 DUK_DDD(DUK_DDDPRINT("parse number: %!T, radix=%ld, flags=0x%08lx",
90008 (duk_tval *) duk_get_tval(thr, -1),
90009 (long) radix,
90010 (unsigned long) flags));
90011
90012 DUK_ASSERT(radix >= 2 && radix <= 36);
90014
90015 /*
90016 * Preliminaries: trim, sign, Infinity check
90017 *
90018 * We rely on the interned string having a NUL terminator, which will
90019 * cause a parse failure wherever it is encountered. As a result, we
90020 * don't need separate pointer checks.
90021 *
90022 * There is no special parsing for 'NaN' in the specification although
90023 * 'Infinity' (with an optional sign) is allowed in some contexts.
90024 * Some contexts allow plus/minus sign, while others only allow the
90025 * minus sign (like JSON.parse()).
90026 *
90027 * Automatic hex number detection (leading '0x' or '0X') and octal
90028 * number detection (leading '0' followed by at least one octal digit)
90029 * is done here too.
90030 *
90031 * Symbols are not explicitly rejected here (that's up to the caller).
90032 * If a symbol were passed here, it should ultimately safely fail
90033 * parsing due to a syntax error.
90034 */
90035
90036 if (flags & DUK_S2N_FLAG_TRIM_WHITE) {
90037 /* Leading / trailing whitespace is sometimes accepted and
90038 * sometimes not. After white space trimming, all valid input
90039 * characters are pure ASCII.
90040 */
90041 duk_trim(thr, -1);
90042 }
90043 h_str = duk_require_hstring(thr, -1);
90044 DUK_ASSERT(h_str != NULL);
90045 p = (const duk_uint8_t *) DUK_HSTRING_GET_DATA(h_str);
90046
90047 neg = 0;
90048 ch = *p;
90049 if (ch == (duk_small_int_t) '+') {
90050 if ((flags & DUK_S2N_FLAG_ALLOW_PLUS) == 0) {
90051 DUK_DDD(DUK_DDDPRINT("parse failed: leading plus sign not allowed"));
90052 goto parse_fail;
90053 }
90054 p++;
90055 } else if (ch == (duk_small_int_t) '-') {
90056 if ((flags & DUK_S2N_FLAG_ALLOW_MINUS) == 0) {
90057 DUK_DDD(DUK_DDDPRINT("parse failed: leading minus sign not allowed"));
90058 goto parse_fail;
90059 }
90060 p++;
90061 neg = 1;
90062 }
90063
90064 if ((flags & DUK_S2N_FLAG_ALLOW_INF) && DUK_STRNCMP((const char *) p, "Infinity", 8) == 0) {
90065 /* Don't check for Infinity unless the context allows it.
90066 * 'Infinity' is a valid integer literal in e.g. base-36:
90067 *
90068 * parseInt('Infinity', 36)
90069 * 1461559270678
90070 */
90071
90072 if ((flags & DUK_S2N_FLAG_ALLOW_GARBAGE) == 0 && p[8] != DUK_ASC_NUL) {
90073 DUK_DDD(DUK_DDDPRINT("parse failed: trailing garbage after matching 'Infinity' not allowed"));
90074 goto parse_fail;
90075 } else {
90076 res = DUK_DOUBLE_INFINITY;
90077 goto negcheck_and_ret;
90078 }
90079 }
90080 ch = *p;
90081 if (ch == (duk_small_int_t) '0') {
90082 duk_small_int_t detect_radix = 0;
90083 ch = DUK_LOWERCASE_CHAR_ASCII(p[1]); /* 'x' or 'X' -> 'x' */
90084 if ((flags & DUK_S2N_FLAG_ALLOW_AUTO_HEX_INT) && ch == DUK_ASC_LC_X) {
90085 DUK_DDD(DUK_DDDPRINT("detected 0x/0X hex prefix, changing radix and preventing fractions and exponent"));
90086 detect_radix = 16;
90087#if 0
90088 } else if ((flags & DUK_S2N_FLAG_ALLOW_AUTO_LEGACY_OCT_INT) &&
90089 (ch >= (duk_small_int_t) '0' && ch <= (duk_small_int_t) '9')) {
90090 DUK_DDD(DUK_DDDPRINT("detected 0n oct prefix, changing radix and preventing fractions and exponent"));
90091 detect_radix = 8;
90092
90093 /* NOTE: if this legacy octal case is added back, it has
90094 * different flags and 'p' advance so this needs to be
90095 * reworked.
90096 */
90097 flags |= DUK_S2N_FLAG_ALLOW_EMPTY_AS_ZERO; /* interpret e.g. '09' as '0', not NaN */
90098 p += 1;
90099#endif
90100 } else if ((flags & DUK_S2N_FLAG_ALLOW_AUTO_OCT_INT) && ch == DUK_ASC_LC_O) {
90101 DUK_DDD(DUK_DDDPRINT("detected 0o oct prefix, changing radix and preventing fractions and exponent"));
90102 detect_radix = 8;
90103 } else if ((flags & DUK_S2N_FLAG_ALLOW_AUTO_BIN_INT) && ch == DUK_ASC_LC_B) {
90104 DUK_DDD(DUK_DDDPRINT("detected 0b bin prefix, changing radix and preventing fractions and exponent"));
90105 detect_radix = 2;
90106 }
90107 if (detect_radix > 0) {
90108 radix = detect_radix;
90109 /* Clear empty as zero flag: interpret e.g. '0x' and '0xg' as a NaN (= parse error) */
90112 flags |= DUK_S2N_FLAG_ALLOW_LEADING_ZERO; /* allow e.g. '0x0009' and '0b00010001' */
90113 p += 2;
90114 }
90115 }
90116
90117 /*
90118 * Scan number and setup for Dragon4.
90119 *
90120 * The fast path case is detected during setup: an integer which
90121 * can be converted without rounding, no net exponent. The fast
90122 * path could be implemented as a separate scan, but may not really
90123 * be worth it: the multiplications for building 'f' are not
90124 * expensive when 'f' is small.
90125 *
90126 * The significand ('f') must contain enough bits of (apparent)
90127 * accuracy, so that Dragon4 will generate enough binary output digits.
90128 * For decimal numbers, this means generating a 20-digit significand,
90129 * which should yield enough practical accuracy to parse IEEE doubles.
90130 * In fact, the ECMAScript specification explicitly allows an
90131 * implementation to treat digits beyond 20 as zeroes (and even
90132 * to round the 20th digit upwards). For non-decimal numbers, the
90133 * appropriate number of digits has been precomputed for comparable
90134 * accuracy.
90135 *
90136 * Digit counts:
90137 *
90138 * [ dig_lzero ]
90139 * |
90140 * .+-..---[ dig_prec ]----.
90141 * | || |
90142 * 0000123.456789012345678901234567890e+123456
90143 * | | | | | |
90144 * `--+--' `------[ dig_frac ]-------' `-+--'
90145 * | |
90146 * [ dig_whole ] [ dig_expt ]
90147 *
90148 * dig_frac and dig_expt are -1 if not present
90149 * dig_lzero is only computed for whole number part
90150 *
90151 * Parsing state
90152 *
90153 * Parsing whole part dig_frac < 0 AND dig_expt < 0
90154 * Parsing fraction part dig_frac >= 0 AND dig_expt < 0
90155 * Parsing exponent part dig_expt >= 0 (dig_frac may be < 0 or >= 0)
90156 *
90157 * Note: in case we hit an implementation limit (like exponent range),
90158 * we should throw an error, NOT return NaN or Infinity. Even with
90159 * very large exponent (or significand) values the final result may be
90160 * finite, so NaN/Infinity would be incorrect.
90161 */
90162
90163 duk__bi_set_small(&nc_ctx->f, 0);
90164 dig_prec = 0;
90165 dig_lzero = 0;
90166 dig_whole = 0;
90167 dig_frac = -1;
90168 dig_expt = -1;
90169 expt = 0;
90170 expt_adj = 0; /* essentially tracks digit position of lowest 'f' digit */
90171 expt_neg = 0;
90172 for (;;) {
90173 ch = *p++;
90174
90175 DUK_DDD(DUK_DDDPRINT("parse digits: p=%p, ch='%c' (%ld), expt=%ld, expt_adj=%ld, "
90176 "dig_whole=%ld, dig_frac=%ld, dig_expt=%ld, dig_lzero=%ld, dig_prec=%ld",
90177 (const void *) p,
90178 (int) ((ch >= 0x20 && ch <= 0x7e) ? ch : '?'),
90179 (long) ch,
90180 (long) expt,
90181 (long) expt_adj,
90182 (long) dig_whole,
90183 (long) dig_frac,
90184 (long) dig_expt,
90185 (long) dig_lzero,
90186 (long) dig_prec));
90187 DUK__BI_PRINT("f", &nc_ctx->f);
90188
90189 /* Most common cases first. */
90190 if (ch >= (duk_small_int_t) '0' && ch <= (duk_small_int_t) '9') {
90191 dig = (duk_small_int_t) ch - '0' + 0;
90192 } else if (ch == (duk_small_int_t) '.') {
90193 /* A leading digit is not required in some cases, e.g. accept ".123".
90194 * In other cases (JSON.parse()) a leading digit is required. This
90195 * is checked for after the loop.
90196 */
90197 if (dig_frac >= 0 || dig_expt >= 0) {
90198 if (flags & DUK_S2N_FLAG_ALLOW_GARBAGE) {
90199 DUK_DDD(DUK_DDDPRINT("garbage termination (invalid period)"));
90200 break;
90201 } else {
90202 DUK_DDD(DUK_DDDPRINT("parse failed: period not allowed"));
90203 goto parse_fail;
90204 }
90205 }
90206
90207 if ((flags & DUK_S2N_FLAG_ALLOW_FRAC) == 0) {
90208 /* Some contexts don't allow fractions at all; this can't be a
90209 * post-check because the state ('f' and expt) would be incorrect.
90210 */
90211 if (flags & DUK_S2N_FLAG_ALLOW_GARBAGE) {
90212 DUK_DDD(DUK_DDDPRINT("garbage termination (invalid first period)"));
90213 break;
90214 } else {
90215 DUK_DDD(DUK_DDDPRINT("parse failed: fraction part not allowed"));
90216 }
90217 }
90218
90219 DUK_DDD(DUK_DDDPRINT("start fraction part"));
90220 dig_frac = 0;
90221 continue;
90222 } else if (ch == (duk_small_int_t) 0) {
90223 DUK_DDD(DUK_DDDPRINT("NUL termination"));
90224 break;
90225 } else if ((flags & DUK_S2N_FLAG_ALLOW_EXP) && dig_expt < 0 &&
90226 (ch == (duk_small_int_t) 'e' || ch == (duk_small_int_t) 'E')) {
90227 /* Note: we don't parse back exponent notation for anything else
90228 * than radix 10, so this is not an ambiguous check (e.g. hex
90229 * exponent values may have 'e' either as a significand digit
90230 * or as an exponent separator).
90231 *
90232 * If the exponent separator occurs twice, 'e' will be interpreted
90233 * as a digit (= 14) and will be rejected as an invalid decimal
90234 * digit.
90235 */
90236
90237 DUK_DDD(DUK_DDDPRINT("start exponent part"));
90238
90239 /* Exponent without a sign or with a +/- sign is accepted
90240 * by all call sites (even JSON.parse()).
90241 */
90242 ch = *p;
90243 if (ch == (duk_small_int_t) '-') {
90244 expt_neg = 1;
90245 p++;
90246 } else if (ch == (duk_small_int_t) '+') {
90247 p++;
90248 }
90249 dig_expt = 0;
90250 continue;
90251 } else if (ch >= (duk_small_int_t) 'a' && ch <= (duk_small_int_t) 'z') {
90252 dig = (duk_small_int_t) (ch - (duk_small_int_t) 'a' + 0x0a);
90253 } else if (ch >= (duk_small_int_t) 'A' && ch <= (duk_small_int_t) 'Z') {
90254 dig = (duk_small_int_t) (ch - (duk_small_int_t) 'A' + 0x0a);
90255 } else {
90256 dig = 255; /* triggers garbage digit check below */
90257 }
90258 DUK_ASSERT((dig >= 0 && dig <= 35) || dig == 255);
90259
90260 if (dig >= radix) {
90261 if (flags & DUK_S2N_FLAG_ALLOW_GARBAGE) {
90262 DUK_DDD(DUK_DDDPRINT("garbage termination"));
90263 break;
90264 } else {
90265 DUK_DDD(DUK_DDDPRINT("parse failed: trailing garbage or invalid digit"));
90266 goto parse_fail;
90267 }
90268 }
90269
90270 if (dig_expt < 0) {
90271 /* whole or fraction digit */
90272
90273 if (dig_prec < duk__str2num_digits_for_radix[radix - 2]) {
90274 /* significant from precision perspective */
90275
90276 duk_small_int_t f_zero = duk__bi_is_zero(&nc_ctx->f);
90277 if (f_zero && dig == 0) {
90278 /* Leading zero is not counted towards precision digits; not
90279 * in the integer part, nor in the fraction part.
90280 */
90281 if (dig_frac < 0) {
90282 dig_lzero++;
90283 }
90284 } else {
90285 /* XXX: join these ops (multiply-accumulate), but only if
90286 * code footprint decreases.
90287 */
90288 duk__bi_mul_small(&nc_ctx->t1, &nc_ctx->f, (duk_uint32_t) radix);
90289 duk__bi_add_small(&nc_ctx->f, &nc_ctx->t1, (duk_uint32_t) dig);
90290 dig_prec++;
90291 }
90292 } else {
90293 /* Ignore digits beyond a radix-specific limit, but note them
90294 * in expt_adj.
90295 */
90296 expt_adj++;
90297 }
90298
90299 if (dig_frac >= 0) {
90300 dig_frac++;
90301 expt_adj--;
90302 } else {
90303 dig_whole++;
90304 }
90305 } else {
90306 /* exponent digit */
90307
90308 DUK_ASSERT(radix == 10);
90309 expt = expt * radix + dig;
90310 if (expt > DUK_S2N_MAX_EXPONENT) {
90311 /* Impose a reasonable exponent limit, so that exp
90312 * doesn't need to get tracked using a bigint.
90313 */
90314 DUK_DDD(DUK_DDDPRINT("parse failed: exponent too large"));
90315 goto parse_explimit_error;
90316 }
90317 dig_expt++;
90318 }
90319 }
90320
90321 /* Leading zero. */
90322
90323 if (dig_lzero > 0 && dig_whole > 1) {
90324 if ((flags & DUK_S2N_FLAG_ALLOW_LEADING_ZERO) == 0) {
90325 DUK_DDD(DUK_DDDPRINT("parse failed: leading zeroes not allowed in integer part"));
90326 goto parse_fail;
90327 }
90328 }
90329
90330 /* Validity checks for various fraction formats ("0.1", ".1", "1.", "."). */
90331
90332 if (dig_whole == 0) {
90333 if (dig_frac == 0) {
90334 /* "." is not accepted in any format */
90335 DUK_DDD(DUK_DDDPRINT("parse failed: plain period without leading or trailing digits"));
90336 goto parse_fail;
90337 } else if (dig_frac > 0) {
90338 /* ".123" */
90339 if ((flags & DUK_S2N_FLAG_ALLOW_NAKED_FRAC) == 0) {
90340 DUK_DDD(DUK_DDDPRINT("parse failed: fraction part not allowed without "
90341 "leading integer digit(s)"));
90342 goto parse_fail;
90343 }
90344 } else {
90345 /* Empty ("") is allowed in some formats (e.g. Number(''), as zero,
90346 * but it must not have a leading +/- sign (GH-2019). Note that
90347 * for Number(), h_str is already trimmed so we can check for zero
90348 * length and still get Number(' + ') == NaN.
90349 */
90350 if ((flags & DUK_S2N_FLAG_ALLOW_EMPTY_AS_ZERO) == 0) {
90351 DUK_DDD(DUK_DDDPRINT("parse failed: empty string not allowed (as zero)"));
90352 goto parse_fail;
90353 } else if (DUK_HSTRING_GET_BYTELEN(h_str) != 0) {
90354 DUK_DDD(DUK_DDDPRINT("parse failed: no digits, but not empty (had a +/- sign)"));
90355 goto parse_fail;
90356 }
90357 }
90358 } else {
90359 if (dig_frac == 0) {
90360 /* "123." is allowed in some formats */
90361 if ((flags & DUK_S2N_FLAG_ALLOW_EMPTY_FRAC) == 0) {
90362 DUK_DDD(DUK_DDDPRINT("parse failed: empty fractions"));
90363 goto parse_fail;
90364 }
90365 } else if (dig_frac > 0) {
90366 /* "123.456" */
90367 ;
90368 } else {
90369 /* "123" */
90370 ;
90371 }
90372 }
90373
90374 /* Exponent without digits (e.g. "1e" or "1e+"). If trailing garbage is
90375 * allowed, ignore exponent part as garbage (= parse as "1", i.e. exp 0).
90376 */
90377
90378 if (dig_expt == 0) {
90379 if ((flags & DUK_S2N_FLAG_ALLOW_GARBAGE) == 0) {
90380 DUK_DDD(DUK_DDDPRINT("parse failed: empty exponent"));
90381 goto parse_fail;
90382 }
90383 DUK_ASSERT(expt == 0);
90384 }
90385
90386 if (expt_neg) {
90387 expt = -expt;
90388 }
90389 DUK_DDD(
90390 DUK_DDDPRINT("expt=%ld, expt_adj=%ld, net exponent -> %ld", (long) expt, (long) expt_adj, (long) (expt + expt_adj)));
90391 expt += expt_adj;
90392
90393 /* Fast path check. */
90394
90395 if (nc_ctx->f.n <= 1 && /* 32-bit value */
90396 expt == 0 /* no net exponent */) {
90397 /* Fast path is triggered for no exponent and also for balanced exponent
90398 * and fraction parts, e.g. for "1.23e2" == "123". Remember to respect
90399 * zero sign.
90400 */
90401
90402 /* XXX: could accept numbers larger than 32 bits, e.g. up to 53 bits? */
90403 DUK_DDD(DUK_DDDPRINT("fast path number parse"));
90404 if (nc_ctx->f.n == 1) {
90405 res = (double) nc_ctx->f.v[0];
90406 } else {
90407 res = 0.0;
90408 }
90409 goto negcheck_and_ret;
90410 }
90411
90412 /* Significand ('f') padding. */
90413
90414 while (dig_prec < duk__str2num_digits_for_radix[radix - 2]) {
90415 /* Pad significand with "virtual" zero digits so that Dragon4 will
90416 * have enough (apparent) precision to work with.
90417 */
90418 DUK_DDD(DUK_DDDPRINT("dig_prec=%ld, pad significand with zero", (long) dig_prec));
90419 duk__bi_mul_small_copy(&nc_ctx->f, (duk_uint32_t) radix, &nc_ctx->t1);
90420 DUK__BI_PRINT("f", &nc_ctx->f);
90421 expt--;
90422 dig_prec++;
90423 }
90424
90425 DUK_DDD(DUK_DDDPRINT("final exponent: %ld", (long) expt));
90426
90427 /* Detect zero special case. */
90428
90429 if (nc_ctx->f.n == 0) {
90430 /* This may happen even after the fast path check, if exponent is
90431 * not balanced (e.g. "0e1"). Remember to respect zero sign.
90432 */
90433 DUK_DDD(DUK_DDDPRINT("significand is zero"));
90434 res = 0.0;
90435 goto negcheck_and_ret;
90436 }
90437
90438 /* Quick reject of too large or too small exponents. This check
90439 * would be incorrect for zero (e.g. "0e1000" is zero, not Infinity)
90440 * so zero check must be above.
90441 */
90442
90443 explim = &duk__str2num_exp_limits[radix - 2];
90444 if (expt > explim->upper) {
90445 DUK_DDD(DUK_DDDPRINT("exponent too large -> infinite"));
90447 goto negcheck_and_ret;
90448 } else if (expt < explim->lower) {
90449 DUK_DDD(DUK_DDDPRINT("exponent too small -> zero"));
90450 res = (duk_double_t) 0.0;
90451 goto negcheck_and_ret;
90452 }
90453
90454 nc_ctx->is_s2n = 1;
90455 nc_ctx->e = expt;
90456 nc_ctx->b = radix;
90457 nc_ctx->B = 2;
90458 nc_ctx->is_fixed = 1;
90459 nc_ctx->abs_pos = 0;
90460 nc_ctx->req_digits = 53 + 1;
90461
90462 DUK__BI_PRINT("f", &nc_ctx->f);
90463 DUK_DDD(DUK_DDDPRINT("e=%ld", (long) nc_ctx->e));
90464
90465 /*
90466 * Dragon4 slow path (binary) digit generation.
90467 * An extra digit is generated for rounding.
90468 */
90469
90470 duk__dragon4_prepare(nc_ctx); /* setup many variables in nc_ctx */
90471
90472 DUK_DDD(DUK_DDDPRINT("after prepare:"));
90473 DUK__BI_PRINT("r", &nc_ctx->r);
90474 DUK__BI_PRINT("s", &nc_ctx->s);
90475 DUK__BI_PRINT("mp", &nc_ctx->mp);
90476 DUK__BI_PRINT("mm", &nc_ctx->mm);
90477
90478 duk__dragon4_scale(nc_ctx);
90479
90480 DUK_DDD(DUK_DDDPRINT("after scale; k=%ld", (long) nc_ctx->k));
90481 DUK__BI_PRINT("r", &nc_ctx->r);
90482 DUK__BI_PRINT("s", &nc_ctx->s);
90483 DUK__BI_PRINT("mp", &nc_ctx->mp);
90484 DUK__BI_PRINT("mm", &nc_ctx->mm);
90485
90486 duk__dragon4_generate(nc_ctx);
90487
90488 DUK_ASSERT(nc_ctx->count == 53 + 1);
90489
90490 /*
90491 * Convert binary digits into an IEEE double. Need to handle
90492 * denormals and rounding correctly.
90493 *
90494 * Some call sites currently assume the result is always a
90495 * non-fastint double. If this is changed, check all call
90496 * sites.
90497 */
90498
90499 duk__dragon4_ctx_to_double(nc_ctx, &res);
90500 goto negcheck_and_ret;
90501
90502negcheck_and_ret:
90503 if (neg) {
90504 res = -res;
90505 }
90506 duk_pop(thr);
90507 duk_push_number(thr, (double) res);
90508 DUK_DDD(DUK_DDDPRINT("result: %!T", (duk_tval *) duk_get_tval(thr, -1)));
90509 return;
90510
90511parse_fail:
90512 DUK_DDD(DUK_DDDPRINT("parse failed"));
90513 duk_pop(thr);
90514 duk_push_nan(thr);
90515 return;
90516
90517parse_explimit_error:
90518 DUK_DDD(DUK_DDDPRINT("parse failed, internal error, can't return a value"));
90519 DUK_ERROR_RANGE(thr, "exponent too large");
90520 DUK_WO_NORETURN(return;);
90521}
90522
90525 duk__numconv_parse_raw(thr, radix, flags);
90526}
90527
90528/* automatic undefs */
90529#undef DUK__BI_MAX_PARTS
90530#undef DUK__BI_PRINT
90531#undef DUK__DIGITCHAR
90532#undef DUK__DRAGON4_OUTPUT_PREINC
90533#undef DUK__IEEE_DOUBLE_EXP_BIAS
90534#undef DUK__IEEE_DOUBLE_EXP_MIN
90535#undef DUK__MAX_FORMATTED_LENGTH
90536#undef DUK__MAX_OUTPUT_DIGITS
90537#undef DUK__NO_EXP
90538#undef DUK__NUMCONV_CTX_BIGINTS_SIZE
90539#undef DUK__NUMCONV_CTX_NUM_BIGINTS
90540/*
90541 * Regexp compilation.
90543 * See doc/regexp.rst for a discussion of the compilation approach and
90544 * current limitations.
90545 *
90546 * Regexp bytecode assumes jumps can be expressed with signed 32-bit
90547 * integers. Consequently the bytecode size must not exceed 0x7fffffffL.
90548 * The implementation casts duk_size_t (buffer size) to duk_(u)int32_t
90549 * in many places. Although this could be changed, the bytecode format
90550 * limit would still prevent regexps exceeding the signed 32-bit limit
90551 * from working.
90552 *
90553 * XXX: The implementation does not prevent bytecode from exceeding the
90554 * maximum supported size. This could be done by limiting the maximum
90555 * input string size (assuming an upper bound can be computed for number
90556 * of bytecode bytes emitted per input byte) or checking buffer maximum
90557 * size when emitting bytecode (slower).
90558 */
90559
90560/* #include duk_internal.h -> already included */
90561
90562#if defined(DUK_USE_REGEXP_SUPPORT)
90563
90564/*
90565 * Helper macros
90566 */
90567
90568#define DUK__RE_INITIAL_BUFSIZE 64
90569
90570#define DUK__RE_BUFLEN(re_ctx) DUK_BW_GET_SIZE(re_ctx->thr, &re_ctx->bw)
90571
90573 * Disjunction struct: result of parsing a disjunction
90574 */
90575
90576typedef struct {
90577 /* Number of characters that the atom matches (e.g. 3 for 'abc'),
90578 * -1 if atom is complex and number of matched characters either
90579 * varies or is not known.
90580 */
90581 duk_int32_t charlen;
90582
90583#if 0
90584 /* These are not needed to implement quantifier capture handling,
90585 * but might be needed at some point.
90586 */
90587
90588 /* re_ctx->captures at start and end of atom parsing.
90589 * Since 'captures' indicates highest capture number emitted
90590 * so far in a DUK_REOP_SAVE, the captures numbers saved by
90591 * the atom are: ]start_captures,end_captures].
90592 */
90593 duk_uint32_t start_captures;
90594 duk_uint32_t end_captures;
90595#endif
90598/*
90599 * Encoding helpers
90600 *
90601 * Some of the typing is bytecode based, e.g. slice sizes are unsigned 32-bit
90602 * even though the buffer operations will use duk_size_t.
90603 */
90604
90605/* XXX: the insert helpers should ensure that the bytecode result is not
90606 * larger than expected (or at least assert for it). Many things in the
90607 * bytecode, like skip offsets, won't work correctly if the bytecode is
90608 * larger than say 2G.
90609 */
90610
90611DUK_LOCAL duk_uint32_t duk__encode_i32(duk_int32_t x) {
90612 if (x < 0) {
90613 return ((duk_uint32_t) (-x)) * 2 + 1;
90614 } else {
90615 return ((duk_uint32_t) x) * 2;
90617}
90618
90619/* XXX: return type should probably be duk_size_t, or explicit checks are needed for
90620 * maximum size.
90621 */
90622DUK_LOCAL duk_uint32_t duk__insert_u32(duk_re_compiler_ctx *re_ctx, duk_uint32_t offset, duk_uint32_t x) {
90623 duk_uint8_t buf[DUK_UNICODE_MAX_XUTF8_LENGTH];
90624 duk_small_int_t len;
90625
90627 DUK_ASSERT(len >= 0);
90628 DUK_BW_INSERT_ENSURE_BYTES(re_ctx->thr, &re_ctx->bw, offset, buf, (duk_size_t) len);
90629 return (duk_uint32_t) len;
90630}
90631
90632DUK_LOCAL void duk__append_u32(duk_re_compiler_ctx *re_ctx, duk_uint32_t x) {
90633 DUK_BW_WRITE_ENSURE_XUTF8(re_ctx->thr, &re_ctx->bw, x);
90634}
90636DUK_LOCAL void duk__append_7bit(duk_re_compiler_ctx *re_ctx, duk_uint32_t x) {
90637#if defined(DUK_USE_PREFER_SIZE)
90638 duk__append_u32(re_ctx, x);
90639#else
90640 DUK_ASSERT(x <= 0x7fU);
90641 DUK_BW_WRITE_ENSURE_U8(re_ctx->thr, &re_ctx->bw, (duk_uint8_t) x);
90642#endif
90643}
90644
90645#if 0
90646DUK_LOCAL void duk__append_2bytes(duk_re_compiler_ctx *re_ctx, duk_uint8_t x, duk_uint8_t y) {
90647 DUK_BW_WRITE_ENSURE_U8_2(re_ctx->thr, &re_ctx->bw, x, y);
90648}
90649#endif
90650
90651DUK_LOCAL duk_uint32_t duk__insert_i32(duk_re_compiler_ctx *re_ctx, duk_uint32_t offset, duk_int32_t x) {
90652 return duk__insert_u32(re_ctx, offset, duk__encode_i32(x));
90653}
90654
90655DUK_LOCAL void duk__append_reop(duk_re_compiler_ctx *re_ctx, duk_uint32_t reop) {
90656 DUK_ASSERT(reop <= 0x7fU);
90657 (void) duk__append_7bit(re_ctx, reop);
90658}
90659
90660#if 0 /* unused */
90661DUK_LOCAL void duk__append_i32(duk_re_compiler_ctx *re_ctx, duk_int32_t x) {
90662 duk__append_u32(re_ctx, duk__encode_i32(x));
90664#endif
90665
90666/* special helper for emitting u16 lists (used for character ranges for built-in char classes) */
90667DUK_LOCAL void duk__append_u16_list(duk_re_compiler_ctx *re_ctx, const duk_uint16_t *values, duk_uint32_t count) {
90668 /* Call sites don't need the result length so it's not accumulated. */
90669 while (count-- > 0) {
90670 duk__append_u32(re_ctx, (duk_uint32_t) (*values++));
90671 }
90672}
90673
90675 duk_uint32_t offset,
90676 duk_uint32_t data_offset,
90677 duk_uint32_t data_length) {
90678 DUK_BW_INSERT_ENSURE_SLICE(re_ctx->thr, &re_ctx->bw, offset, data_offset, data_length);
90679}
90680
90681DUK_LOCAL void duk__append_slice(duk_re_compiler_ctx *re_ctx, duk_uint32_t data_offset, duk_uint32_t data_length) {
90682 DUK_BW_WRITE_ENSURE_SLICE(re_ctx->thr, &re_ctx->bw, data_offset, data_length);
90683}
90684
90685DUK_LOCAL void duk__remove_slice(duk_re_compiler_ctx *re_ctx, duk_uint32_t data_offset, duk_uint32_t data_length) {
90686 DUK_BW_REMOVE_ENSURE_SLICE(re_ctx->thr, &re_ctx->bw, data_offset, data_length);
90687}
90688
90689/*
90690 * Insert a jump offset at 'offset' to complete an instruction
90691 * (the jump offset is always the last component of an instruction).
90692 * The 'skip' argument must be computed relative to 'offset',
90693 * -without- taking into account the skip field being inserted.
90694 *
90695 * ... A B C ins X Y Z ... (ins may be a JUMP, SPLIT1/SPLIT2, etc)
90696 * => ... A B C ins SKIP X Y Z
90697 *
90698 * Computing the final (adjusted) skip value, which is relative to the
90699 * first byte of the next instruction, is a bit tricky because of the
90700 * variable length UTF-8 encoding. See doc/regexp.rst for discussion.
90701 */
90702DUK_LOCAL duk_uint32_t duk__insert_jump_offset(duk_re_compiler_ctx *re_ctx, duk_uint32_t offset, duk_int32_t skip) {
90703#if 0
90704 /* Iterative solution. */
90705 if (skip < 0) {
90706 duk_small_int_t len;
90707 /* two encoding attempts suffices */
90709 len = duk_unicode_get_xutf8_length((duk_codepoint_t) duk__encode_i32(skip - (duk_int32_t) len));
90710 DUK_ASSERT(duk_unicode_get_xutf8_length(duk__encode_i32(skip - (duk_int32_t) len)) == len); /* no change */
90711 skip -= (duk_int32_t) len;
90712 }
90713#endif
90714
90715#if defined(DUK_USE_PREFER_SIZE)
90716 /* Closed form solution, this produces smallest code.
90717 * See re_neg_jump_offset (closed2).
90718 */
90719 if (skip < 0) {
90720 skip--;
90721 if (skip < -0x3fL) {
90722 skip--;
90723 }
90724 if (skip < -0x3ffL) {
90725 skip--;
90726 }
90727 if (skip < -0x7fffL) {
90728 skip--;
90729 }
90730 if (skip < -0xfffffL) {
90731 skip--;
90732 }
90733 if (skip < -0x1ffffffL) {
90734 skip--;
90735 }
90736 if (skip < -0x3fffffffL) {
90737 skip--;
90738 }
90739 }
90740#else /* DUK_USE_PREFER_SIZE */
90741 /* Closed form solution, this produces fastest code.
90742 * See re_neg_jump_offset (closed1).
90743 */
90744 if (skip < 0) {
90745 if (skip >= -0x3eL) {
90746 skip -= 1;
90747 } else if (skip >= -0x3fdL) {
90748 skip -= 2;
90749 } else if (skip >= -0x7ffcL) {
90750 skip -= 3;
90751 } else if (skip >= -0xffffbL) {
90752 skip -= 4;
90753 } else if (skip >= -0x1fffffaL) {
90754 skip -= 5;
90755 } else if (skip >= -0x3ffffff9L) {
90756 skip -= 6;
90757 } else {
90758 skip -= 7;
90759 }
90760 }
90761#endif /* DUK_USE_PREFER_SIZE */
90762
90763 return duk__insert_i32(re_ctx, offset, skip);
90764}
90765
90766DUK_LOCAL duk_uint32_t duk__append_jump_offset(duk_re_compiler_ctx *re_ctx, duk_int32_t skip) {
90767 return (duk_uint32_t) duk__insert_jump_offset(re_ctx, (duk_uint32_t) DUK__RE_BUFLEN(re_ctx), skip);
90768}
90769
90770/*
90771 * duk_re_range_callback for generating character class ranges.
90772 *
90773 * When ignoreCase is false, the range is simply emitted as is. We don't,
90774 * for instance, eliminate duplicates or overlapping ranges in a character
90775 * class.
90776 *
90777 * When ignoreCase is true but the 'direct' flag is set, the caller knows
90778 * that the range canonicalizes to itself for case insensitive matching,
90779 * so the range is emitted as is. This is mainly useful for built-in ranges
90780 * like \W.
90781 *
90782 * Otherwise, when ignoreCase is true, the range needs to be normalized
90783 * through canonicalization. Unfortunately a canonicalized version of a
90784 * continuous range is not necessarily continuous (e.g. [x-{] is continuous
90785 * but [X-{] is not). As a result, a single input range may expand to a lot
90786 * of output ranges. The current algorithm creates the canonicalized ranges
90787 * footprint efficiently at the cost of compile time execution time; see
90788 * doc/regexp.rst for discussion, and some more details below.
90789 *
90790 * Note that the ctx->nranges is a context-wide temporary value. This is OK
90791 * because there cannot be multiple character classes being parsed
90792 * simultaneously.
90793 *
90794 * More detail on canonicalization:
90795 *
90796 * Conceptually, a range is canonicalized by scanning the entire range,
90797 * normalizing each codepoint by converting it to uppercase, and generating
90798 * a set of result ranges.
90799 *
90800 * Ideally a minimal set of output ranges would be emitted by merging all
90801 * possible ranges even if they're emitted out of sequence. Because the
90802 * input string is also case normalized during matching, some codepoints
90803 * never occur at runtime; these "don't care" codepoints can be included or
90804 * excluded from ranges when merging/optimizing ranges.
90805 *
90806 * The current algorithm does not do optimal range merging. Rather, output
90807 * codepoints are generated in sequence, and when the output codepoints are
90808 * continuous (CP, CP+1, CP+2, ...), they are merged locally into as large a
90809 * range as possible. A small canonicalization bitmap is used to reduce
90810 * actual codepoint canonicalizations which are quite slow at present. The
90811 * bitmap provides a "codepoint block is continuous with respect to
90812 * canonicalization" for N-codepoint blocks. This allows blocks to be
90813 * skipped quickly.
90814 *
90815 * There are a number of shortcomings and future work here:
90816 *
90817 * - Individual codepoint normalizations are slow because they involve
90818 * walking bit-packed rules without a lookup index.
90819 *
90820 * - The conceptual algorithm needs to canonicalize every codepoint in the
90821 * input range to figure out the output range(s). Even with the small
90822 * canonicalization bitmap the algorithm runs quite slowly for worst case
90823 * inputs. There are many data structure alternatives to improve this.
90824 *
90825 * - While the current algorithm generates maximal output ranges when the
90826 * output codepoints are emitted linearly, output ranges are not sorted or
90827 * merged otherwise. In the worst case a lot of ranges are emitted when
90828 * most of the ranges could be merged. In this process one could take
90829 * advantage of "don't care" codepoints, which are never matched against at
90830 * runtime due to canonicalization of input codepoints before comparison,
90831 * to merge otherwise discontinuous output ranges.
90832 *
90833 * - The runtime data structure is just a linear list of ranges to match
90834 * against. This can be quite slow if there are a lot of output ranges.
90835 * There are various ways to make matching against the ranges faster,
90836 * e.g. sorting the ranges and using a binary search; skip lists; tree
90837 * based representations; full or approximate codepoint bitmaps, etc.
90838 *
90839 * - Only BMP is supported, codepoints above BMP are assumed to canonicalize
90840 * to themselves. For now this is one place where we don't want to
90841 * support chars outside the BMP, because the exhaustive search would be
90842 * massively larger. It would be possible to support non-BMP with a
90843 * different algorithm, or perhaps doing case normalization only at match
90844 * time.
90845 */
90846
90848 DUK_ASSERT(r2 >= r1);
90849 duk__append_u32(re_ctx, (duk_uint32_t) r1);
90850 duk__append_u32(re_ctx, (duk_uint32_t) r2);
90851 re_ctx->nranges++;
90852}
90853
90854#if defined(DUK_USE_REGEXP_CANON_BITMAP)
90855/* Find next canonicalization discontinuity (conservative estimate) starting
90856 * from 'start', not exceeding 'end'. If continuity is fine up to 'end'
90857 * inclusive, returns end. Minimum possible return value is start.
90858 */
90860 duk_uint_t start_blk;
90861 duk_uint_t end_blk;
90862 duk_uint_t blk;
90863 duk_uint_t offset;
90864 duk_uint8_t mask;
90865
90866 /* Inclusive block range. */
90867 DUK_ASSERT(start >= 0);
90868 DUK_ASSERT(end >= 0);
90869 DUK_ASSERT(end >= start);
90870 start_blk = (duk_uint_t) (start >> DUK_CANON_BITMAP_BLKSHIFT);
90872
90873 for (blk = start_blk; blk <= end_blk; blk++) {
90874 offset = blk >> 3;
90875 mask = 1U << (blk & 0x07);
90876 if (offset >= sizeof(duk_unicode_re_canon_bitmap)) {
90877 /* Reached non-BMP range which is assumed continuous. */
90878 return end;
90879 }
90880 DUK_ASSERT(offset < sizeof(duk_unicode_re_canon_bitmap));
90881 if ((duk_unicode_re_canon_bitmap[offset] & mask) == 0) {
90882 /* Block is discontinuous, continuity is guaranteed
90883 * only up to end of previous block (+1 for exclusive
90884 * return value => start of current block). Start
90885 * block requires special handling.
90886 */
90887 if (blk > start_blk) {
90889 } else {
90890 return start;
90891 }
90892 }
90893 }
90894 DUK_ASSERT(blk == end_blk + 1); /* Reached end block which is continuous. */
90895 return end;
90896}
90897#else /* DUK_USE_REGEXP_CANON_BITMAP */
90899 DUK_ASSERT(start >= 0);
90900 DUK_ASSERT(end >= 0);
90901 DUK_ASSERT(end >= start);
90902 if (start >= 0x10000) {
90903 /* Even without the bitmap, treat non-BMP as continuous. */
90904 return end;
90905 }
90906 return start;
90907}
90908#endif /* DUK_USE_REGEXP_CANON_BITMAP */
90909
90911 duk_re_compiler_ctx *re_ctx = (duk_re_compiler_ctx *) userdata;
90912 duk_codepoint_t r_start;
90913 duk_codepoint_t r_end;
90916 duk_codepoint_t r_disc;
90917
90918 DUK_DD(DUK_DDPRINT("duk__regexp_generate_ranges(): re_ctx=%p, range=[%ld,%ld] direct=%ld",
90919 (void *) re_ctx,
90920 (long) r1,
90921 (long) r2,
90922 (long) direct));
90923
90924 DUK_ASSERT(r2 >= r1); /* SyntaxError for out of order range. */
90925
90926 if (direct || (re_ctx->re_flags & DUK_RE_FLAG_IGNORE_CASE) == 0) {
90927 DUK_DD(DUK_DDPRINT("direct or not case sensitive, emit range: [%ld,%ld]", (long) r1, (long) r2));
90928 duk__regexp_emit_range(re_ctx, r1, r2);
90929 return;
90930 }
90931
90932 DUK_DD(DUK_DDPRINT("case sensitive, process range: [%ld,%ld]", (long) r1, (long) r2));
90933
90934 r_start = duk_unicode_re_canonicalize_char(re_ctx->thr, r1);
90935 r_end = r_start;
90936
90937 for (i = r1 + 1; i <= r2;) {
90938 /* Input codepoint space processed up to i-1, and
90939 * current range in r_{start,end} is up-to-date
90940 * (inclusive) and may either break or continue.
90941 */
90942 r_disc = duk__re_canon_next_discontinuity(i, r2);
90943 DUK_ASSERT(r_disc >= i);
90944 DUK_ASSERT(r_disc <= r2);
90945
90946 r_end += r_disc - i; /* May be zero. */
90947 t = duk_unicode_re_canonicalize_char(re_ctx->thr, r_disc);
90948 if (t == r_end + 1) {
90949 /* Not actually a discontinuity, continue range
90950 * to r_disc and recheck.
90951 */
90952 r_end = t;
90953 } else {
90954 duk__regexp_emit_range(re_ctx, r_start, r_end);
90955 r_start = t;
90956 r_end = t;
90957 }
90958 i = r_disc + 1; /* Guarantees progress. */
90959 }
90960 duk__regexp_emit_range(re_ctx, r_start, r_end);
90961
90962#if 0 /* Exhaustive search, very slow. */
90963 r_start = duk_unicode_re_canonicalize_char(re_ctx->thr, r1);
90964 r_end = r_start;
90965 for (i = r1 + 1; i <= r2; i++) {
90966 t = duk_unicode_re_canonicalize_char(re_ctx->thr, i);
90967 if (t == r_end + 1) {
90968 r_end = t;
90969 } else {
90970 DUK_DD(DUK_DDPRINT("canonicalized, emit range: [%ld,%ld]", (long) r_start, (long) r_end));
90971 duk__append_u32(re_ctx, (duk_uint32_t) r_start);
90972 duk__append_u32(re_ctx, (duk_uint32_t) r_end);
90973 re_ctx->nranges++;
90974 r_start = t;
90975 r_end = t;
90976 }
90977 }
90978 DUK_DD(DUK_DDPRINT("canonicalized, emit range: [%ld,%ld]", (long) r_start, (long) r_end));
90979 duk__append_u32(re_ctx, (duk_uint32_t) r_start);
90980 duk__append_u32(re_ctx, (duk_uint32_t) r_end);
90981 re_ctx->nranges++;
90982#endif
90983}
90984
90985/*
90986 * Parse regexp Disjunction. Most of regexp compilation happens here.
90987 *
90988 * Handles Disjunction, Alternative, and Term productions directly without
90989 * recursion. The only constructs requiring recursion are positive/negative
90990 * lookaheads, capturing parentheses, and non-capturing parentheses.
90991 *
90992 * The function determines whether the entire disjunction is a 'simple atom'
90993 * (see doc/regexp.rst discussion on 'simple quantifiers') and if so,
90994 * returns the atom character length which is needed by the caller to keep
90995 * track of its own atom character length. A disjunction with more than one
90996 * alternative is never considered a simple atom (although in some cases
90997 * that might be the case).
90998 *
90999 * Return value: simple atom character length or < 0 if not a simple atom.
91000 * Appends the bytecode for the disjunction matcher to the end of the temp
91001 * buffer.
91002 *
91003 * Regexp top level structure is:
91004 *
91005 * Disjunction = Term*
91006 * | Term* | Disjunction
91007 *
91008 * Term = Assertion
91009 * | Atom
91010 * | Atom Quantifier
91011 *
91012 * An empty Term sequence is a valid disjunction alternative (e.g. /|||c||/).
91013 *
91014 * Notes:
91015 *
91016 * * Tracking of the 'simple-ness' of the current atom vs. the entire
91017 * disjunction are separate matters. For instance, the disjunction
91018 * may be complex, but individual atoms may be simple. Furthermore,
91019 * simple quantifiers are used whenever possible, even if the
91020 * disjunction as a whole is complex.
91021 *
91022 * * The estimate of whether an atom is simple is conservative now,
91023 * and it would be possible to expand it. For instance, captures
91024 * cause the disjunction to be marked complex, even though captures
91025 * -can- be handled by simple quantifiers with some minor modifications.
91026 *
91027 * * Disjunction 'tainting' as 'complex' is handled at the end of the
91028 * main for loop collectively for atoms. Assertions, quantifiers,
91029 * and '|' tokens need to taint the result manually if necessary.
91030 * Assertions cannot add to result char length, only atoms (and
91031 * quantifiers) can; currently quantifiers will taint the result
91032 * as complex though.
91033 */
91034
91035DUK_LOCAL const duk_uint16_t * const duk__re_range_lookup1[3] = { duk_unicode_re_ranges_digit,
91038DUK_LOCAL const duk_uint8_t duk__re_range_lookup2[3] = { sizeof(duk_unicode_re_ranges_digit) / (2 * sizeof(duk_uint16_t)),
91039 sizeof(duk_unicode_re_ranges_white) / (2 * sizeof(duk_uint16_t)),
91040 sizeof(duk_unicode_re_ranges_wordchar) / (2 * sizeof(duk_uint16_t)) };
91041
91043 duk_small_uint_t re_op,
91044 const duk_uint16_t *ranges,
91046#if 0
91047 DUK_ASSERT(re_op <= 0x7fUL);
91048 DUK_ASSERT(count <= 0x7fUL);
91049 duk__append_2bytes(re_ctx, (duk_uint8_t) re_op, (duk_uint8_t) count);
91050#endif
91051 duk__append_reop(re_ctx, re_op);
91052 duk__append_7bit(re_ctx, count);
91053 duk__append_u16_list(re_ctx, ranges, count * 2);
91054}
91055
91057 duk_int32_t atom_start_offset = -1; /* negative -> no atom matched on previous round */
91058 duk_int32_t atom_char_length = 0; /* negative -> complex atom */
91059 duk_uint32_t atom_start_captures = re_ctx->captures; /* value of re_ctx->captures at start of atom */
91060 duk_int32_t unpatched_disjunction_split = -1;
91061 duk_int32_t unpatched_disjunction_jump = -1;
91062 duk_uint32_t entry_offset = (duk_uint32_t) DUK__RE_BUFLEN(re_ctx);
91063 duk_int32_t res_charlen = 0; /* -1 if disjunction is complex, char length if simple */
91064 duk__re_disjunction_info tmp_disj;
91065
91066 DUK_ASSERT(out_atom_info != NULL);
91067
91068 duk_native_stack_check(re_ctx->thr);
91069 if (re_ctx->recursion_depth >= re_ctx->recursion_limit) {
91071 DUK_WO_NORETURN(return;);
91072 }
91073 re_ctx->recursion_depth++;
91074
91075#if 0
91076 out_atom_info->start_captures = re_ctx->captures;
91077#endif
91078
91079 for (;;) {
91080 /* atom_char_length, atom_start_offset, atom_start_offset reflect the
91081 * atom matched on the previous loop. If a quantifier is encountered
91082 * on this loop, these are needed to handle the quantifier correctly.
91083 * new_atom_char_length etc are for the atom parsed on this round;
91084 * they're written to atom_char_length etc at the end of the round.
91085 */
91086 duk_int32_t new_atom_char_length; /* char length of the atom parsed in this loop */
91087 duk_int32_t new_atom_start_offset; /* bytecode start offset of the atom parsed in this loop
91088 * (allows quantifiers to copy the atom bytecode)
91089 */
91090 duk_uint32_t new_atom_start_captures; /* re_ctx->captures at the start of the atom parsed in this loop */
91091
91092 duk_lexer_parse_re_token(&re_ctx->lex, &re_ctx->curr_token);
91093
91095 "re token: %ld (num=%ld, char=%c)",
91096 (long) re_ctx->curr_token.t,
91097 (long) re_ctx->curr_token.num,
91098 (re_ctx->curr_token.num >= 0x20 && re_ctx->curr_token.num <= 0x7e) ? (int) re_ctx->curr_token.num : (int) '?'));
91099
91100 /* set by atom case clauses */
91101 new_atom_start_offset = -1;
91102 new_atom_char_length = -1;
91103 new_atom_start_captures = re_ctx->captures;
91104
91105 switch (re_ctx->curr_token.t) {
91106 case DUK_RETOK_DISJUNCTION: {
91107 /*
91108 * The handling here is a bit tricky. If a previous '|' has been processed,
91109 * we have a pending split1 and a pending jump (for a previous match). These
91110 * need to be back-patched carefully. See docs for a detailed example.
91111 */
91112
91113 /* patch pending jump and split */
91114 if (unpatched_disjunction_jump >= 0) {
91115 duk_uint32_t offset;
91116
91117 DUK_ASSERT(unpatched_disjunction_split >= 0);
91118 offset = (duk_uint32_t) unpatched_disjunction_jump;
91119 offset += duk__insert_jump_offset(re_ctx, offset, (duk_int32_t) (DUK__RE_BUFLEN(re_ctx) - offset));
91120 /* offset is now target of the pending split (right after jump) */
91122 (duk_uint32_t) unpatched_disjunction_split,
91123 (duk_int32_t) offset - unpatched_disjunction_split);
91124 }
91125
91126 /* add a new pending split to the beginning of the entire disjunction */
91127 (void) duk__insert_u32(re_ctx, entry_offset, DUK_REOP_SPLIT1); /* prefer direct execution */
91128 unpatched_disjunction_split = (duk_int32_t) (entry_offset + 1); /* +1 for opcode */
91129
91130 /* add a new pending match jump for latest finished alternative */
91132 unpatched_disjunction_jump = (duk_int32_t) DUK__RE_BUFLEN(re_ctx);
91133
91134 /* 'taint' result as complex */
91135 res_charlen = -1;
91136 break;
91137 }
91138 case DUK_RETOK_QUANTIFIER: {
91139 if (atom_start_offset < 0) {
91141 DUK_WO_NORETURN(return;);
91142 }
91143 if (re_ctx->curr_token.qmin > re_ctx->curr_token.qmax) {
91145 DUK_WO_NORETURN(return;);
91146 }
91147 if (atom_char_length >= 0) {
91148 /*
91149 * Simple atom
91150 *
91151 * If atom_char_length is zero, we'll have unbounded execution time for e.g.
91152 * /()*x/.exec('x'). We can't just skip the match because it might have some
91153 * side effects (for instance, if we allowed captures in simple atoms, the
91154 * capture needs to happen). The simple solution below is to force the
91155 * quantifier to match at most once, since the additional matches have no effect.
91156 *
91157 * With a simple atom there can be no capture groups, so no captures need
91158 * to be reset.
91159 */
91160 duk_int32_t atom_code_length;
91161 duk_uint32_t offset;
91162 duk_uint32_t qmin, qmax;
91163
91164 qmin = re_ctx->curr_token.qmin;
91165 qmax = re_ctx->curr_token.qmax;
91166 if (atom_char_length == 0) {
91167 /* qmin and qmax will be 0 or 1 */
91168 if (qmin > 1) {
91169 qmin = 1;
91170 }
91171 if (qmax > 1) {
91172 qmax = 1;
91173 }
91174 }
91175
91176 duk__append_reop(re_ctx, DUK_REOP_MATCH); /* complete 'sub atom' */
91177 atom_code_length = (duk_int32_t) (DUK__RE_BUFLEN(re_ctx) - (duk_size_t) atom_start_offset);
91178
91179 offset = (duk_uint32_t) atom_start_offset;
91180 if (re_ctx->curr_token.greedy) {
91181 offset += duk__insert_u32(re_ctx, offset, DUK_REOP_SQGREEDY);
91182 offset += duk__insert_u32(re_ctx, offset, qmin);
91183 offset += duk__insert_u32(re_ctx, offset, qmax);
91184 offset += duk__insert_u32(re_ctx, offset, (duk_uint32_t) atom_char_length);
91185 offset += duk__insert_jump_offset(re_ctx, offset, atom_code_length);
91186 } else {
91187 offset += duk__insert_u32(re_ctx, offset, DUK_REOP_SQMINIMAL);
91188 offset += duk__insert_u32(re_ctx, offset, qmin);
91189 offset += duk__insert_u32(re_ctx, offset, qmax);
91190 offset += duk__insert_jump_offset(re_ctx, offset, atom_code_length);
91191 }
91192 DUK_UNREF(offset); /* silence scan-build warning */
91193 } else {
91194 /*
91195 * Complex atom
91196 *
91197 * The original code is used as a template, and removed at the end
91198 * (this differs from the handling of simple quantifiers).
91199 *
91200 * NOTE: there is no current solution for empty atoms in complex
91201 * quantifiers. This would need some sort of a 'progress' instruction.
91202 *
91203 * XXX: impose limit on maximum result size, i.e. atom_code_len * atom_copies?
91204 */
91205 duk_int32_t atom_code_length;
91206 duk_uint32_t atom_copies;
91207 duk_uint32_t tmp_qmin, tmp_qmax;
91208
91209 /* pre-check how many atom copies we're willing to make (atom_copies not needed below) */
91210 atom_copies = (re_ctx->curr_token.qmax == DUK_RE_QUANTIFIER_INFINITE) ? re_ctx->curr_token.qmin :
91211 re_ctx->curr_token.qmax;
91212 if (atom_copies > DUK_RE_MAX_ATOM_COPIES) {
91214 DUK_WO_NORETURN(return;);
91215 }
91216
91217 /* wipe the capture range made by the atom (if any) */
91218 DUK_ASSERT(atom_start_captures <= re_ctx->captures);
91219 if (atom_start_captures != re_ctx->captures) {
91220 DUK_ASSERT(atom_start_captures < re_ctx->captures);
91221 DUK_DDD(DUK_DDDPRINT("must wipe ]atom_start_captures,re_ctx->captures]: ]%ld,%ld]",
91222 (long) atom_start_captures,
91223 (long) re_ctx->captures));
91224
91225 /* insert (DUK_REOP_WIPERANGE, start, count) in reverse order so the order ends up right */
91226 duk__insert_u32(re_ctx,
91227 (duk_uint32_t) atom_start_offset,
91228 (re_ctx->captures - atom_start_captures) * 2U);
91229 duk__insert_u32(re_ctx, (duk_uint32_t) atom_start_offset, (atom_start_captures + 1) * 2);
91230 duk__insert_u32(re_ctx, (duk_uint32_t) atom_start_offset, DUK_REOP_WIPERANGE);
91231 } else {
91232 DUK_DDD(
91233 DUK_DDDPRINT("no need to wipe captures: atom_start_captures == re_ctx->captures == %ld",
91234 (long) atom_start_captures));
91235 }
91236
91237 atom_code_length = (duk_int32_t) DUK__RE_BUFLEN(re_ctx) - atom_start_offset;
91238
91239 /* insert the required matches (qmin) by copying the atom */
91240 tmp_qmin = re_ctx->curr_token.qmin;
91241 tmp_qmax = re_ctx->curr_token.qmax;
91242 while (tmp_qmin > 0) {
91243 duk__append_slice(re_ctx,
91244 (duk_uint32_t) atom_start_offset,
91245 (duk_uint32_t) atom_code_length);
91246 tmp_qmin--;
91247 if (tmp_qmax != DUK_RE_QUANTIFIER_INFINITE) {
91248 tmp_qmax--;
91249 }
91250 }
91251 DUK_ASSERT(tmp_qmin == 0);
91252
91253 /* insert code for matching the remainder - infinite or finite */
91254 if (tmp_qmax == DUK_RE_QUANTIFIER_INFINITE) {
91255 /* reuse last emitted atom for remaining 'infinite' quantifier */
91256
91257 if (re_ctx->curr_token.qmin == 0) {
91258 /* Special case: original qmin was zero so there is nothing
91259 * to repeat. Emit an atom copy but jump over it here.
91260 */
91262 duk__append_jump_offset(re_ctx, atom_code_length);
91263 duk__append_slice(re_ctx,
91264 (duk_uint32_t) atom_start_offset,
91265 (duk_uint32_t) atom_code_length);
91266 }
91267 if (re_ctx->curr_token.greedy) {
91268 duk__append_reop(re_ctx, DUK_REOP_SPLIT2); /* prefer jump */
91269 } else {
91270 duk__append_reop(re_ctx, DUK_REOP_SPLIT1); /* prefer direct */
91271 }
91272 duk__append_jump_offset(re_ctx, -atom_code_length - 1); /* -1 for opcode */
91273 } else {
91274 /*
91275 * The remaining matches are emitted as sequence of SPLITs and atom
91276 * copies; the SPLITs skip the remaining copies and match the sequel.
91277 * This sequence needs to be emitted starting from the last copy
91278 * because the SPLITs are variable length due to the variable length
91279 * skip offset. This causes a lot of memory copying now.
91280 *
91281 * Example structure (greedy, match maximum # atoms):
91282 *
91283 * SPLIT1 LSEQ
91284 * (atom)
91285 * SPLIT1 LSEQ ; <- the byte length of this instruction is needed
91286 * (atom) ; to encode the above SPLIT1 correctly
91287 * ...
91288 * LSEQ:
91289 */
91290 duk_uint32_t offset = (duk_uint32_t) DUK__RE_BUFLEN(re_ctx);
91291 while (tmp_qmax > 0) {
91292 duk__insert_slice(re_ctx,
91293 offset,
91294 (duk_uint32_t) atom_start_offset,
91295 (duk_uint32_t) atom_code_length);
91296 if (re_ctx->curr_token.greedy) {
91297 duk__insert_u32(re_ctx, offset, DUK_REOP_SPLIT1); /* prefer direct */
91298 } else {
91299 duk__insert_u32(re_ctx, offset, DUK_REOP_SPLIT2); /* prefer jump */
91300 }
91302 offset + 1, /* +1 for opcode */
91303 (duk_int32_t) (DUK__RE_BUFLEN(re_ctx) - (offset + 1)));
91304 tmp_qmax--;
91305 }
91306 }
91307
91308 /* remove the original 'template' atom */
91309 duk__remove_slice(re_ctx, (duk_uint32_t) atom_start_offset, (duk_uint32_t) atom_code_length);
91310 }
91311
91312 /* 'taint' result as complex */
91313 res_charlen = -1;
91314 break;
91315 }
91318 break;
91319 }
91320 case DUK_RETOK_ASSERT_END: {
91322 break;
91323 }
91326 break;
91327 }
91330 break;
91331 }
91334 duk_uint32_t offset;
91335 duk_uint32_t opcode =
91337
91338 offset = (duk_uint32_t) DUK__RE_BUFLEN(re_ctx);
91339 duk__parse_disjunction(re_ctx, 0, &tmp_disj);
91341
91342 (void) duk__insert_u32(re_ctx, offset, opcode);
91343 (void) duk__insert_jump_offset(re_ctx,
91344 offset + 1, /* +1 for opcode */
91345 (duk_int32_t) (DUK__RE_BUFLEN(re_ctx) - (offset + 1)));
91346
91347 /* 'taint' result as complex -- this is conservative,
91348 * as lookaheads do not backtrack.
91349 */
91350 res_charlen = -1;
91351 break;
91352 }
91353 case DUK_RETOK_ATOM_PERIOD: {
91354 new_atom_char_length = 1;
91355 new_atom_start_offset = (duk_int32_t) DUK__RE_BUFLEN(re_ctx);
91357 break;
91358 }
91359 case DUK_RETOK_ATOM_CHAR: {
91360 /* Note: successive characters could be joined into string matches
91361 * but this is not trivial (consider e.g. '/xyz+/); see docs for
91362 * more discussion.
91363 *
91364 * No support for \u{H+} yet. While only BMP Unicode escapes are
91365 * supported for RegExps at present, 'ch' may still be a non-BMP
91366 * codepoint if it is decoded straight from source text UTF-8.
91367 * There's no non-BMP support yet so this is handled simply by
91368 * matching the non-BMP character (which is custom behavior).
91369 */
91370 duk_uint32_t ch;
91371
91372 new_atom_char_length = 1;
91373 new_atom_start_offset = (duk_int32_t) DUK__RE_BUFLEN(re_ctx);
91375 ch = re_ctx->curr_token.num;
91376 if (re_ctx->re_flags & DUK_RE_FLAG_IGNORE_CASE) {
91377 ch = (duk_uint32_t) duk_unicode_re_canonicalize_char(re_ctx->thr, (duk_codepoint_t) ch);
91378 }
91379 duk__append_u32(re_ctx, ch);
91380 break;
91381 }
91388 duk_small_uint_t re_op;
91389 duk_small_uint_t idx;
91390
91391 new_atom_char_length = 1;
91392 new_atom_start_offset = (duk_int32_t) DUK__RE_BUFLEN(re_ctx);
91393
91394 DUK_ASSERT((DUK_RETOK_ATOM_DIGIT & 0x01) != 0);
91395 DUK_ASSERT((DUK_RETOK_ATOM_WHITE & 0x01) != 0);
91396 DUK_ASSERT((DUK_RETOK_ATOM_WORD_CHAR & 0x01) != 0);
91397 DUK_ASSERT((DUK_RETOK_ATOM_NOT_DIGIT & 0x01) == 0);
91398 DUK_ASSERT((DUK_RETOK_ATOM_NOT_WHITE & 0x01) == 0);
91400 re_op = (re_ctx->curr_token.t & 0x01) ? DUK_REOP_RANGES : DUK_REOP_INVRANGES;
91401
91404 idx = (duk_small_uint_t) ((re_ctx->curr_token.t - DUK_RETOK_ATOM_DIGIT) >> 1U);
91405 DUK_ASSERT(idx <= 2U); /* Assume continuous token numbers; also checks negative underflow. */
91406
91408 break;
91409 }
91411 duk_uint32_t backref = (duk_uint32_t) re_ctx->curr_token.num;
91412 if (backref > re_ctx->highest_backref) {
91413 re_ctx->highest_backref = backref;
91414 }
91415 new_atom_char_length = -1; /* mark as complex */
91416 new_atom_start_offset = (duk_int32_t) DUK__RE_BUFLEN(re_ctx);
91418 duk__append_u32(re_ctx, backref);
91419 break;
91420 }
91422 duk_uint32_t cap;
91423
91424 new_atom_char_length = -1; /* mark as complex (capture handling) */
91425 new_atom_start_offset = (duk_int32_t) DUK__RE_BUFLEN(re_ctx);
91426 cap = ++re_ctx->captures;
91428 duk__append_u32(re_ctx, cap * 2);
91430 0,
91431 &tmp_disj); /* retval (sub-atom char length) unused, tainted as complex above */
91433 duk__append_u32(re_ctx, cap * 2 + 1);
91434 break;
91435 }
91437 new_atom_start_offset = (duk_int32_t) DUK__RE_BUFLEN(re_ctx);
91438 duk__parse_disjunction(re_ctx, 0, &tmp_disj);
91439 new_atom_char_length = tmp_disj.charlen;
91440 break;
91441 }
91444 /*
91445 * Range parsing is done with a special lexer function which calls
91446 * us for every range parsed. This is different from how rest of
91447 * the parsing works, but avoids a heavy, arbitrary size intermediate
91448 * value type to hold the ranges.
91449 *
91450 * Another complication is the handling of character ranges when
91451 * case insensitive matching is used (see docs for discussion).
91452 * The range handler callback given to the lexer takes care of this
91453 * as well.
91454 *
91455 * Note that duplicate ranges are not eliminated when parsing character
91456 * classes, so that canonicalization of
91457 *
91458 * [0-9a-fA-Fx-{]
91459 *
91460 * creates the result (note the duplicate ranges):
91461 *
91462 * [0-9A-FA-FX-Z{-{]
91463 *
91464 * where [x-{] is split as a result of canonicalization. The duplicate
91465 * ranges are not a semantics issue: they work correctly.
91466 */
91467
91468 duk_uint32_t offset;
91469
91470 DUK_DD(DUK_DDPRINT("character class"));
91471
91472 /* insert ranges instruction, range count patched in later */
91473 new_atom_char_length = 1;
91474 new_atom_start_offset = (duk_int32_t) DUK__RE_BUFLEN(re_ctx);
91475 duk__append_reop(re_ctx,
91478 offset = (duk_uint32_t) DUK__RE_BUFLEN(re_ctx); /* patch in range count later */
91479
91480 /* parse ranges until character class ends */
91481 re_ctx->nranges = 0; /* note: ctx-wide temporary */
91482 duk_lexer_parse_re_ranges(&re_ctx->lex, duk__regexp_generate_ranges, (void *) re_ctx);
91483
91484 /* insert range count */
91485 duk__insert_u32(re_ctx, offset, re_ctx->nranges);
91486 break;
91487 }
91489 if (expect_eof) {
91491 DUK_WO_NORETURN(return;);
91492 }
91493 goto done;
91494 }
91495 case DUK_RETOK_EOF: {
91496 if (!expect_eof) {
91498 DUK_WO_NORETURN(return;);
91499 }
91500 goto done;
91501 }
91502 default: {
91504 DUK_WO_NORETURN(return;);
91505 }
91506 }
91507
91508 /* a complex (new) atom taints the result */
91509 if (new_atom_start_offset >= 0) {
91510 if (new_atom_char_length < 0) {
91511 res_charlen = -1;
91512 } else if (res_charlen >= 0) {
91513 /* only advance if not tainted */
91514 res_charlen += new_atom_char_length;
91515 }
91516 }
91517
91518 /* record previous atom info in case next token is a quantifier */
91519 atom_start_offset = new_atom_start_offset;
91520 atom_char_length = new_atom_char_length;
91521 atom_start_captures = new_atom_start_captures;
91522 }
91523
91524done:
91525
91526 /* finish up pending jump and split for last alternative */
91527 if (unpatched_disjunction_jump >= 0) {
91528 duk_uint32_t offset;
91529
91530 DUK_ASSERT(unpatched_disjunction_split >= 0);
91531 offset = (duk_uint32_t) unpatched_disjunction_jump;
91532 offset += duk__insert_jump_offset(re_ctx, offset, (duk_int32_t) (DUK__RE_BUFLEN(re_ctx) - offset));
91533 /* offset is now target of the pending split (right after jump) */
91535 (duk_uint32_t) unpatched_disjunction_split,
91536 (duk_int32_t) offset - unpatched_disjunction_split);
91537 }
91538
91539#if 0
91540 out_atom_info->end_captures = re_ctx->captures;
91541#endif
91542 out_atom_info->charlen = res_charlen;
91543 DUK_DDD(DUK_DDDPRINT("parse disjunction finished: charlen=%ld", (long) out_atom_info->charlen));
91544
91545 re_ctx->recursion_depth--;
91546}
91547
91548/*
91549 * Flags parsing (see E5 Section 15.10.4.1).
91550 */
91551
91553 const duk_uint8_t *p;
91554 const duk_uint8_t *p_end;
91555 duk_uint32_t flags = 0;
91556
91557 p = DUK_HSTRING_GET_DATA(h);
91558 p_end = p + DUK_HSTRING_GET_BYTELEN(h);
91559
91560 /* Note: can be safely scanned as bytes (undecoded) */
91561
91562 while (p < p_end) {
91563 duk_uint8_t c = *p++;
91564 switch (c) {
91565 case (duk_uint8_t) 'g': {
91566 if (flags & DUK_RE_FLAG_GLOBAL) {
91567 goto flags_error;
91568 }
91569 flags |= DUK_RE_FLAG_GLOBAL;
91570 break;
91571 }
91572 case (duk_uint8_t) 'i': {
91573 if (flags & DUK_RE_FLAG_IGNORE_CASE) {
91574 goto flags_error;
91575 }
91576 flags |= DUK_RE_FLAG_IGNORE_CASE;
91577 break;
91578 }
91579 case (duk_uint8_t) 'm': {
91581 goto flags_error;
91582 }
91583 flags |= DUK_RE_FLAG_MULTILINE;
91584 break;
91585 }
91586 default: {
91587 goto flags_error;
91588 }
91589 }
91590 }
91591
91592 return flags;
91593
91594flags_error:
91596 DUK_WO_NORETURN(return 0U;);
91597}
91598
91599/*
91600 * Create escaped RegExp source (E5 Section 15.10.3).
91601 *
91602 * The current approach is to special case the empty RegExp
91603 * ('' -> '(?:)') and otherwise replace unescaped '/' characters
91604 * with '\/' regardless of where they occur in the regexp.
91605 *
91606 * Note that normalization does not seem to be necessary for
91607 * RegExp literals (e.g. '/foo/') because to be acceptable as
91608 * a RegExp literal, the text between forward slashes must
91609 * already match the escaping requirements (e.g. must not contain
91610 * unescaped forward slashes or be empty). Escaping IS needed
91611 * for expressions like 'new Regexp("...", "")' however.
91612 * Currently, we re-escape in either case.
91613 *
91614 * Also note that we process the source here in UTF-8 encoded
91615 * form. This is correct, because any non-ASCII characters are
91616 * passed through without change.
91617 */
91618
91619DUK_LOCAL void duk__create_escaped_source(duk_hthread *thr, int idx_pattern) {
91620 duk_hstring *h;
91621 const duk_uint8_t *p;
91622 duk_bufwriter_ctx bw_alloc;
91624 duk_uint8_t *q;
91625 duk_size_t i, n;
91626 duk_uint_fast8_t c_prev, c;
91627
91628 h = duk_known_hstring(thr, idx_pattern);
91629 p = (const duk_uint8_t *) DUK_HSTRING_GET_DATA(h);
91631
91632 if (n == 0) {
91633 duk_push_literal(thr, "(?:)");
91634 return;
91635 }
91636
91637 bw = &bw_alloc;
91638 DUK_BW_INIT_PUSHBUF(thr, bw, n);
91639 q = DUK_BW_GET_PTR(thr, bw);
91640
91641 c_prev = (duk_uint_fast8_t) 0;
91642
91643 for (i = 0; i < n; i++) {
91644 c = p[i];
91645
91646 q = DUK_BW_ENSURE_RAW(thr, bw, 2, q);
91647
91648 if (c == (duk_uint_fast8_t) '/' && c_prev != (duk_uint_fast8_t) '\\') {
91649 /* Unescaped '/' ANYWHERE in the regexp (in disjunction,
91650 * inside a character class, ...) => same escape works.
91651 */
91652 *q++ = DUK_ASC_BACKSLASH;
91653 }
91654 *q++ = (duk_uint8_t) c;
91655
91656 c_prev = c;
91657 }
91658
91659 DUK_BW_SETPTR_AND_COMPACT(thr, bw, q);
91660 (void) duk_buffer_to_string(thr, -1); /* Safe if input is safe. */
91661
91662 /* [ ... escaped_source ] */
91663}
91664
91665/*
91666 * Exposed regexp compilation primitive.
91667 *
91668 * Sets up a regexp compilation context, and calls duk__parse_disjunction() to do the
91669 * actual parsing. Handles generation of the compiled regexp header and the
91670 * "boilerplate" capture of the matching substring (save 0 and 1). Also does some
91671 * global level regexp checks after recursive compilation has finished.
91672 *
91673 * An escaped version of the regexp source, suitable for use as a RegExp instance
91674 * 'source' property (see E5 Section 15.10.3), is also left on the stack.
91675 *
91676 * Input stack: [ pattern flags ]
91677 * Output stack: [ bytecode escaped_source ] (both as strings)
91678 */
91679
91681 duk_re_compiler_ctx re_ctx;
91682 duk_lexer_point lex_point;
91683 duk_hstring *h_pattern;
91684 duk_hstring *h_flags;
91685 duk__re_disjunction_info ign_disj;
91686
91687 DUK_ASSERT(thr != NULL);
91688
91689 /*
91690 * Args validation
91691 */
91692
91693 /* TypeError if fails */
91694 h_pattern = duk_require_hstring_notsymbol(thr, -2);
91695 h_flags = duk_require_hstring_notsymbol(thr, -1);
91696
91697 /*
91698 * Create normalized 'source' property (E5 Section 15.10.3).
91699 */
91700
91701 /* [ ... pattern flags ] */
91702
91704
91705 /* [ ... pattern flags escaped_source ] */
91706
91707 /*
91708 * Init compilation context
91709 */
91710
91711 /* [ ... pattern flags escaped_source buffer ] */
91712
91713 duk_memzero(&re_ctx, sizeof(re_ctx));
91714 DUK_LEXER_INITCTX(&re_ctx.lex); /* duplicate zeroing, expect for (possible) NULL inits */
91715 re_ctx.thr = thr;
91716 re_ctx.lex.thr = thr;
91717 re_ctx.lex.input = DUK_HSTRING_GET_DATA(h_pattern);
91718 re_ctx.lex.input_length = DUK_HSTRING_GET_BYTELEN(h_pattern);
91721 re_ctx.re_flags = duk__parse_regexp_flags(thr, h_flags);
91722
91724
91725 DUK_DD(DUK_DDPRINT("regexp compiler ctx initialized, flags=0x%08lx, recursion_limit=%ld",
91726 (unsigned long) re_ctx.re_flags,
91727 (long) re_ctx.recursion_limit));
91728
91729 /*
91730 * Init lexer
91731 */
91732
91733 lex_point.offset = 0; /* expensive init, just want to fill window */
91734 lex_point.line = 1;
91735 DUK_LEXER_SETPOINT(&re_ctx.lex, &lex_point);
91736
91737 /*
91738 * Compilation
91739 */
91740
91741 DUK_DD(DUK_DDPRINT("starting regexp compilation"));
91742
91744 duk__append_7bit(&re_ctx, 0);
91745 duk__parse_disjunction(&re_ctx, 1 /*expect_eof*/, &ign_disj);
91747 duk__append_7bit(&re_ctx, 1);
91749
91750 /*
91751 * Check for invalid backreferences; note that it is NOT an error
91752 * to back-reference a capture group which has not yet been introduced
91753 * in the pattern (as in /\1(foo)/); in fact, the backreference will
91754 * always match! It IS an error to back-reference a capture group
91755 * which will never be introduced in the pattern. Thus, we can check
91756 * for such references only after parsing is complete.
91757 */
91758
91759 if (re_ctx.highest_backref > re_ctx.captures) {
91761 DUK_WO_NORETURN(return;);
91763
91764 /*
91765 * Emit compiled regexp header: flags, ncaptures
91766 * (insertion order inverted on purpose)
91767 */
91768
91769 duk__insert_u32(&re_ctx, 0, (re_ctx.captures + 1) * 2);
91770 duk__insert_u32(&re_ctx, 0, re_ctx.re_flags);
91771
91772 /* [ ... pattern flags escaped_source buffer ] */
91773
91774 DUK_BW_COMPACT(thr, &re_ctx.bw);
91775 (void) duk_buffer_to_string(thr, -1); /* Safe because flags is at most 7 bit. */
91776
91777 /* [ ... pattern flags escaped_source bytecode ] */
91778
91779 /*
91780 * Finalize stack
91781 */
91782
91783 duk_remove(thr, -4); /* -> [ ... flags escaped_source bytecode ] */
91784 duk_remove(thr, -3); /* -> [ ... escaped_source bytecode ] */
91785
91786 DUK_DD(DUK_DDPRINT("regexp compilation successful, bytecode: %!T, escaped source: %!T",
91787 (duk_tval *) duk_get_tval(thr, -1),
91788 (duk_tval *) duk_get_tval(thr, -2)));
91789}
91790
91791/*
91792 * Create a RegExp instance (E5 Section 15.10.7).
91793 *
91794 * Note: the output stack left by duk_regexp_compile() is directly compatible
91795 * with the input here.
91796 *
91797 * Input stack: [ escaped_source bytecode ] (both as strings)
91798 * Output stack: [ RegExp ]
91799 */
91800
91802 duk_hobject *h;
91803
91804 /* [ ... escaped_source bytecode ] */
91805
91806 duk_push_object(thr);
91807 h = duk_known_hobject(thr, -1);
91808 duk_insert(thr, -3);
91809
91810 /* [ ... regexp_object escaped_source bytecode ] */
91811
91814
91816
91817 /* [ ... regexp_object escaped_source ] */
91818
91819 /* In ES2015 .source, and the .global, .multiline, etc flags are
91820 * inherited getters. Store the escaped source as an internal
91821 * property for the getter.
91822 */
91823
91825
91826 /* [ ... regexp_object ] */
91827
91828 duk_push_int(thr, 0);
91830
91831 /* [ ... regexp_object ] */
91832}
91833
91834#else /* DUK_USE_REGEXP_SUPPORT */
91836/* regexp support disabled */
91837
91838#endif /* DUK_USE_REGEXP_SUPPORT */
91839
91840/* automatic undefs */
91841#undef DUK__RE_BUFLEN
91842#undef DUK__RE_INITIAL_BUFSIZE
91843/*
91844 * Regexp executor.
91845 *
91846 * Safety: the ECMAScript executor should prevent user from reading and
91847 * replacing regexp bytecode. Even so, the executor must validate all
91848 * memory accesses etc. When an invalid access is detected (e.g. a 'save'
91849 * opcode to invalid, unallocated index) it should fail with an internal
91850 * error but not cause a segmentation fault.
91851 *
91852 * Notes:
91853 *
91854 * - Backtrack counts are limited to unsigned 32 bits but should
91855 * technically be duk_size_t for strings longer than 4G chars.
91856 * This also requires a regexp bytecode change.
91857 */
91858
91859/* #include duk_internal.h -> already included */
91860
91861#if defined(DUK_USE_REGEXP_SUPPORT)
91862
91863/*
91864 * Helpers for UTF-8 handling
91865 *
91866 * For bytecode readers the duk_uint32_t and duk_int32_t types are correct
91867 * because they're used for more than just codepoints.
91868 */
91869
91870DUK_LOCAL duk_uint32_t duk__bc_get_u32(duk_re_matcher_ctx *re_ctx, const duk_uint8_t **pc) {
91871 return (duk_uint32_t) duk_unicode_decode_xutf8_checked(re_ctx->thr, pc, re_ctx->bytecode, re_ctx->bytecode_end);
91872}
91873
91874DUK_LOCAL duk_int32_t duk__bc_get_i32(duk_re_matcher_ctx *re_ctx, const duk_uint8_t **pc) {
91875 duk_uint32_t t;
91876
91877 /* signed integer encoding needed to work with UTF-8 */
91878 t = (duk_uint32_t) duk_unicode_decode_xutf8_checked(re_ctx->thr, pc, re_ctx->bytecode, re_ctx->bytecode_end);
91879 if (t & 1) {
91880 return -((duk_int32_t) (t >> 1));
91881 } else {
91882 return (duk_int32_t) (t >> 1);
91883 }
91884}
91885
91886DUK_LOCAL const duk_uint8_t *duk__utf8_backtrack(duk_hthread *thr,
91887 const duk_uint8_t **ptr,
91888 const duk_uint8_t *ptr_start,
91889 const duk_uint8_t *ptr_end,
91891 const duk_uint8_t *p;
91892
91893 /* Note: allow backtracking from p == ptr_end */
91894 p = *ptr;
91895 if (p < ptr_start || p > ptr_end) {
91896 goto fail;
91897 }
91898
91899 while (count > 0) {
91900 for (;;) {
91901 p--;
91902 if (p < ptr_start) {
91903 goto fail;
91904 }
91905 if ((*p & 0xc0) != 0x80) {
91906 /* utf-8 continuation bytes have the form 10xx xxxx */
91907 break;
91908 }
91909 }
91910 count--;
91911 }
91912 *ptr = p;
91913 return p;
91914
91915fail:
91916 DUK_ERROR_INTERNAL(thr);
91917 DUK_WO_NORETURN(return NULL;);
91918}
91919
91920DUK_LOCAL const duk_uint8_t *duk__utf8_advance(duk_hthread *thr,
91921 const duk_uint8_t **ptr,
91922 const duk_uint8_t *ptr_start,
91923 const duk_uint8_t *ptr_end,
91925 const duk_uint8_t *p;
91926
91927 p = *ptr;
91928 if (p < ptr_start || p >= ptr_end) {
91929 goto fail;
91930 }
91931
91932 while (count > 0) {
91933 for (;;) {
91934 p++;
91935
91936 /* Note: if encoding ends by hitting end of input, we don't check that
91937 * the encoding is valid, we just assume it is.
91938 */
91939 if (p >= ptr_end || ((*p & 0xc0) != 0x80)) {
91940 /* utf-8 continuation bytes have the form 10xx xxxx */
91941 break;
91943 }
91944 count--;
91945 }
91946
91947 *ptr = p;
91948 return p;
91949
91950fail:
91951 DUK_ERROR_INTERNAL(thr);
91952 DUK_WO_NORETURN(return NULL;);
91953}
91954
91955/*
91956 * Helpers for dealing with the input string
91957 */
91958
91959/* Get a (possibly canonicalized) input character from current sp. The input
91960 * itself is never modified, and captures always record non-canonicalized
91961 * characters even in case-insensitive matching. Return <0 if out of input.
91962 */
91963DUK_LOCAL duk_codepoint_t duk__inp_get_cp(duk_re_matcher_ctx *re_ctx, const duk_uint8_t **sp) {
91964 duk_codepoint_t res;
91965
91966 if (*sp >= re_ctx->input_end) {
91967 return -1;
91968 }
91969 res = (duk_codepoint_t) duk_unicode_decode_xutf8_checked(re_ctx->thr, sp, re_ctx->input, re_ctx->input_end);
91970 if (re_ctx->re_flags & DUK_RE_FLAG_IGNORE_CASE) {
91971 res = duk_unicode_re_canonicalize_char(re_ctx->thr, res);
91972 }
91973 return res;
91974}
91975
91976DUK_LOCAL const duk_uint8_t *duk__inp_backtrack(duk_re_matcher_ctx *re_ctx, const duk_uint8_t **sp, duk_uint_fast32_t count) {
91977 return duk__utf8_backtrack(re_ctx->thr, sp, re_ctx->input, re_ctx->input_end, count);
91978}
91979
91980/* Backtrack utf-8 input and return a (possibly canonicalized) input character. */
91981DUK_LOCAL duk_codepoint_t duk__inp_get_prev_cp(duk_re_matcher_ctx *re_ctx, const duk_uint8_t *sp) {
91982 /* note: caller 'sp' is intentionally not updated here */
91983 (void) duk__inp_backtrack(re_ctx, &sp, (duk_uint_fast32_t) 1);
91984 return duk__inp_get_cp(re_ctx, &sp);
91985}
91986
91987/*
91988 * Regexp recursive matching function.
91989 *
91990 * Returns 'sp' on successful match (points to character after last matched one),
91991 * NULL otherwise.
91992 *
91993 * The C recursion depth limit check is only performed in this function, this
91994 * suffices because the function is present in all true recursion required by
91995 * regexp execution.
91996 */
91997
91998DUK_LOCAL const duk_uint8_t *duk__match_regexp(duk_re_matcher_ctx *re_ctx, const duk_uint8_t *pc, const duk_uint8_t *sp) {
91999 duk_native_stack_check(re_ctx->thr);
92000 if (re_ctx->recursion_depth >= re_ctx->recursion_limit) {
92002 DUK_WO_NORETURN(return NULL;);
92003 }
92004 re_ctx->recursion_depth++;
92005
92006 for (;;) {
92007 duk_small_int_t op;
92008
92009 if (re_ctx->steps_count >= re_ctx->steps_limit) {
92011 DUK_WO_NORETURN(return NULL;);
92012 }
92013 re_ctx->steps_count++;
92014
92015 /* Opcodes are at most 7 bits now so they encode to one byte. If this
92016 * were not the case or 'pc' is invalid here (due to a bug etc) we'll
92017 * still fail safely through the switch default case.
92018 */
92019 DUK_ASSERT(pc[0] <= 0x7fU);
92020#if 0
92021 op = (duk_small_int_t) duk__bc_get_u32(re_ctx, &pc);
92022#endif
92023 op = *pc++;
92024
92025 DUK_DDD(DUK_DDDPRINT("match: rec=%ld, steps=%ld, pc (after op)=%ld, sp=%ld, op=%ld",
92026 (long) re_ctx->recursion_depth,
92027 (long) re_ctx->steps_count,
92028 (long) (pc - re_ctx->bytecode),
92029 (long) (sp - re_ctx->input),
92030 (long) op));
92031
92032 switch (op) {
92033 case DUK_REOP_MATCH: {
92034 goto match;
92035 }
92036 case DUK_REOP_CHAR: {
92037 /*
92038 * Byte-based matching would be possible for case-sensitive
92039 * matching but not for case-insensitive matching. So, we
92040 * match by decoding the input and bytecode character normally.
92041 *
92042 * Bytecode characters are assumed to be already canonicalized.
92043 * Input characters are canonicalized automatically by
92044 * duk__inp_get_cp() if necessary.
92045 *
92046 * There is no opcode for matching multiple characters. The
92047 * regexp compiler has trouble joining strings efficiently
92048 * during compilation. See doc/regexp.rst for more discussion.
92049 */
92050 duk_codepoint_t c1, c2;
92051
92052 c1 = (duk_codepoint_t) duk__bc_get_u32(re_ctx, &pc);
92054 c1 == duk_unicode_re_canonicalize_char(re_ctx->thr, c1)); /* canonicalized by compiler */
92055 c2 = duk__inp_get_cp(re_ctx, &sp);
92056 /* No need to check for c2 < 0 (end of input): because c1 >= 0, it
92057 * will fail the match below automatically and cause goto fail.
92058 */
92059#if 0
92060 if (c2 < 0) {
92061 goto fail;
92062 }
92063#endif
92064 DUK_ASSERT(c1 >= 0);
92065
92066 DUK_DDD(DUK_DDDPRINT("char match, c1=%ld, c2=%ld", (long) c1, (long) c2));
92067 if (c1 != c2) {
92068 goto fail;
92069 }
92070 break;
92071 }
92072 case DUK_REOP_PERIOD: {
92074
92075 c = duk__inp_get_cp(re_ctx, &sp);
92076 if (c < 0 || duk_unicode_is_line_terminator(c)) {
92077 /* E5 Sections 15.10.2.8, 7.3 */
92078 goto fail;
92079 }
92080 break;
92081 }
92082 case DUK_REOP_RANGES:
92083 case DUK_REOP_INVRANGES: {
92084 duk_uint32_t n;
92086 duk_small_int_t match;
92087
92088 n = duk__bc_get_u32(re_ctx, &pc);
92089 c = duk__inp_get_cp(re_ctx, &sp);
92090 if (c < 0) {
92091 goto fail;
92092 }
92093
92094 match = 0;
92095 while (n) {
92096 duk_codepoint_t r1, r2;
92097 r1 = (duk_codepoint_t) duk__bc_get_u32(re_ctx, &pc);
92098 r2 = (duk_codepoint_t) duk__bc_get_u32(re_ctx, &pc);
92099 DUK_DDD(DUK_DDDPRINT("matching ranges/invranges, n=%ld, r1=%ld, r2=%ld, c=%ld",
92100 (long) n,
92101 (long) r1,
92102 (long) r2,
92103 (long) c));
92104 if (c >= r1 && c <= r2) {
92105 /* Note: don't bail out early, we must read all the ranges from
92106 * bytecode. Another option is to skip them efficiently after
92107 * breaking out of here. Prefer smallest code.
92108 */
92109 match = 1;
92110 }
92111 n--;
92112 }
92113
92114 if (op == DUK_REOP_RANGES) {
92115 if (!match) {
92116 goto fail;
92117 }
92118 } else {
92120 if (match) {
92121 goto fail;
92122 }
92123 }
92124 break;
92125 }
92126 case DUK_REOP_ASSERT_START: {
92128
92129 if (sp <= re_ctx->input) {
92130 break;
92131 }
92132 if (!(re_ctx->re_flags & DUK_RE_FLAG_MULTILINE)) {
92133 goto fail;
92134 }
92135 c = duk__inp_get_prev_cp(re_ctx, sp);
92137 /* E5 Sections 15.10.2.8, 7.3 */
92138 break;
92139 }
92140 goto fail;
92141 }
92142 case DUK_REOP_ASSERT_END: {
92144 const duk_uint8_t *tmp_sp;
92145
92146 tmp_sp = sp;
92147 c = duk__inp_get_cp(re_ctx, &tmp_sp);
92148 if (c < 0) {
92149 break;
92150 }
92151 if (!(re_ctx->re_flags & DUK_RE_FLAG_MULTILINE)) {
92152 goto fail;
92153 }
92155 /* E5 Sections 15.10.2.8, 7.3 */
92156 break;
92157 }
92158 goto fail;
92159 }
92162 /*
92163 * E5 Section 15.10.2.6. The previous and current character
92164 * should -not- be canonicalized as they are now. However,
92165 * canonicalization does not affect the result of IsWordChar()
92166 * (which depends on Unicode characters never canonicalizing
92167 * into ASCII characters) so this does not matter.
92168 */
92169 duk_small_int_t w1, w2;
92170
92171 if (sp <= re_ctx->input) {
92172 w1 = 0; /* not a wordchar */
92173 } else {
92175 c = duk__inp_get_prev_cp(re_ctx, sp);
92177 }
92178 if (sp >= re_ctx->input_end) {
92179 w2 = 0; /* not a wordchar */
92180 } else {
92181 const duk_uint8_t *tmp_sp = sp; /* dummy so sp won't get updated */
92183 c = duk__inp_get_cp(re_ctx, &tmp_sp);
92185 }
92186
92188 if (w1 == w2) {
92189 goto fail;
92190 }
92191 } else {
92193 if (w1 != w2) {
92194 goto fail;
92195 }
92196 }
92197 break;
92198 }
92199 case DUK_REOP_JUMP: {
92200 duk_int32_t skip;
92201
92202 skip = duk__bc_get_i32(re_ctx, &pc);
92203 pc += skip;
92204 break;
92205 }
92206 case DUK_REOP_SPLIT1: {
92207 /* split1: prefer direct execution (no jump) */
92208 const duk_uint8_t *sub_sp;
92209 duk_int32_t skip;
92210
92211 skip = duk__bc_get_i32(re_ctx, &pc);
92212 sub_sp = duk__match_regexp(re_ctx, pc, sp);
92213 if (sub_sp) {
92214 sp = sub_sp;
92215 goto match;
92216 }
92217 pc += skip;
92218 break;
92219 }
92220 case DUK_REOP_SPLIT2: {
92221 /* split2: prefer jump execution (not direct) */
92222 const duk_uint8_t *sub_sp;
92223 duk_int32_t skip;
92224
92225 skip = duk__bc_get_i32(re_ctx, &pc);
92226 sub_sp = duk__match_regexp(re_ctx, pc + skip, sp);
92227 if (sub_sp) {
92228 sp = sub_sp;
92229 goto match;
92230 }
92231 break;
92232 }
92233 case DUK_REOP_SQMINIMAL: {
92234 duk_uint32_t q, qmin, qmax;
92235 duk_int32_t skip;
92236 const duk_uint8_t *sub_sp;
92237
92238 qmin = duk__bc_get_u32(re_ctx, &pc);
92239 qmax = duk__bc_get_u32(re_ctx, &pc);
92240 skip = duk__bc_get_i32(re_ctx, &pc);
92241 DUK_DDD(DUK_DDDPRINT("minimal quantifier, qmin=%lu, qmax=%lu, skip=%ld",
92242 (unsigned long) qmin,
92243 (unsigned long) qmax,
92244 (long) skip));
92245
92246 q = 0;
92247 while (q <= qmax) {
92248 if (q >= qmin) {
92249 sub_sp = duk__match_regexp(re_ctx, pc + skip, sp);
92250 if (sub_sp) {
92251 sp = sub_sp;
92252 goto match;
92253 }
92254 }
92255 sub_sp = duk__match_regexp(re_ctx, pc, sp);
92256 if (!sub_sp) {
92257 break;
92258 }
92259 sp = sub_sp;
92260 q++;
92261 }
92262 goto fail;
92263 }
92264 case DUK_REOP_SQGREEDY: {
92265 duk_uint32_t q, qmin, qmax, atomlen;
92266 duk_int32_t skip;
92267 const duk_uint8_t *sub_sp;
92268
92269 qmin = duk__bc_get_u32(re_ctx, &pc);
92270 qmax = duk__bc_get_u32(re_ctx, &pc);
92271 atomlen = duk__bc_get_u32(re_ctx, &pc);
92272 skip = duk__bc_get_i32(re_ctx, &pc);
92273 DUK_DDD(DUK_DDDPRINT("greedy quantifier, qmin=%lu, qmax=%lu, atomlen=%lu, skip=%ld",
92274 (unsigned long) qmin,
92275 (unsigned long) qmax,
92276 (unsigned long) atomlen,
92277 (long) skip));
92278
92279 q = 0;
92280 while (q < qmax) {
92281 sub_sp = duk__match_regexp(re_ctx, pc, sp);
92282 if (!sub_sp) {
92283 break;
92284 }
92285 sp = sub_sp;
92286 q++;
92287 }
92288 while (q >= qmin) {
92289 sub_sp = duk__match_regexp(re_ctx, pc + skip, sp);
92290 if (sub_sp) {
92291 sp = sub_sp;
92292 goto match;
92293 }
92294 if (q == qmin) {
92295 break;
92296 }
92297
92298 /* Note: if atom were to contain e.g. captures, we would need to
92299 * re-match the atom to get correct captures. Simply quantifiers
92300 * do not allow captures in their atom now, so this is not an issue.
92301 */
92302
92303 DUK_DDD(DUK_DDDPRINT("greedy quantifier, backtrack %ld characters (atomlen)", (long) atomlen));
92304 sp = duk__inp_backtrack(re_ctx, &sp, (duk_uint_fast32_t) atomlen);
92305 q--;
92306 }
92307 goto fail;
92308 }
92309 case DUK_REOP_SAVE: {
92310 duk_uint32_t idx;
92311 const duk_uint8_t *old;
92312 const duk_uint8_t *sub_sp;
92313
92314 idx = duk__bc_get_u32(re_ctx, &pc);
92315 if (idx >= re_ctx->nsaved) {
92316 /* idx is unsigned, < 0 check is not necessary */
92317 DUK_D(DUK_DPRINT("internal error, regexp save index insane: idx=%ld", (long) idx));
92318 goto internal_error;
92319 }
92320 old = re_ctx->saved[idx];
92321 re_ctx->saved[idx] = sp;
92322 sub_sp = duk__match_regexp(re_ctx, pc, sp);
92323 if (sub_sp) {
92324 sp = sub_sp;
92325 goto match;
92326 }
92327 re_ctx->saved[idx] = old;
92328 goto fail;
92329 }
92330 case DUK_REOP_WIPERANGE: {
92331 /* Wipe capture range and save old values for backtracking.
92332 *
92333 * XXX: this typically happens with a relatively small idx_count.
92334 * It might be useful to handle cases where the count is small
92335 * (say <= 8) by saving the values in stack instead. This would
92336 * reduce memory churn and improve performance, at the cost of a
92337 * slightly higher code footprint.
92338 */
92339 duk_uint32_t idx_start, idx_count;
92340#if defined(DUK_USE_EXPLICIT_NULL_INIT)
92341 duk_uint32_t idx_end, idx;
92342#endif
92343 duk_uint8_t **range_save;
92344 const duk_uint8_t *sub_sp;
92345
92346 idx_start = duk__bc_get_u32(re_ctx, &pc);
92347 idx_count = duk__bc_get_u32(re_ctx, &pc);
92348 DUK_DDD(DUK_DDDPRINT("wipe saved range: start=%ld, count=%ld -> [%ld,%ld] (captures [%ld,%ld])",
92349 (long) idx_start,
92350 (long) idx_count,
92351 (long) idx_start,
92352 (long) (idx_start + idx_count - 1),
92353 (long) (idx_start / 2),
92354 (long) ((idx_start + idx_count - 1) / 2)));
92355 if (idx_start + idx_count > re_ctx->nsaved || idx_count == 0) {
92356 /* idx is unsigned, < 0 check is not necessary */
92357 DUK_D(DUK_DPRINT("internal error, regexp wipe indices insane: idx_start=%ld, idx_count=%ld",
92358 (long) idx_start,
92359 (long) idx_count));
92360 goto internal_error;
92361 }
92362 DUK_ASSERT(idx_count > 0);
92363
92364 duk_require_stack(re_ctx->thr, 1);
92365 range_save = (duk_uint8_t **) duk_push_fixed_buffer_nozero(re_ctx->thr, sizeof(duk_uint8_t *) * idx_count);
92366 DUK_ASSERT(range_save != NULL);
92367 duk_memcpy(range_save, re_ctx->saved + idx_start, sizeof(duk_uint8_t *) * idx_count);
92368#if defined(DUK_USE_EXPLICIT_NULL_INIT)
92369 idx_end = idx_start + idx_count;
92370 for (idx = idx_start; idx < idx_end; idx++) {
92371 re_ctx->saved[idx] = NULL;
92372 }
92373#else
92374 duk_memzero((void *) (re_ctx->saved + idx_start), sizeof(duk_uint8_t *) * idx_count);
92375#endif
92376
92377 sub_sp = duk__match_regexp(re_ctx, pc, sp);
92378 if (sub_sp) {
92379 /* match: keep wiped/resaved values */
92380 DUK_DDD(DUK_DDDPRINT("match: keep wiped/resaved values [%ld,%ld] (captures [%ld,%ld])",
92381 (long) idx_start,
92382 (long) (idx_start + idx_count - 1),
92383 (long) (idx_start / 2),
92384 (long) ((idx_start + idx_count - 1) / 2)));
92385 duk_pop_unsafe(re_ctx->thr);
92386 sp = sub_sp;
92387 goto match;
92388 }
92389
92390 /* fail: restore saves */
92391 DUK_DDD(DUK_DDDPRINT("fail: restore wiped/resaved values [%ld,%ld] (captures [%ld,%ld])",
92392 (long) idx_start,
92393 (long) (idx_start + idx_count - 1),
92394 (long) (idx_start / 2),
92395 (long) ((idx_start + idx_count - 1) / 2)));
92396 duk_memcpy((void *) (re_ctx->saved + idx_start),
92397 (const void *) range_save,
92398 sizeof(duk_uint8_t *) * idx_count);
92399 duk_pop_unsafe(re_ctx->thr);
92400 goto fail;
92401 }
92402 case DUK_REOP_LOOKPOS:
92403 case DUK_REOP_LOOKNEG: {
92404 /*
92405 * Needs a save of multiple saved[] entries depending on what range
92406 * may be overwritten. Because the regexp parser does no such analysis,
92407 * we currently save the entire saved array here. Lookaheads are thus
92408 * a bit expensive. Note that the saved array is not needed for just
92409 * the lookahead sub-match, but for the matching of the entire sequel.
92410 *
92411 * The temporary save buffer is pushed on to the valstack to handle
92412 * errors correctly. Each lookahead causes a C recursion and pushes
92413 * more stuff on the value stack. If the C recursion limit is less
92414 * than the value stack slack, there is no need to check the stack.
92415 * We do so regardless, just in case.
92416 */
92417
92418 duk_int32_t skip;
92419 duk_uint8_t **full_save;
92420 const duk_uint8_t *sub_sp;
92421
92422 DUK_ASSERT(re_ctx->nsaved > 0);
92423
92424 duk_require_stack(re_ctx->thr, 1);
92425 full_save =
92426 (duk_uint8_t **) duk_push_fixed_buffer_nozero(re_ctx->thr, sizeof(duk_uint8_t *) * re_ctx->nsaved);
92427 DUK_ASSERT(full_save != NULL);
92428 duk_memcpy(full_save, re_ctx->saved, sizeof(duk_uint8_t *) * re_ctx->nsaved);
92429
92430 skip = duk__bc_get_i32(re_ctx, &pc);
92431 sub_sp = duk__match_regexp(re_ctx, pc, sp);
92432 if (op == DUK_REOP_LOOKPOS) {
92433 if (!sub_sp) {
92434 goto lookahead_fail;
92435 }
92436 } else {
92437 if (sub_sp) {
92438 goto lookahead_fail;
92439 }
92440 }
92441 sub_sp = duk__match_regexp(re_ctx, pc + skip, sp);
92442 if (sub_sp) {
92443 /* match: keep saves */
92444 duk_pop_unsafe(re_ctx->thr);
92445 sp = sub_sp;
92446 goto match;
92447 }
92448
92449 /* fall through */
92450
92451 lookahead_fail:
92452 /* fail: restore saves */
92453 duk_memcpy((void *) re_ctx->saved, (const void *) full_save, sizeof(duk_uint8_t *) * re_ctx->nsaved);
92454 duk_pop_unsafe(re_ctx->thr);
92455 goto fail;
92456 }
92458 /*
92459 * Byte matching for back-references would be OK in case-
92460 * sensitive matching. In case-insensitive matching we need
92461 * to canonicalize characters, so back-reference matching needs
92462 * to be done with codepoints instead. So, we just decode
92463 * everything normally here, too.
92464 *
92465 * Note: back-reference index which is 0 or higher than
92466 * NCapturingParens (= number of capturing parens in the
92467 * -entire- regexp) is a compile time error. However, a
92468 * backreference referring to a valid capture which has
92469 * not matched anything always succeeds! See E5 Section
92470 * 15.10.2.9, step 5, sub-step 3.
92471 */
92472 duk_uint32_t idx;
92473 const duk_uint8_t *p;
92474
92475 idx = duk__bc_get_u32(re_ctx, &pc);
92476 idx = idx << 1; /* backref n -> saved indices [n*2, n*2+1] */
92477 if (idx < 2 || idx + 1 >= re_ctx->nsaved) {
92478 /* regexp compiler should catch these */
92479 DUK_D(DUK_DPRINT("internal error, backreference index insane"));
92480 goto internal_error;
92481 }
92482 if (!re_ctx->saved[idx] || !re_ctx->saved[idx + 1]) {
92483 /* capture is 'undefined', always matches! */
92484 DUK_DDD(DUK_DDDPRINT("backreference: saved[%ld,%ld] not complete, always match",
92485 (long) idx,
92486 (long) (idx + 1)));
92487 break;
92488 }
92489 DUK_DDD(DUK_DDDPRINT("backreference: match saved[%ld,%ld]", (long) idx, (long) (idx + 1)));
92490
92491 p = re_ctx->saved[idx];
92492 while (p < re_ctx->saved[idx + 1]) {
92493 duk_codepoint_t c1, c2;
92494
92495 /* Note: not necessary to check p against re_ctx->input_end:
92496 * the memory access is checked by duk__inp_get_cp(), while
92497 * valid compiled regexps cannot write a saved[] entry
92498 * which points to outside the string.
92499 */
92500 c1 = duk__inp_get_cp(re_ctx, &p);
92501 DUK_ASSERT(c1 >= 0);
92502 c2 = duk__inp_get_cp(re_ctx, &sp);
92503 /* No need for an explicit c2 < 0 check: because c1 >= 0,
92504 * the comparison will always fail if c2 < 0.
92505 */
92506#if 0
92507 if (c2 < 0) {
92508 goto fail;
92509 }
92510#endif
92511 if (c1 != c2) {
92512 goto fail;
92513 }
92514 }
92515 break;
92516 }
92517 default: {
92518 DUK_D(DUK_DPRINT("internal error, regexp opcode error: %ld", (long) op));
92519 goto internal_error;
92520 }
92521 }
92522 }
92523
92524match:
92525 re_ctx->recursion_depth--;
92526 return sp;
92527
92528fail:
92529 re_ctx->recursion_depth--;
92530 return NULL;
92531
92532internal_error:
92533 DUK_ERROR_INTERNAL(re_ctx->thr);
92534 DUK_WO_NORETURN(return NULL;);
92535}
92536
92537/*
92538 * Exposed matcher function which provides the semantics of RegExp.prototype.exec().
92539 *
92540 * RegExp.prototype.test() has the same semantics as exec() but does not return the
92541 * result object (which contains the matching string and capture groups). Currently
92542 * there is no separate test() helper, so a temporary result object is created and
92543 * discarded if test() is needed. This is intentional, to save code space.
92544 *
92545 * Input stack: [ ... re_obj input ]
92546 * Output stack: [ ... result ]
92547 */
92548
92550 duk_re_matcher_ctx re_ctx;
92551 duk_hobject *h_regexp;
92552 duk_hstring *h_bytecode;
92553 duk_hstring *h_input;
92554 duk_uint8_t *p_buf;
92555 const duk_uint8_t *pc;
92556 const duk_uint8_t *sp;
92557 duk_small_int_t match = 0;
92558 duk_small_int_t global;
92560 double d;
92561 duk_uint32_t char_offset;
92562
92563 DUK_ASSERT(thr != NULL);
92564
92565 DUK_DD(DUK_DDPRINT("regexp match: regexp=%!T, input=%!T",
92566 (duk_tval *) duk_get_tval(thr, -2),
92567 (duk_tval *) duk_get_tval(thr, -1)));
92568
92569 /*
92570 * Regexp instance check, bytecode check, input coercion.
92571 *
92572 * See E5 Section 15.10.6.
92573 */
92574
92575 /* TypeError if wrong; class check, see E5 Section 15.10.6 */
92577 DUK_ASSERT(h_regexp != NULL);
92579 DUK_UNREF(h_regexp);
92580
92581 h_input = duk_to_hstring(thr, -1);
92582 DUK_ASSERT(h_input != NULL);
92583
92584 duk_xget_owndataprop_stridx_short(thr, -2, DUK_STRIDX_INT_BYTECODE); /* [ ... re_obj input ] -> [ ... re_obj input bc ] */
92585 h_bytecode =
92586 duk_require_hstring(thr, -1); /* no regexp instance should exist without a non-configurable bytecode property */
92587 DUK_ASSERT(h_bytecode != NULL);
92588
92589 /*
92590 * Basic context initialization.
92591 *
92592 * Some init values are read from the bytecode header
92593 * whose format is (UTF-8 codepoints):
92594 *
92595 * uint flags
92596 * uint nsaved (even, 2n+2 where n = num captures)
92597 */
92598
92599 /* [ ... re_obj input bc ] */
92600
92601 duk_memzero(&re_ctx, sizeof(re_ctx));
92602
92603 re_ctx.thr = thr;
92604 re_ctx.input = (const duk_uint8_t *) DUK_HSTRING_GET_DATA(h_input);
92605 re_ctx.input_end = re_ctx.input + DUK_HSTRING_GET_BYTELEN(h_input);
92606 re_ctx.bytecode = (const duk_uint8_t *) DUK_HSTRING_GET_DATA(h_bytecode);
92607 re_ctx.bytecode_end = re_ctx.bytecode + DUK_HSTRING_GET_BYTELEN(h_bytecode);
92608 re_ctx.saved = NULL;
92611
92612 /* read header */
92613 pc = re_ctx.bytecode;
92614 re_ctx.re_flags = duk__bc_get_u32(&re_ctx, &pc);
92615 re_ctx.nsaved = duk__bc_get_u32(&re_ctx, &pc);
92616 re_ctx.bytecode = pc;
92617
92618 DUK_ASSERT(DUK_RE_FLAG_GLOBAL < 0x10000UL); /* must fit into duk_small_int_t */
92619 global = (duk_small_int_t) (force_global | (duk_small_int_t) (re_ctx.re_flags & DUK_RE_FLAG_GLOBAL));
92620
92621 DUK_ASSERT(re_ctx.nsaved >= 2);
92622 DUK_ASSERT((re_ctx.nsaved % 2) == 0);
92623
92624 p_buf = (duk_uint8_t *) duk_push_fixed_buffer(thr, sizeof(duk_uint8_t *) * re_ctx.nsaved); /* rely on zeroing */
92625 DUK_UNREF(p_buf);
92626 re_ctx.saved = (const duk_uint8_t **) duk_get_buffer(thr, -1, NULL);
92627 DUK_ASSERT(re_ctx.saved != NULL);
92628
92629 /* [ ... re_obj input bc saved_buf ] */
92630
92631#if defined(DUK_USE_EXPLICIT_NULL_INIT)
92632 for (i = 0; i < re_ctx.nsaved; i++) {
92633 re_ctx.saved[i] = (duk_uint8_t *) NULL;
92634 }
92635#elif defined(DUK_USE_ZERO_BUFFER_DATA)
92636 /* buffer is automatically zeroed */
92637#else
92638 duk_memzero((void *) p_buf, sizeof(duk_uint8_t *) * re_ctx.nsaved);
92639#endif
92640
92641 DUK_DDD(DUK_DDDPRINT("regexp ctx initialized, flags=0x%08lx, nsaved=%ld, recursion_limit=%ld, steps_limit=%ld",
92642 (unsigned long) re_ctx.re_flags,
92643 (long) re_ctx.nsaved,
92644 (long) re_ctx.recursion_limit,
92645 (long) re_ctx.steps_limit));
92646
92647 /*
92648 * Get starting character offset for match, and initialize 'sp' based on it.
92649 *
92650 * Note: lastIndex is non-configurable so it must be present (we check the
92651 * internal class of the object above, so we know it is). User code can set
92652 * its value to an arbitrary (garbage) value though; E5 requires that lastIndex
92653 * be coerced to a number before using. The code below works even if the
92654 * property is missing: the value will then be coerced to zero.
92655 *
92656 * Note: lastIndex may be outside Uint32 range even after ToInteger() coercion.
92657 * For instance, ToInteger(+Infinity) = +Infinity. We track the match offset
92658 * as an integer, but pre-check it to be inside the 32-bit range before the loop.
92659 * If not, the check in E5 Section 15.10.6.2, step 9.a applies.
92660 */
92661
92662 /* XXX: lastIndex handling produces a lot of asm */
92663
92664 /* [ ... re_obj input bc saved_buf ] */
92665
92666 duk_get_prop_stridx_short(thr, -4, DUK_STRIDX_LAST_INDEX); /* -> [ ... re_obj input bc saved_buf lastIndex ] */
92667 (void) duk_to_int(thr, -1); /* ToInteger(lastIndex) */
92668 d = duk_get_number(thr, -1); /* integer, but may be +/- Infinite, +/- zero (not NaN, though) */
92670
92671 if (global) {
92672 if (d < 0.0 || d > (double) DUK_HSTRING_GET_CHARLEN(h_input)) {
92673 /* match fail */
92674 char_offset = 0; /* not really necessary */
92675 DUK_ASSERT(match == 0);
92676 goto match_over;
92677 }
92678 char_offset = (duk_uint32_t) d;
92679 } else {
92680 /* lastIndex must be ignored for non-global regexps, but get the
92681 * value for (theoretical) side effects. No side effects can
92682 * really occur, because lastIndex is a normal property and is
92683 * always non-configurable for RegExp instances.
92684 */
92685 char_offset = (duk_uint32_t) 0;
92686 }
92687
92688 DUK_ASSERT(char_offset <= DUK_HSTRING_GET_CHARLEN(h_input));
92689 sp = re_ctx.input + duk_heap_strcache_offset_char2byte(thr, h_input, char_offset);
92690
92691 /*
92692 * Match loop.
92693 *
92694 * Try matching at different offsets until match found or input exhausted.
92695 */
92696
92697 /* [ ... re_obj input bc saved_buf ] */
92698
92699 DUK_ASSERT(match == 0);
92700
92701 for (;;) {
92702 /* char offset in [0, h_input->clen] (both ends inclusive), checked before entry */
92703 DUK_ASSERT_DISABLE(char_offset >= 0);
92704 DUK_ASSERT(char_offset <= DUK_HSTRING_GET_CHARLEN(h_input));
92705
92706 /* Note: re_ctx.steps is intentionally not reset, it applies to the entire unanchored match */
92707 DUK_ASSERT(re_ctx.recursion_depth == 0);
92708
92709 DUK_DDD(DUK_DDDPRINT("attempt match at char offset %ld; %p [%p,%p]",
92710 (long) char_offset,
92711 (const void *) sp,
92712 (const void *) re_ctx.input,
92713 (const void *) re_ctx.input_end));
92714
92715 /*
92716 * Note:
92717 *
92718 * - duk__match_regexp() is required not to longjmp() in ordinary "non-match"
92719 * conditions; a longjmp() will terminate the entire matching process.
92720 *
92721 * - Clearing saved[] is not necessary because backtracking does it
92722 *
92723 * - Backtracking also rewinds re_ctx.recursion back to zero, unless an
92724 * internal/limit error occurs (which causes a longjmp())
92725 *
92726 * - If we supported anchored matches, we would break out here
92727 * unconditionally; however, ECMAScript regexps don't have anchored
92728 * matches. It might make sense to implement a fast bail-out if
92729 * the regexp begins with '^' and sp is not 0: currently we'll just
92730 * run through the entire input string, trivially failing the match
92731 * at every non-zero offset.
92732 */
92733
92734 if (duk__match_regexp(&re_ctx, re_ctx.bytecode, sp) != NULL) {
92735 DUK_DDD(DUK_DDDPRINT("match at offset %ld", (long) char_offset));
92736 match = 1;
92737 break;
92738 }
92739
92740 /* advance by one character (code point) and one char_offset */
92741 char_offset++;
92742 if (char_offset > DUK_HSTRING_GET_CHARLEN(h_input)) {
92743 /*
92744 * Note:
92745 *
92746 * - Intentionally attempt (empty) match at char_offset == k_input->clen
92747 *
92748 * - Negative char_offsets have been eliminated and char_offset is duk_uint32_t
92749 * -> no need or use for a negative check
92750 */
92751
92752 DUK_DDD(DUK_DDDPRINT("no match after trying all sp offsets"));
92753 break;
92754 }
92755
92756 /* avoid calling at end of input, will DUK_ERROR (above check suffices to avoid this) */
92757 (void) duk__utf8_advance(thr, &sp, re_ctx.input, re_ctx.input_end, (duk_uint_fast32_t) 1);
92758 }
92759
92760match_over:
92761
92762 /*
92763 * Matching complete, create result array or return a 'null'. Update lastIndex
92764 * if necessary. See E5 Section 15.10.6.2.
92765 *
92766 * Because lastIndex is a character (not byte) offset, we need the character
92767 * length of the match which we conveniently get as a side effect of interning
92768 * the matching substring (0th index of result array).
92769 *
92770 * saved[0] start pointer (~ byte offset) of current match
92771 * saved[1] end pointer (~ byte offset) of current match (exclusive)
92772 * char_offset start character offset of current match (-> .index of result)
92773 * char_end_offset end character offset (computed below)
92774 */
92775
92776 /* [ ... re_obj input bc saved_buf ] */
92777
92778 if (match) {
92779#if defined(DUK_USE_ASSERTIONS)
92780 duk_hobject *h_res;
92781#endif
92782 duk_uint32_t char_end_offset = 0;
92783
92784 DUK_DDD(DUK_DDDPRINT("regexp matches at char_offset %ld", (long) char_offset));
92785
92786 DUK_ASSERT(re_ctx.nsaved >= 2); /* must have start and end */
92787 DUK_ASSERT((re_ctx.nsaved % 2) == 0); /* and even number */
92788
92789 /* XXX: Array size is known before and (2 * re_ctx.nsaved) but not taken
92790 * advantage of now. The array is not compacted either, as regexp match
92791 * objects are usually short lived.
92792 */
92793
92794 duk_push_array(thr);
92795
92796#if defined(DUK_USE_ASSERTIONS)
92797 h_res = duk_require_hobject(thr, -1);
92801#endif
92802
92803 /* [ ... re_obj input bc saved_buf res_obj ] */
92804
92805 duk_push_u32(thr, char_offset);
92807
92808 duk_dup_m4(thr);
92810
92811 for (i = 0; i < re_ctx.nsaved; i += 2) {
92812 /* Captures which are undefined have NULL pointers and are returned
92813 * as 'undefined'. The same is done when saved[] pointers are insane
92814 * (this should, of course, never happen in practice).
92815 */
92816 duk_push_uarridx(thr, (duk_uarridx_t) (i / 2));
92817
92818 if (re_ctx.saved[i] && re_ctx.saved[i + 1] && re_ctx.saved[i + 1] >= re_ctx.saved[i]) {
92819 duk_push_lstring(thr,
92820 (const char *) re_ctx.saved[i],
92821 (duk_size_t) (re_ctx.saved[i + 1] - re_ctx.saved[i]));
92822 if (i == 0) {
92823 /* Assumes that saved[0] and saved[1] are always
92824 * set by regexp bytecode (if not, char_end_offset
92825 * will be zero). Also assumes clen reflects the
92826 * correct char length.
92827 */
92828 char_end_offset = char_offset + (duk_uint32_t) duk_get_length(thr, -1); /* add charlen */
92829 }
92830 } else {
92831 duk_push_undefined(thr);
92832 }
92833
92834 /* [ ... re_obj input bc saved_buf res_obj idx val ] */
92836 }
92837
92838 /* [ ... re_obj input bc saved_buf res_obj ] */
92839
92840 /* NB: 'length' property is automatically updated by the array setup loop */
92841
92842 if (global) {
92843 /* global regexp: lastIndex updated on match */
92844 duk_push_u32(thr, char_end_offset);
92846 } else {
92847 /* non-global regexp: lastIndex never updated on match */
92848 ;
92849 }
92850 } else {
92851 /*
92852 * No match, E5 Section 15.10.6.2, step 9.a.i - 9.a.ii apply, regardless
92853 * of 'global' flag of the RegExp. In particular, if lastIndex is invalid
92854 * initially, it is reset to zero.
92855 */
92856
92857 DUK_DDD(DUK_DDDPRINT("regexp does not match"));
92858
92859 duk_push_null(thr);
92860
92861 /* [ ... re_obj input bc saved_buf res_obj ] */
92862
92863 duk_push_int(thr, 0);
92865 }
92866
92867 /* [ ... re_obj input bc saved_buf res_obj ] */
92868
92869 duk_insert(thr, -5);
92870
92871 /* [ ... res_obj re_obj input bc saved_buf ] */
92872
92873 duk_pop_n_unsafe(thr, 4);
92874
92875 /* [ ... res_obj ] */
92876
92877 /* XXX: these last tricks are unnecessary if the function is made
92878 * a genuine native function.
92879 */
92880}
92881
92883 duk__regexp_match_helper(thr, 0 /*force_global*/);
92884}
92885
92886/* This variant is needed by String.prototype.split(); it needs to perform
92887 * global-style matching on a cloned RegExp which is potentially non-global.
92888 */
92890 duk__regexp_match_helper(thr, 1 /*force_global*/);
92891}
92892
92893#else /* DUK_USE_REGEXP_SUPPORT */
92894
92895/* regexp support disabled */
92896
92897#endif /* DUK_USE_REGEXP_SUPPORT */
92898/*
92899 * Self tests to ensure execution environment is sane. Intended to catch
92900 * compiler/platform problems which cannot be detected at compile time.
92901 */
92902
92903/* #include duk_internal.h -> already included */
92904
92905#if defined(DUK_USE_SELF_TESTS)
92906
92907/*
92908 * Unions and structs for self tests
92909 */
92910
92911typedef union {
92912 double d;
92913 duk_uint8_t x[8];
92914} duk__test_double_union;
92915
92916/* Self test failed. Expects a local variable 'error_count' to exist. */
92917#define DUK__FAILED(msg) \
92918 do { \
92919 DUK_D(DUK_DPRINT("self test failed: " #msg " at " DUK_FILE_MACRO ":" DUK_MACRO_STRINGIFY(DUK_LINE_MACRO))); \
92920 error_count++; \
92921 } while (0)
92922
92923#define DUK__DBLUNION_CMP_TRUE(a, b) \
92924 do { \
92925 if (duk_memcmp((const void *) (a), (const void *) (b), sizeof(duk__test_double_union)) != 0) { \
92926 DUK__FAILED("double union compares false (expected true)"); \
92927 } \
92928 } while (0)
92929
92930#define DUK__DBLUNION_CMP_FALSE(a, b) \
92931 do { \
92932 if (duk_memcmp((const void *) (a), (const void *) (b), sizeof(duk__test_double_union)) == 0) { \
92933 DUK__FAILED("double union compares true (expected false)"); \
92934 } \
92935 } while (0)
92936
92937typedef union {
92938 duk_uint32_t i;
92939 duk_uint8_t x[8];
92940} duk__test_u32_union;
92941
92942#if defined(DUK_USE_INTEGER_LE)
92943#define DUK__U32_INIT(u, a, b, c, d) \
92944 do { \
92945 (u)->x[0] = (d); \
92946 (u)->x[1] = (c); \
92947 (u)->x[2] = (b); \
92948 (u)->x[3] = (a); \
92949 } while (0)
92950#elif defined(DUK_USE_INTEGER_ME)
92951#error integer mixed endian not supported now
92952#elif defined(DUK_USE_INTEGER_BE)
92953#define DUK__U32_INIT(u, a, b, c, d) \
92954 do { \
92955 (u)->x[0] = (a); \
92956 (u)->x[1] = (b); \
92957 (u)->x[2] = (c); \
92958 (u)->x[3] = (d); \
92959 } while (0)
92960#else
92961#error unknown integer endianness
92962#endif
92963
92964#if defined(DUK_USE_DOUBLE_LE)
92965#define DUK__DOUBLE_INIT(u, a, b, c, d, e, f, g, h) \
92966 do { \
92967 (u)->x[0] = (h); \
92968 (u)->x[1] = (g); \
92969 (u)->x[2] = (f); \
92970 (u)->x[3] = (e); \
92971 (u)->x[4] = (d); \
92972 (u)->x[5] = (c); \
92973 (u)->x[6] = (b); \
92974 (u)->x[7] = (a); \
92975 } while (0)
92976#define DUK__DOUBLE_COMPARE(u, a, b, c, d, e, f, g, h) \
92977 ((u)->x[0] == (h) && (u)->x[1] == (g) && (u)->x[2] == (f) && (u)->x[3] == (e) && (u)->x[4] == (d) && (u)->x[5] == (c) && \
92978 (u)->x[6] == (b) && (u)->x[7] == (a))
92979#elif defined(DUK_USE_DOUBLE_ME)
92980#define DUK__DOUBLE_INIT(u, a, b, c, d, e, f, g, h) \
92981 do { \
92982 (u)->x[0] = (d); \
92983 (u)->x[1] = (c); \
92984 (u)->x[2] = (b); \
92985 (u)->x[3] = (a); \
92986 (u)->x[4] = (h); \
92987 (u)->x[5] = (g); \
92988 (u)->x[6] = (f); \
92989 (u)->x[7] = (e); \
92990 } while (0)
92991#define DUK__DOUBLE_COMPARE(u, a, b, c, d, e, f, g, h) \
92992 ((u)->x[0] == (d) && (u)->x[1] == (c) && (u)->x[2] == (b) && (u)->x[3] == (a) && (u)->x[4] == (h) && (u)->x[5] == (g) && \
92993 (u)->x[6] == (f) && (u)->x[7] == (e))
92994#elif defined(DUK_USE_DOUBLE_BE)
92995#define DUK__DOUBLE_INIT(u, a, b, c, d, e, f, g, h) \
92996 do { \
92997 (u)->x[0] = (a); \
92998 (u)->x[1] = (b); \
92999 (u)->x[2] = (c); \
93000 (u)->x[3] = (d); \
93001 (u)->x[4] = (e); \
93002 (u)->x[5] = (f); \
93003 (u)->x[6] = (g); \
93004 (u)->x[7] = (h); \
93005 } while (0)
93006#define DUK__DOUBLE_COMPARE(u, a, b, c, d, e, f, g, h) \
93007 ((u)->x[0] == (a) && (u)->x[1] == (b) && (u)->x[2] == (c) && (u)->x[3] == (d) && (u)->x[4] == (e) && (u)->x[5] == (f) && \
93008 (u)->x[6] == (g) && (u)->x[7] == (h))
93009#else
93010#error unknown double endianness
93011#endif
93012
93013/*
93014 * Various sanity checks for typing
93015 */
93016
93017DUK_LOCAL duk_uint_t duk__selftest_types(void) {
93018 duk_uint_t error_count = 0;
93019
93020 if (!(sizeof(duk_int8_t) == 1 && sizeof(duk_uint8_t) == 1 && sizeof(duk_int16_t) == 2 && sizeof(duk_uint16_t) == 2 &&
93021 sizeof(duk_int32_t) == 4 && sizeof(duk_uint32_t) == 4)) {
93022 DUK__FAILED("duk_(u)int{8,16,32}_t size");
93023 }
93024#if defined(DUK_USE_64BIT_OPS)
93025 if (!(sizeof(duk_int64_t) == 8 && sizeof(duk_uint64_t) == 8)) {
93026 DUK__FAILED("duk_(u)int64_t size");
93027 }
93028#endif
93029
93030 if (!(sizeof(duk_size_t) >= sizeof(duk_uint_t))) {
93031 /* Some internal code now assumes that all duk_uint_t values
93032 * can be expressed with a duk_size_t.
93033 */
93034 DUK__FAILED("duk_size_t is smaller than duk_uint_t");
93035 }
93036 if (!(sizeof(duk_int_t) >= 4)) {
93037 DUK__FAILED("duk_int_t is not 32 bits");
93038 }
93039
93040 return error_count;
93041}
93042
93043/*
93044 * Packed tval sanity
93045 */
93046
93047DUK_LOCAL duk_uint_t duk__selftest_packed_tval(void) {
93048 duk_uint_t error_count = 0;
93049
93050#if defined(DUK_USE_PACKED_TVAL)
93051 if (sizeof(void *) > 4) {
93052 DUK__FAILED("packed duk_tval in use but sizeof(void *) > 4");
93053 }
93054#endif
93055
93056 return error_count;
93057}
93058
93059/*
93060 * Two's complement arithmetic.
93061 */
93062
93063DUK_LOCAL duk_uint_t duk__selftest_twos_complement(void) {
93064 duk_uint_t error_count = 0;
93065 volatile int test;
93066 test = -1;
93067
93068 /* Note that byte order doesn't affect this test: all bytes in
93069 * 'test' will be 0xFF for two's complement.
93070 */
93071 if (((volatile duk_uint8_t *) &test)[0] != (duk_uint8_t) 0xff) {
93072 DUK__FAILED("two's complement arithmetic");
93073 }
93074
93075 return error_count;
93076}
93077
93078/*
93079 * Byte order. Important to self check, because on some exotic platforms
93080 * there is no actual detection but rather assumption based on platform
93081 * defines.
93082 */
93083
93084DUK_LOCAL duk_uint_t duk__selftest_byte_order(void) {
93085 duk_uint_t error_count = 0;
93086 duk__test_u32_union u1;
93087 duk__test_double_union u2;
93088
93089 /*
93090 * >>> struct.pack('>d', 102030405060).encode('hex')
93091 * '4237c17c6dc40000'
93092 */
93093
93094 DUK__U32_INIT(&u1, 0xde, 0xad, 0xbe, 0xef);
93095 DUK__DOUBLE_INIT(&u2, 0x42, 0x37, 0xc1, 0x7c, 0x6d, 0xc4, 0x00, 0x00);
93096
93097 if (u1.i != (duk_uint32_t) 0xdeadbeefUL) {
93098 DUK__FAILED("duk_uint32_t byte order");
93099 }
93100
93101 if (!duk_double_equals(u2.d, 102030405060.0)) {
93102 DUK__FAILED("double byte order");
93103 }
93104
93105 return error_count;
93106}
93107
93108/*
93109 * DUK_BSWAP macros
93110 */
93111
93112DUK_LOCAL duk_uint_t duk__selftest_bswap_macros(void) {
93113 duk_uint_t error_count = 0;
93114 volatile duk_uint32_t x32_input, x32_output;
93115 duk_uint32_t x32;
93116 volatile duk_uint16_t x16_input, x16_output;
93117 duk_uint16_t x16;
93119 duk_double_t du_diff;
93120#if defined(DUK_BSWAP64)
93121 volatile duk_uint64_t x64_input, x64_output;
93122 duk_uint64_t x64;
93123#endif
93124
93125 /* Cover both compile time and runtime bswap operations, as these
93126 * may have different bugs.
93127 */
93128
93129 x16_input = 0xbeefUL;
93130 x16 = x16_input;
93131 x16 = DUK_BSWAP16(x16);
93132 x16_output = x16;
93133 if (x16_output != (duk_uint16_t) 0xefbeUL) {
93134 DUK__FAILED("DUK_BSWAP16");
93135 }
93136
93137 x16 = 0xbeefUL;
93138 x16 = DUK_BSWAP16(x16);
93139 if (x16 != (duk_uint16_t) 0xefbeUL) {
93140 DUK__FAILED("DUK_BSWAP16");
93141 }
93142
93143 x32_input = 0xdeadbeefUL;
93144 x32 = x32_input;
93145 x32 = DUK_BSWAP32(x32);
93146 x32_output = x32;
93147 if (x32_output != (duk_uint32_t) 0xefbeaddeUL) {
93148 DUK__FAILED("DUK_BSWAP32");
93149 }
93150
93151 x32 = 0xdeadbeefUL;
93152 x32 = DUK_BSWAP32(x32);
93153 if (x32 != (duk_uint32_t) 0xefbeaddeUL) {
93154 DUK__FAILED("DUK_BSWAP32");
93155 }
93156
93157#if defined(DUK_BSWAP64)
93158 x64_input = DUK_U64_CONSTANT(0x8899aabbccddeeff);
93159 x64 = x64_input;
93160 x64 = DUK_BSWAP64(x64);
93161 x64_output = x64;
93162 if (x64_output != (duk_uint64_t) DUK_U64_CONSTANT(0xffeeddccbbaa9988)) {
93163 DUK__FAILED("DUK_BSWAP64");
93164 }
93165
93166 x64 = DUK_U64_CONSTANT(0x8899aabbccddeeff);
93167 x64 = DUK_BSWAP64(x64);
93168 if (x64 != (duk_uint64_t) DUK_U64_CONSTANT(0xffeeddccbbaa9988)) {
93169 DUK__FAILED("DUK_BSWAP64");
93170 }
93171#endif
93172
93173 /* >>> struct.unpack('>d', '4000112233445566'.decode('hex'))
93174 * (2.008366013071895,)
93175 */
93176
93177 du.uc[0] = 0x40;
93178 du.uc[1] = 0x00;
93179 du.uc[2] = 0x11;
93180 du.uc[3] = 0x22;
93181 du.uc[4] = 0x33;
93182 du.uc[5] = 0x44;
93183 du.uc[6] = 0x55;
93184 du.uc[7] = 0x66;
93186 du_diff = du.d - 2.008366013071895;
93187#if 0
93188 DUK_D(DUK_DPRINT("du_diff: %lg\n", (double) du_diff));
93189#endif
93190 if (du_diff > 1e-15) {
93191 /* Allow very small lenience because some compilers won't parse
93192 * exact IEEE double constants (happened in matrix testing with
93193 * Linux gcc-4.8 -m32 at least).
93194 */
93195#if 0
93196 DUK_D(DUK_DPRINT("Result of DUK_DBLUNION_DOUBLE_NTOH: %02x %02x %02x %02x %02x %02x %02x %02x\n",
93197 (unsigned int) du.uc[0], (unsigned int) du.uc[1],
93198 (unsigned int) du.uc[2], (unsigned int) du.uc[3],
93199 (unsigned int) du.uc[4], (unsigned int) du.uc[5],
93200 (unsigned int) du.uc[6], (unsigned int) du.uc[7]));
93201#endif
93202 DUK__FAILED("DUK_DBLUNION_DOUBLE_NTOH");
93203 }
93204
93205 return error_count;
93206}
93207
93208/*
93209 * Basic double / byte union memory layout.
93210 */
93211
93212DUK_LOCAL duk_uint_t duk__selftest_double_union_size(void) {
93213 duk_uint_t error_count = 0;
93214
93215 if (sizeof(duk__test_double_union) != 8) {
93216 DUK__FAILED("invalid union size");
93217 }
93218
93219 return error_count;
93220}
93221
93222/*
93223 * Union aliasing, see misc/clang_aliasing.c.
93224 */
93225
93226DUK_LOCAL duk_uint_t duk__selftest_double_aliasing(void) {
93227 /* This testcase fails when Emscripten-generated code runs on Firefox.
93228 * It's not an issue because the failure should only affect packed
93229 * duk_tval representation, which is not used with Emscripten.
93230 */
93231#if defined(DUK_USE_PACKED_TVAL)
93232 duk_uint_t error_count = 0;
93233 duk__test_double_union a, b;
93234
93235 /* Test signaling NaN and alias assignment in all endianness combinations.
93236 */
93237
93238 /* little endian */
93239 a.x[0] = 0x11;
93240 a.x[1] = 0x22;
93241 a.x[2] = 0x33;
93242 a.x[3] = 0x44;
93243 a.x[4] = 0x00;
93244 a.x[5] = 0x00;
93245 a.x[6] = 0xf1;
93246 a.x[7] = 0xff;
93247 b = a;
93248 DUK__DBLUNION_CMP_TRUE(&a, &b);
93249
93250 /* big endian */
93251 a.x[0] = 0xff;
93252 a.x[1] = 0xf1;
93253 a.x[2] = 0x00;
93254 a.x[3] = 0x00;
93255 a.x[4] = 0x44;
93256 a.x[5] = 0x33;
93257 a.x[6] = 0x22;
93258 a.x[7] = 0x11;
93259 b = a;
93260 DUK__DBLUNION_CMP_TRUE(&a, &b);
93261
93262 /* mixed endian */
93263 a.x[0] = 0x00;
93264 a.x[1] = 0x00;
93265 a.x[2] = 0xf1;
93266 a.x[3] = 0xff;
93267 a.x[4] = 0x11;
93268 a.x[5] = 0x22;
93269 a.x[6] = 0x33;
93270 a.x[7] = 0x44;
93271 b = a;
93272 DUK__DBLUNION_CMP_TRUE(&a, &b);
93273
93274 return error_count;
93275#else
93276 DUK_D(DUK_DPRINT("skip double aliasing self test when duk_tval is not packed"));
93277 return 0;
93278#endif
93279}
93280
93281/*
93282 * Zero sign, see misc/tcc_zerosign2.c.
93283 */
93284
93285DUK_LOCAL duk_uint_t duk__selftest_double_zero_sign(void) {
93286 duk_uint_t error_count = 0;
93287 duk__test_double_union a, b;
93288
93289 a.d = 0.0;
93290 b.d = -a.d;
93291 DUK__DBLUNION_CMP_FALSE(&a, &b);
93292
93293 return error_count;
93294}
93295
93296/*
93297 * Rounding mode: Duktape assumes round-to-nearest, check that this is true.
93298 * If we had C99 fenv.h we could check that fegetround() == FE_TONEAREST,
93299 * but we don't want to rely on that header; and even if we did, it's good
93300 * to ensure the rounding actually works.
93301 */
93302
93303DUK_LOCAL duk_uint_t duk__selftest_double_rounding(void) {
93304 duk_uint_t error_count = 0;
93305 duk__test_double_union a, b, c;
93306
93307#if 0
93308 /* Include <fenv.h> and test manually; these trigger failures: */
93309 fesetround(FE_UPWARD);
93310 fesetround(FE_DOWNWARD);
93311 fesetround(FE_TOWARDZERO);
93312
93313 /* This is the default and passes. */
93314 fesetround(FE_TONEAREST);
93315#endif
93316
93317 /* Rounding tests check that none of the other modes (round to
93318 * +Inf, round to -Inf, round to zero) can be active:
93319 * http://www.gnu.org/software/libc/manual/html_node/Rounding.html
93320 */
93321
93322 /* 1.0 + 2^(-53): result is midway between 1.0 and 1.0 + ulp.
93323 * Round to nearest: 1.0
93324 * Round to +Inf: 1.0 + ulp
93325 * Round to -Inf: 1.0
93326 * Round to zero: 1.0
93327 * => Correct result eliminates round to +Inf.
93328 */
93329 DUK__DOUBLE_INIT(&a, 0xf0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00);
93330 DUK__DOUBLE_INIT(&b, 0x3c, 0xa0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00);
93331 duk_memset((void *) &c, 0, sizeof(c));
93332 c.d = a.d + b.d;
93333 if (!DUK__DOUBLE_COMPARE(&c, 0xf0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00)) {
93334 DUK_D(DUK_DPRINT("broken result (native endiannesss): %02x %02x %02x %02x %02x %02x %02x %02x",
93335 (unsigned int) c.x[0],
93336 (unsigned int) c.x[1],
93337 (unsigned int) c.x[2],
93338 (unsigned int) c.x[3],
93339 (unsigned int) c.x[4],
93340 (unsigned int) c.x[5],
93341 (unsigned int) c.x[6],
93342 (unsigned int) c.x[7]));
93343 DUK__FAILED("invalid result from 1.0 + 0.5ulp");
93344 }
93345
93346 /* (1.0 + ulp) + 2^(-53): result is midway between 1.0 + ulp and 1.0 + 2*ulp.
93347 * Round to nearest: 1.0 + 2*ulp (round to even mantissa)
93348 * Round to +Inf: 1.0 + 2*ulp
93349 * Round to -Inf: 1.0 + ulp
93350 * Round to zero: 1.0 + ulp
93351 * => Correct result eliminates round to -Inf and round to zero.
93352 */
93353 DUK__DOUBLE_INIT(&a, 0x3f, 0xf0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01);
93354 DUK__DOUBLE_INIT(&b, 0x3c, 0xa0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00);
93355 duk_memset((void *) &c, 0, sizeof(c));
93356 c.d = a.d + b.d;
93357 if (!DUK__DOUBLE_COMPARE(&c, 0x3f, 0xf0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02)) {
93358 DUK_D(DUK_DPRINT("broken result (native endiannesss): %02x %02x %02x %02x %02x %02x %02x %02x",
93359 (unsigned int) c.x[0],
93360 (unsigned int) c.x[1],
93361 (unsigned int) c.x[2],
93362 (unsigned int) c.x[3],
93363 (unsigned int) c.x[4],
93364 (unsigned int) c.x[5],
93365 (unsigned int) c.x[6],
93366 (unsigned int) c.x[7]));
93367 DUK__FAILED("invalid result from (1.0 + ulp) + 0.5ulp");
93368 }
93369
93370 /* Could do negative number testing too, but the tests above should
93371 * differentiate between IEEE 754 rounding modes.
93372 */
93373 return error_count;
93374}
93375
93376/*
93377 * fmod(): often a portability issue in embedded or bare platform targets.
93378 * Check for at least minimally correct behavior. Unlike some other math
93379 * functions (like cos()) Duktape relies on fmod() internally too.
93380 */
93381
93382DUK_LOCAL duk_uint_t duk__selftest_fmod(void) {
93383 duk_uint_t error_count = 0;
93384 duk__test_double_union u1, u2;
93385 volatile duk_double_t t1, t2, t3;
93386
93387 /* fmod() with integer argument and exponent 2^32 is used by e.g.
93388 * ToUint32() and some Duktape internals.
93389 */
93390 u1.d = DUK_FMOD(10.0, 4294967296.0);
93391 u2.d = 10.0;
93392 DUK__DBLUNION_CMP_TRUE(&u1, &u2);
93393
93394 u1.d = DUK_FMOD(4294967306.0, 4294967296.0);
93395 u2.d = 10.0;
93396 DUK__DBLUNION_CMP_TRUE(&u1, &u2);
93397
93398 u1.d = DUK_FMOD(73014444042.0, 4294967296.0);
93399 u2.d = 10.0;
93400 DUK__DBLUNION_CMP_TRUE(&u1, &u2);
93401
93402 /* 52-bit integer split into two parts:
93403 * >>> 0x1fedcba9876543
93404 * 8987183256397123
93405 * >>> float(0x1fedcba9876543) / float(2**53)
93406 * 0.9977777777777778
93407 */
93408 u1.d = DUK_FMOD(8987183256397123.0, 4294967296.0);
93409 u2.d = (duk_double_t) 0xa9876543UL;
93410 DUK__DBLUNION_CMP_TRUE(&u1, &u2);
93411 t1 = 8987183256397123.0;
93412 t2 = 4294967296.0;
93413 t3 = t1 / t2;
93414 u1.d = DUK_FLOOR(t3);
93415 u2.d = (duk_double_t) 0x1fedcbUL;
93416 DUK__DBLUNION_CMP_TRUE(&u1, &u2);
93417
93418 /* C99 behavior is for fmod() result sign to mathc argument sign. */
93419 u1.d = DUK_FMOD(-10.0, 4294967296.0);
93420 u2.d = -10.0;
93421 DUK__DBLUNION_CMP_TRUE(&u1, &u2);
93422
93423 u1.d = DUK_FMOD(-4294967306.0, 4294967296.0);
93424 u2.d = -10.0;
93425 DUK__DBLUNION_CMP_TRUE(&u1, &u2);
93426
93427 u1.d = DUK_FMOD(-73014444042.0, 4294967296.0);
93428 u2.d = -10.0;
93429 DUK__DBLUNION_CMP_TRUE(&u1, &u2);
93430
93431 return error_count;
93432}
93433
93434/*
93435 * Struct size/alignment if platform requires it
93436 *
93437 * There are some compiler specific struct padding pragmas etc in use, this
93438 * selftest ensures they're correctly detected and used.
93439 */
93440
93441DUK_LOCAL duk_uint_t duk__selftest_struct_align(void) {
93442 duk_uint_t error_count = 0;
93443
93444#if (DUK_USE_ALIGN_BY == 4)
93445 if ((sizeof(duk_hbuffer_fixed) % 4) != 0) {
93446 DUK__FAILED("sizeof(duk_hbuffer_fixed) not aligned to 4");
93447 }
93448#elif (DUK_USE_ALIGN_BY == 8)
93449 if ((sizeof(duk_hbuffer_fixed) % 8) != 0) {
93450 DUK__FAILED("sizeof(duk_hbuffer_fixed) not aligned to 8");
93451 }
93452#elif (DUK_USE_ALIGN_BY == 1)
93453 /* no check */
93454#else
93455#error invalid DUK_USE_ALIGN_BY
93456#endif
93457 return error_count;
93458}
93459
93460/*
93461 * 64-bit arithmetic
93462 *
93463 * There are some platforms/compilers where 64-bit types are available
93464 * but don't work correctly. Test for known cases.
93465 */
93466
93467DUK_LOCAL duk_uint_t duk__selftest_64bit_arithmetic(void) {
93468 duk_uint_t error_count = 0;
93469#if defined(DUK_USE_64BIT_OPS)
93470 volatile duk_int64_t i;
93471 volatile duk_double_t d;
93472
93473 /* Catch a double-to-int64 cast issue encountered in practice. */
93474 d = 2147483648.0;
93475 i = (duk_int64_t) d;
93476 if (i != DUK_I64_CONSTANT(0x80000000)) {
93477 DUK__FAILED("casting 2147483648.0 to duk_int64_t failed");
93478 }
93479#else
93480 /* nop */
93481#endif
93482 return error_count;
93483}
93484
93485/*
93486 * Casting
93487 */
93488
93489DUK_LOCAL duk_uint_t duk__selftest_cast_double_to_small_uint(void) {
93490 /*
93491 * https://github.com/svaarala/duktape/issues/127#issuecomment-77863473
93492 */
93493
93494 duk_uint_t error_count = 0;
93495
93496 duk_double_t d1, d2;
93498
93499 duk_double_t d1v, d2v;
93501
93502 /* Test without volatiles */
93503
93504 d1 = 1.0;
93505 u = (duk_small_uint_t) d1;
93506 d2 = (duk_double_t) u;
93507
93508 if (!(duk_double_equals(d1, 1.0) && u == 1 && duk_double_equals(d2, 1.0) && duk_double_equals(d1, d2))) {
93509 DUK__FAILED("double to duk_small_uint_t cast failed");
93510 }
93511
93512 /* Same test with volatiles */
93513
93514 d1v = 1.0;
93515 uv = (duk_small_uint_t) d1v;
93516 d2v = (duk_double_t) uv;
93517
93518 if (!(duk_double_equals(d1v, 1.0) && uv == 1 && duk_double_equals(d2v, 1.0) && duk_double_equals(d1v, d2v))) {
93519 DUK__FAILED("double to duk_small_uint_t cast failed");
93520 }
93521
93522 return error_count;
93523}
93524
93525DUK_LOCAL duk_uint_t duk__selftest_cast_double_to_uint32(void) {
93526 /*
93527 * This test fails on an exotic ARM target; double-to-uint
93528 * cast is incorrectly clamped to -signed- int highest value.
93529 *
93530 * https://github.com/svaarala/duktape/issues/336
93531 */
93532
93533 duk_uint_t error_count = 0;
93534 duk_double_t dv;
93535 duk_uint32_t uv;
93536
93537 dv = 3735928559.0; /* 0xdeadbeef in decimal */
93538 uv = (duk_uint32_t) dv;
93539
93540 if (uv != 0xdeadbeefUL) {
93541 DUK__FAILED("double to duk_uint32_t cast failed");
93542 }
93543
93544 return error_count;
93545}
93546
93547/*
93548 * Minimal test of user supplied allocation functions
93549 *
93550 * - Basic alloc + realloc + free cycle
93551 *
93552 * - Realloc to significantly larger size to (hopefully) trigger a
93553 * relocation and check that relocation copying works
93554 */
93555
93556DUK_LOCAL duk_uint_t duk__selftest_alloc_funcs(duk_alloc_function alloc_func,
93557 duk_realloc_function realloc_func,
93558 duk_free_function free_func,
93559 void *udata) {
93560 duk_uint_t error_count = 0;
93561 void *ptr;
93562 void *new_ptr;
93563 duk_small_int_t i, j;
93564 unsigned char x;
93565
93566 if (alloc_func == NULL || realloc_func == NULL || free_func == NULL) {
93567 return 0;
93568 }
93569
93570 for (i = 1; i <= 256; i++) {
93571 ptr = alloc_func(udata, (duk_size_t) i);
93572 if (ptr == NULL) {
93573 DUK_D(DUK_DPRINT("alloc failed, ignore"));
93574 continue; /* alloc failed, ignore */
93575 }
93576 for (j = 0; j < i; j++) {
93577 ((unsigned char *) ptr)[j] = (unsigned char) (0x80 + j);
93578 }
93579 new_ptr = realloc_func(udata, ptr, 1024);
93580 if (new_ptr == NULL) {
93581 DUK_D(DUK_DPRINT("realloc failed, ignore"));
93582 free_func(udata, ptr);
93583 continue; /* realloc failed, ignore */
93584 }
93585 ptr = new_ptr;
93586 for (j = 0; j < i; j++) {
93587 x = ((unsigned char *) ptr)[j];
93588 if (x != (unsigned char) (0x80 + j)) {
93589 DUK_D(DUK_DPRINT("byte at index %ld doesn't match after realloc: %02lx",
93590 (long) j,
93591 (unsigned long) x));
93592 DUK__FAILED("byte compare after realloc");
93593 break;
93594 }
93595 }
93596 free_func(udata, ptr);
93597 }
93598
93599 return error_count;
93600}
93601
93602/*
93603 * Self test main
93604 */
93605
93606DUK_INTERNAL duk_uint_t duk_selftest_run_tests(duk_alloc_function alloc_func,
93607 duk_realloc_function realloc_func,
93608 duk_free_function free_func,
93609 void *udata) {
93610 duk_uint_t error_count = 0;
93611
93612 DUK_D(DUK_DPRINT("self test starting"));
93613
93614 error_count += duk__selftest_types();
93615 error_count += duk__selftest_packed_tval();
93616 error_count += duk__selftest_twos_complement();
93617 error_count += duk__selftest_byte_order();
93618 error_count += duk__selftest_bswap_macros();
93619 error_count += duk__selftest_double_union_size();
93620 error_count += duk__selftest_double_aliasing();
93621 error_count += duk__selftest_double_zero_sign();
93622 error_count += duk__selftest_double_rounding();
93623 error_count += duk__selftest_fmod();
93624 error_count += duk__selftest_struct_align();
93625 error_count += duk__selftest_64bit_arithmetic();
93626 error_count += duk__selftest_cast_double_to_small_uint();
93627 error_count += duk__selftest_cast_double_to_uint32();
93628 error_count += duk__selftest_alloc_funcs(alloc_func, realloc_func, free_func, udata);
93629
93630 DUK_D(DUK_DPRINT("self test complete, total error count: %ld", (long) error_count));
93631
93632 return error_count;
93633}
93634
93635#endif /* DUK_USE_SELF_TESTS */
93636
93637/* automatic undefs */
93638#undef DUK__DBLUNION_CMP_FALSE
93639#undef DUK__DBLUNION_CMP_TRUE
93640#undef DUK__DOUBLE_COMPARE
93641#undef DUK__DOUBLE_INIT
93642#undef DUK__FAILED
93643#undef DUK__U32_INIT
93644/* #include duk_internal.h -> already included */
93645
93646#if defined(DUK_USE_FASTINT)
93647
93648/*
93649 * Manually optimized double-to-fastint downgrade check.
93650 *
93651 * This check has a large impact on performance, especially for fastint
93652 * slow paths, so must be changed carefully. The code should probably be
93653 * optimized for the case where the result does not fit into a fastint,
93654 * to minimize the penalty for "slow path code" dealing with fractions etc.
93655 *
93656 * At least on one tested soft float ARM platform double-to-int64 coercion
93657 * is very slow (and sometimes produces incorrect results, see self tests).
93658 * This algorithm combines a fastint compatibility check and extracting the
93659 * integer value from an IEEE double for setting the tagged fastint. For
93660 * other platforms a more naive approach might be better.
93661 *
93662 * See doc/fastint.rst for details.
93663 */
93664
93667 duk_int64_t i;
93668 duk_small_int_t expt;
93670
93671 /* XXX: optimize for packed duk_tval directly? */
93672
93673 du.d = x;
93674 i = (duk_int64_t) DUK_DBLUNION_GET_INT64(&du);
93675 expt = (duk_small_int_t) ((i >> 52) & 0x07ff);
93676 shift = expt - 1023;
93677
93678 if (shift >= 0 && shift <= 46) { /* exponents 1023 to 1069 */
93679 duk_int64_t t;
93680
93681 if (((DUK_I64_CONSTANT(0x000fffffffffffff) >> shift) & i) == 0) {
93682 t = i | DUK_I64_CONSTANT(0x0010000000000000); /* implicit leading one */
93683 t = t & DUK_I64_CONSTANT(0x001fffffffffffff);
93684 t = t >> (52 - shift);
93685 if (i < 0) {
93686 t = -t;
93687 }
93688 DUK_TVAL_SET_FASTINT(tv, t);
93689 return;
93690 }
93691 } else if (shift == -1023) { /* exponent 0 */
93692 if (i >= 0 && (i & DUK_I64_CONSTANT(0x000fffffffffffff)) == 0) {
93693 /* Note: reject negative zero. */
93694 DUK_TVAL_SET_FASTINT(tv, (duk_int64_t) 0);
93695 return;
93696 }
93697 } else if (shift == 47) { /* exponent 1070 */
93698 if (i < 0 && (i & DUK_I64_CONSTANT(0x000fffffffffffff)) == 0) {
93699 DUK_TVAL_SET_FASTINT(tv, (duk_int64_t) DUK_FASTINT_MIN);
93700 return;
93701 }
93702 }
93703
93704 DUK_TVAL_SET_DOUBLE(tv, x);
93705 return;
93706}
93707
93710}
93711
93712/*
93713 * Manually optimized number-to-double conversion
93714 */
93715
93716#if defined(DUK_USE_FASTINT) && defined(DUK_USE_PACKED_TVAL)
93717DUK_INTERNAL DUK_ALWAYS_INLINE duk_double_t duk_tval_get_number_packed(duk_tval *tv) {
93719 duk_uint64_t t;
93720
93721 t = (duk_uint64_t) DUK_DBLUNION_GET_UINT64(tv);
93722 if ((t >> 48) != DUK_TAG_FASTINT) {
93723 return tv->d;
93724 } else if (t & DUK_U64_CONSTANT(0x0000800000000000)) {
93725 t = (duk_uint64_t) (-((duk_int64_t) t)); /* avoid unary minus on unsigned */
93726 t = t & DUK_U64_CONSTANT(0x0000ffffffffffff); /* negative */
93727 t |= DUK_U64_CONSTANT(0xc330000000000000);
93728 DUK_DBLUNION_SET_UINT64(&du, t);
93729 return du.d + 4503599627370496.0; /* 1 << 52 */
93730 } else if (t != 0) {
93731 t &= DUK_U64_CONSTANT(0x0000ffffffffffff); /* positive */
93732 t |= DUK_U64_CONSTANT(0x4330000000000000);
93733 DUK_DBLUNION_SET_UINT64(&du, t);
93734 return du.d - 4503599627370496.0; /* 1 << 52 */
93735 } else {
93736 return 0.0; /* zero */
93737 }
93738}
93739#endif /* DUK_USE_FASTINT && DUK_USE_PACKED_TVAL */
93740
93741#if 0 /* unused */
93742#if defined(DUK_USE_FASTINT) && !defined(DUK_USE_PACKED_TVAL)
93743DUK_INTERNAL DUK_ALWAYS_INLINE duk_double_t duk_tval_get_number_unpacked(duk_tval *tv) {
93745 duk_uint64_t t;
93746
93747 DUK_ASSERT(tv->t == DUK_TAG_NUMBER || tv->t == DUK_TAG_FASTINT);
93748
93749 if (tv->t == DUK_TAG_FASTINT) {
93750 if (tv->v.fi >= 0) {
93751 t = DUK_U64_CONSTANT(0x4330000000000000) | (duk_uint64_t) tv->v.fi;
93752 DUK_DBLUNION_SET_UINT64(&du, t);
93753 return du.d - 4503599627370496.0; /* 1 << 52 */
93754 } else {
93755 t = DUK_U64_CONSTANT(0xc330000000000000) | (duk_uint64_t) (-tv->v.fi);
93756 DUK_DBLUNION_SET_UINT64(&du, t);
93757 return du.d + 4503599627370496.0; /* 1 << 52 */
93758 }
93759 } else {
93760 return tv->v.d;
93761 }
93762}
93763#endif /* DUK_USE_FASTINT && DUK_USE_PACKED_TVAL */
93764#endif /* 0 */
93765
93766#if defined(DUK_USE_FASTINT) && !defined(DUK_USE_PACKED_TVAL)
93769 duk_uint64_t t;
93770
93772
93773 if (tv->v.fi >= 0) {
93774 t = DUK_U64_CONSTANT(0x4330000000000000) | (duk_uint64_t) tv->v.fi;
93775 DUK_DBLUNION_SET_UINT64(&du, t);
93776 return du.d - 4503599627370496.0; /* 1 << 52 */
93777 } else {
93778 t = DUK_U64_CONSTANT(0xc330000000000000) | (duk_uint64_t) (-tv->v.fi);
93779 DUK_DBLUNION_SET_UINT64(&du, t);
93780 return du.d + 4503599627370496.0; /* 1 << 52 */
93781 }
93783#endif /* DUK_USE_FASTINT && DUK_USE_PACKED_TVAL */
93784
93785#endif /* DUK_USE_FASTINT */
93786
93787/*
93788 * Assertion helpers.
93789 */
93790
93791#if defined(DUK_USE_ASSERTIONS)
93792DUK_INTERNAL void duk_tval_assert_valid(duk_tval *tv) {
93793 DUK_ASSERT(tv != NULL);
93794}
93795#endif
93796/*
93797 * Unicode support tables automatically generated during build.
93798 */
93799
93800/* #include duk_internal.h -> already included */
93801
93802/*
93803 * Unicode tables containing ranges of Unicode characters in a
93804 * packed format. These tables are used to match non-ASCII
93805 * characters of complex productions by resorting to a linear
93806 * range-by-range comparison. This is very slow, but is expected
93807 * to be very rare in practical ECMAScript source code, and thus
93808 * compactness is most important.
93809 *
93810 * The tables are matched using uni_range_match() and the format
93811 * is described in tools/extract_chars.py.
93812 */
93813
93814#if defined(DUK_USE_SOURCE_NONBMP)
93815/* IdentifierStart production with ASCII excluded */
93816/* duk_unicode_ids_noa[] */
93817/*
93818 * Automatically generated by extract_chars.py, do not edit!
93819 */
93820
93821const duk_uint8_t duk_unicode_ids_noa[1116] = {
93822249,176,176,80,111,7,47,15,47,254,11,197,191,0,72,2,15,115,66,19,50,7,2,34,
938232,240,66,244,50,247,185,249,98,241,99,7,241,159,57,240,181,63,31,241,191,
9382421,18,245,50,15,1,24,27,35,15,2,2,240,239,15,244,156,15,10,241,26,21,6,240,
93825101,10,4,15,9,240,152,175,39,240,82,127,56,242,100,15,4,8,159,1,240,5,115,
9382619,240,98,98,4,52,15,2,14,18,47,0,27,9,85,19,240,98,98,18,18,31,17,50,15,5,
9382747,2,130,34,240,98,98,18,68,15,4,15,1,31,9,12,115,19,240,98,98,18,68,15,16,
9382818,47,1,15,3,2,84,34,52,18,2,20,20,36,191,8,15,38,114,34,240,114,240,4,15,
9382912,38,31,16,5,114,34,240,114,146,68,15,18,2,31,1,31,4,114,34,241,147,15,2,
938306,41,47,10,86,240,36,240,130,130,3,111,44,242,2,29,111,44,18,2,66,240,130,
938312,146,26,3,66,15,7,63,18,15,49,114,241,79,13,79,101,241,191,6,15,2,85,52,4,
9383224,37,205,15,3,241,98,6,3,241,178,255,224,63,35,54,32,35,63,25,35,63,17,35,
9383354,32,35,62,47,41,35,63,51,241,127,0,240,47,70,53,79,254,21,227,240,18,240,
93834166,243,180,168,194,63,0,240,47,0,240,47,0,194,47,1,242,79,21,5,15,53,244,
93835152,67,241,34,6,243,107,240,255,35,240,227,76,241,197,240,175,40,240,122,
93836242,95,68,15,79,241,255,3,111,41,240,238,27,241,207,12,241,79,27,43,241,67,
93837136,241,179,47,27,50,82,20,6,251,15,50,255,224,8,53,63,22,53,55,32,32,32,
9383847,15,63,37,38,32,66,38,67,53,92,98,38,246,96,224,240,44,245,112,80,57,32,
9383968,112,32,32,35,42,51,100,80,240,63,25,255,233,107,241,242,241,242,247,87,
9384052,29,241,98,6,3,242,136,15,2,240,122,98,98,98,98,98,98,98,111,66,15,254,
9384112,146,240,184,132,52,95,70,114,47,74,35,111,27,47,78,240,63,11,242,127,0,
93842255,224,244,255,240,0,138,143,60,255,240,4,14,47,2,255,227,127,243,95,30,
9384363,253,79,0,177,240,111,31,240,47,15,63,64,241,152,63,87,63,37,52,242,42,
9384434,35,47,7,240,255,36,240,15,34,243,5,64,33,207,12,191,7,240,191,13,143,31,
93845240,224,240,36,41,180,47,25,240,146,39,240,111,7,64,79,34,32,65,52,48,32,
93846240,162,58,130,213,53,53,166,38,47,27,43,159,99,240,255,255,0,26,150,223,7,
9384795,33,255,240,0,255,143,254,6,3,245,175,24,109,70,2,146,194,66,2,18,18,245,
93848207,19,255,224,93,240,79,48,63,38,241,171,246,100,47,119,241,111,10,127,10,
93849207,73,69,53,53,50,241,91,47,10,47,3,33,46,61,241,79,107,243,127,37,255,
93850223,13,79,33,242,31,16,239,14,111,22,191,14,63,20,87,36,241,207,142,240,79,
9385120,95,20,95,24,159,36,248,239,254,2,154,240,107,127,138,83,2,241,194,20,3,
93852240,123,240,122,240,255,51,240,50,27,240,107,240,175,56,242,135,31,50,15,1,
9385350,34,240,223,28,240,212,240,223,21,114,240,207,13,242,107,240,107,240,62,
93854240,47,96,243,159,41,242,62,242,62,241,79,254,13,15,13,176,159,6,248,207,7,
93855223,37,243,223,29,241,47,9,240,207,20,240,240,207,19,64,223,32,240,3,240,
93856112,32,241,95,2,47,9,244,102,32,35,46,41,143,31,241,135,49,63,6,38,33,36,
9385764,240,64,212,249,15,37,240,67,240,96,241,47,32,240,97,32,250,175,31,241,
93858179,241,111,32,240,96,242,223,27,224,243,159,11,253,127,28,246,111,48,241,
9385916,249,39,63,23,240,32,32,240,224,191,24,128,240,112,207,30,240,80,241,79,
9386041,255,152,47,21,240,48,242,63,14,246,38,33,47,22,240,112,240,181,33,47,16,
93861240,0,255,224,59,240,63,254,0,31,254,40,207,88,245,255,3,251,79,254,155,15,
93862254,50,31,254,236,95,254,19,159,255,0,16,173,255,225,43,143,15,246,63,14,
93863240,79,32,240,35,241,31,5,111,3,255,225,164,243,15,114,243,182,15,52,207,
9386450,18,15,14,255,240,0,110,169,255,225,229,255,240,1,64,31,254,1,31,35,47,3,
9386557,255,224,126,255,231,248,245,182,196,136,159,255,0,6,90,244,82,243,114,
9386619,3,19,50,178,2,98,243,18,51,114,98,240,194,50,66,4,98,255,224,70,63,9,47,
938679,47,15,47,9,47,15,47,9,47,15,47,9,47,15,47,9,39,255,232,40,241,219,111,2,
9386815,254,6,95,28,255,228,8,251,95,45,243,72,15,254,58,131,47,11,33,32,48,41,
9386935,32,32,112,80,32,32,34,33,32,48,32,32,32,32,33,32,51,38,35,35,32,41,47,1,
9387098,36,47,1,255,240,0,3,143,255,0,149,201,241,191,254,242,124,252,227,255,
93871240,0,87,79,0,255,240,0,194,63,254,177,63,254,17,0,
93872};
93873#else
93874/* IdentifierStart production with ASCII and non-BMP excluded */
93875/* duk_unicode_ids_noabmp[] */
93876/*
93877 * Automatically generated by extract_chars.py, do not edit!
93878 */
93879
93880const duk_uint8_t duk_unicode_ids_noabmp[625] = {
93881249,176,176,80,111,7,47,15,47,254,11,197,191,0,72,2,15,115,66,19,50,7,2,34,
938822,240,66,244,50,247,185,249,98,241,99,7,241,159,57,240,181,63,31,241,191,
9388321,18,245,50,15,1,24,27,35,15,2,2,240,239,15,244,156,15,10,241,26,21,6,240,
93884101,10,4,15,9,240,152,175,39,240,82,127,56,242,100,15,4,8,159,1,240,5,115,
9388519,240,98,98,4,52,15,2,14,18,47,0,27,9,85,19,240,98,98,18,18,31,17,50,15,5,
9388647,2,130,34,240,98,98,18,68,15,4,15,1,31,9,12,115,19,240,98,98,18,68,15,16,
9388718,47,1,15,3,2,84,34,52,18,2,20,20,36,191,8,15,38,114,34,240,114,240,4,15,
9388812,38,31,16,5,114,34,240,114,146,68,15,18,2,31,1,31,4,114,34,241,147,15,2,
938896,41,47,10,86,240,36,240,130,130,3,111,44,242,2,29,111,44,18,2,66,240,130,
938902,146,26,3,66,15,7,63,18,15,49,114,241,79,13,79,101,241,191,6,15,2,85,52,4,
9389124,37,205,15,3,241,98,6,3,241,178,255,224,63,35,54,32,35,63,25,35,63,17,35,
9389254,32,35,62,47,41,35,63,51,241,127,0,240,47,70,53,79,254,21,227,240,18,240,
93893166,243,180,168,194,63,0,240,47,0,240,47,0,194,47,1,242,79,21,5,15,53,244,
93894152,67,241,34,6,243,107,240,255,35,240,227,76,241,197,240,175,40,240,122,
93895242,95,68,15,79,241,255,3,111,41,240,238,27,241,207,12,241,79,27,43,241,67,
93896136,241,179,47,27,50,82,20,6,251,15,50,255,224,8,53,63,22,53,55,32,32,32,
9389747,15,63,37,38,32,66,38,67,53,92,98,38,246,96,224,240,44,245,112,80,57,32,
9389868,112,32,32,35,42,51,100,80,240,63,25,255,233,107,241,242,241,242,247,87,
9389952,29,241,98,6,3,242,136,15,2,240,122,98,98,98,98,98,98,98,111,66,15,254,
9390012,146,240,184,132,52,95,70,114,47,74,35,111,27,47,78,240,63,11,242,127,0,
93901255,224,244,255,240,0,138,143,60,255,240,4,14,47,2,255,227,127,243,95,30,
9390263,253,79,0,177,240,111,31,240,47,15,63,64,241,152,63,87,63,37,52,242,42,
9390334,35,47,7,240,255,36,240,15,34,243,5,64,33,207,12,191,7,240,191,13,143,31,
93904240,224,240,36,41,180,47,25,240,146,39,240,111,7,64,79,34,32,65,52,48,32,
93905240,162,58,130,213,53,53,166,38,47,27,43,159,99,240,255,255,0,26,150,223,7,
9390695,33,255,240,0,255,143,254,6,3,245,175,24,109,70,2,146,194,66,2,18,18,245,
93907207,19,255,224,93,240,79,48,63,38,241,171,246,100,47,119,241,111,10,127,10,
93908207,73,69,53,53,50,0,
93909};
93910#endif
93911
93912#if defined(DUK_USE_SOURCE_NONBMP)
93913/* IdentifierStart production with Letter and ASCII excluded */
93914/* duk_unicode_ids_m_let_noa[] */
93915/*
93916 * Automatically generated by extract_chars.py, do not edit!
93917 */
93918
93919const duk_uint8_t duk_unicode_ids_m_let_noa[42] = {
93920255,240,0,94,18,255,233,99,241,51,63,254,215,32,240,184,240,2,255,240,6,89,
93921249,255,240,4,148,79,37,255,224,192,9,15,120,79,255,0,15,30,245,240,
93922};
93923#else
93924/* IdentifierStart production with Letter, ASCII, and non-BMP excluded */
93925/* duk_unicode_ids_m_let_noabmp[] */
93926/*
93927 * Automatically generated by extract_chars.py, do not edit!
93928 */
93929
93930const duk_uint8_t duk_unicode_ids_m_let_noabmp[24] = {
93931255,240,0,94,18,255,233,99,241,51,63,254,215,32,240,184,240,2,255,240,6,89,
93932249,0,
93933};
93934#endif
93935
93936#if defined(DUK_USE_SOURCE_NONBMP)
93937/* IdentifierPart production with IdentifierStart and ASCII excluded */
93938/* duk_unicode_idp_m_ids_noa[] */
93939/*
93940 * Automatically generated by extract_chars.py, do not edit!
93941 */
93942
93943const duk_uint8_t duk_unicode_idp_m_ids_noa[576] = {
93944255,225,243,246,15,254,0,116,255,191,29,32,33,33,32,243,170,242,47,15,112,
93945245,118,53,49,35,57,240,144,241,15,11,244,218,240,25,241,56,160,240,163,40,
9394634,36,241,210,246,158,47,17,242,130,47,2,38,177,57,240,50,242,160,38,49,50,
93947160,177,57,240,0,50,242,160,36,81,50,64,240,107,64,194,242,160,39,34,34,
93948240,97,57,181,34,242,160,38,49,50,145,177,57,240,64,242,212,66,35,160,240,
939499,240,36,242,182,34,35,129,193,57,240,50,242,160,38,34,35,129,193,57,240,
9395035,242,145,38,34,35,160,177,57,240,65,243,128,85,32,39,121,49,242,240,54,
93951215,41,244,144,56,197,57,243,1,121,192,32,32,81,242,63,4,33,106,47,20,160,
93952245,111,4,41,211,82,34,54,67,235,46,255,225,179,47,254,42,98,240,242,240,
93953241,241,1,243,47,16,160,57,241,50,57,245,209,241,64,246,139,91,185,247,41,
93954242,244,242,185,47,13,58,121,240,141,243,68,242,31,1,201,240,56,210,241,12,
9395557,241,237,242,47,4,153,121,246,130,47,5,80,112,50,251,143,42,36,255,225,0,
9395631,35,31,5,15,109,197,4,191,254,175,34,247,240,245,47,16,255,225,30,95,91,
9395731,255,0,100,121,159,55,5,159,18,31,66,31,254,0,64,64,80,240,148,244,161,
93958242,79,2,185,127,2,234,240,231,240,188,241,227,242,29,240,25,192,185,242,
9395929,208,145,57,241,50,242,64,34,49,97,32,241,180,97,253,231,33,57,255,240,3,
93960225,128,255,225,213,240,15,2,240,4,31,10,47,178,159,23,15,254,27,16,253,64,
93961248,116,255,224,25,159,254,68,178,33,99,241,162,80,249,113,255,225,49,57,
93962159,254,16,10,250,18,242,126,241,25,240,19,241,250,242,121,114,241,109,41,
9396397,241,224,210,242,45,147,73,244,75,112,249,43,105,115,242,145,38,49,50,
93964160,177,54,68,251,47,2,169,80,244,63,4,217,252,118,56,240,209,244,79,1,240,
9396525,244,60,153,244,94,89,254,78,249,121,253,150,54,64,240,233,241,166,35,
93966144,170,242,15,0,255,224,137,114,127,2,159,42,240,98,223,108,84,2,18,98,9,
93967159,34,66,18,73,159,254,3,211,255,240,3,165,217,247,132,242,214,240,185,
93968255,226,233,2,242,120,63,255,0,59,254,31,255,0,3,186,68,89,115,111,16,63,
93969134,47,254,71,223,34,255,224,244,242,117,242,41,15,0,15,8,66,239,254,68,70,
9397047,1,54,33,36,255,118,169,255,224,150,223,254,76,166,245,246,105,255,240,
93971192,105,175,224,0,
93972};
93973#else
93974/* IdentifierPart production with IdentifierStart, ASCII, and non-BMP excluded */
93975/* duk_unicode_idp_m_ids_noabmp[] */
93976/*
93977 * Automatically generated by extract_chars.py, do not edit!
93978 */
93979
93980const duk_uint8_t duk_unicode_idp_m_ids_noabmp[358] = {
93981255,225,243,246,15,254,0,116,255,191,29,32,33,33,32,243,170,242,47,15,112,
93982245,118,53,49,35,57,240,144,241,15,11,244,218,240,25,241,56,160,240,163,40,
9398334,36,241,210,246,158,47,17,242,130,47,2,38,177,57,240,50,242,160,38,49,50,
93984160,177,57,240,0,50,242,160,36,81,50,64,240,107,64,194,242,160,39,34,34,
93985240,97,57,181,34,242,160,38,49,50,145,177,57,240,64,242,212,66,35,160,240,
939869,240,36,242,182,34,35,129,193,57,240,50,242,160,38,34,35,129,193,57,240,
9398735,242,145,38,34,35,160,177,57,240,65,243,128,85,32,39,121,49,242,240,54,
93988215,41,244,144,56,197,57,243,1,121,192,32,32,81,242,63,4,33,106,47,20,160,
93989245,111,4,41,211,82,34,54,67,235,46,255,225,179,47,254,42,98,240,242,240,
93990241,241,1,243,47,16,160,57,241,50,57,245,209,241,64,246,139,91,185,247,41,
93991242,244,242,185,47,13,58,121,240,141,243,68,242,31,1,201,240,56,210,241,12,
9399257,241,237,242,47,4,153,121,246,130,47,5,80,112,50,251,143,42,36,255,225,0,
9399331,35,31,5,15,109,197,4,191,254,175,34,247,240,245,47,16,255,225,30,95,91,
9399431,255,0,100,121,159,55,5,159,18,31,66,31,254,0,64,64,80,240,148,244,161,
93995242,79,2,185,127,2,234,240,231,240,188,241,227,242,29,240,25,192,185,242,
9399629,208,145,57,241,50,242,64,34,49,97,32,241,180,97,253,231,33,57,255,240,3,
93997225,128,255,225,213,240,15,2,240,4,31,10,47,178,159,23,0,
93998};
93999#endif
94000
94001/*
94002 * Case conversion tables generated using tools/extract_caseconv.py.
94003 */
94004
94005/* duk_unicode_caseconv_uc[] */
94006/* duk_unicode_caseconv_lc[] */
94007
94008/*
94009 * Automatically generated by extract_caseconv.py, do not edit!
94010 */
94011
94012const duk_uint8_t duk_unicode_caseconv_uc[1411] = {
94013152,3,128,3,0,184,7,192,6,192,112,35,242,199,224,64,74,192,49,32,128,162,
94014128,108,65,1,189,129,254,131,3,173,3,136,6,7,98,7,34,68,15,12,14,140,72,30,
94015104,28,112,32,67,0,65,4,0,138,0,128,4,1,88,65,76,83,8,104,14,72,43,16,253,
9401628,189,6,39,240,39,224,24,114,12,16,132,16,248,0,248,64,129,241,1,241,128,
94017195,228,3,229,2,7,204,7,206,4,15,160,15,164,6,31,96,31,104,16,62,224,63,
94018116,8,125,200,127,32,32,251,176,254,208,33,247,129,255,128,67,239,67,253,
9401964,135,223,7,254,129,15,216,15,220,2,31,208,31,216,4,63,192,63,208,8,133,
94020192,133,128,129,38,129,37,177,162,195,2,192,5,229,160,2,20,9,170,220,4,232,
9402140,127,160,255,144,154,136,4,4,4,0,192,9,152,9,144,48,19,160,19,145,0,41,
9402296,41,69,192,94,128,94,65,128,193,128,193,2,1,161,1,160,6,3,104,3,102,8,7,
9402356,7,52,64,14,248,14,240,144,31,144,31,130,128,68,96,68,66,64,145,192,145,
94024130,129,184,129,184,2,3,217,3,216,24,8,194,8,192,68,18,44,18,40,216,38,16,
9402538,8,112,77,16,77,6,3,192,35,192,18,199,168,71,168,24,15,168,143,172,132,
9402644,104,44,103,6,89,2,89,0,200,179,176,179,172,21,50,13,50,1,122,104,26,104,
940271,212,228,116,228,65,233,204,233,204,143,211,189,83,188,130,167,127,167,
94028126,11,79,35,79,32,10,158,94,158,88,85,61,173,61,160,97,192,107,64,107,1,0,
94029226,128,226,3,1,198,1,196,6,3,228,3,226,8,10,0,6,152,16,31,192,31,184,34,
94030199,50,199,32,65,128,196,0,195,130,1,185,1,184,4,4,205,79,84,8,0,192,143,0,
94031142,193,1,52,128,203,2,45,39,16,199,5,253,0,11,80,57,192,15,240,23,128,19,
9403216,4,144,23,240,5,48,24,0,36,48,25,32,25,16,25,80,31,96,25,144,25,128,25,
94033160,35,208,25,224,34,0,26,128,26,112,27,240,31,112,29,208,24,224,31,48,31,
9403416,37,2,198,240,37,18,198,208,37,34,199,0,37,48,24,16,37,64,24,96,37,144,
9403524,240,37,176,25,0,37,202,122,176,38,0,25,48,38,26,122,192,38,48,25,64,38,
9403690,120,208,38,128,25,112,38,178,198,32,38,202,122,208,39,18,198,224,39,32,
9403725,208,39,80,25,240,39,210,198,64,40,42,124,80,40,122,123,16,40,128,26,224,
9403840,144,36,64,40,192,36,80,41,32,27,112,41,218,123,32,41,234,123,0,52,80,57,
94039144,55,112,55,96,58,192,56,96,60,32,58,48,60,192,56,192,61,0,57,32,61,16,
9404057,128,61,80,58,96,61,96,58,0,61,112,60,240,63,0,57,160,63,16,58,16,63,32,
9404163,144,63,48,55,240,63,80,57,80,76,240,76,1,200,0,65,33,200,16,65,65,200,
9404232,65,225,200,80,66,33,200,96,66,161,200,112,70,33,200,138,100,161,215,154,
94043119,209,215,210,198,49,216,234,124,97,233,177,230,1,251,224,57,145,254,81,
94044254,194,20,226,19,34,24,66,24,50,198,18,198,2,198,80,35,162,198,96,35,226,
94045207,50,207,42,120,202,120,186,121,74,124,74,124,58,124,42,181,58,123,60,
94046192,27,240,2,152,2,152,10,76,5,120,0,156,3,225,0,37,1,134,1,200,96,115,32,
9404797,0,96,32,118,24,29,40,24,64,24,8,44,60,10,106,10,164,61,45,0,36,1,152,
94048143,75,192,10,128,97,3,211,16,2,184,24,80,244,204,0,178,6,20,61,53,0,32,
94049129,95,15,168,64,116,160,98,99,234,88,29,40,24,152,24,0,250,166,7,74,6,38,
940506,2,62,173,129,210,129,137,129,161,15,192,67,225,0,115,35,240,48,248,72,28,
94051200,252,20,62,20,7,50,63,7,15,133,129,204,143,194,67,225,128,115,35,240,
94052176,248,104,28,200,252,52,62,28,7,50,63,15,15,135,129,204,143,196,67,225,0,
94053115,35,241,48,248,72,28,200,252,84,62,20,7,50,63,23,15,133,129,204,143,198,
9405467,225,128,115,35,241,176,248,104,28,200,252,116,62,28,7,50,63,31,15,135,
94055129,204,143,200,67,229,0,115,35,242,48,249,72,28,200,252,148,62,84,7,50,63,
9405639,15,149,129,204,143,202,67,229,128,115,35,242,176,249,104,28,200,252,180,
9405762,92,7,50,63,47,15,151,129,204,143,204,67,229,0,115,35,243,48,249,72,28,
94058200,252,212,62,84,7,50,63,55,15,149,129,204,143,206,67,229,128,115,35,243,
94059176,249,104,28,200,252,244,62,92,7,50,63,63,15,151,129,204,143,208,67,237,
940600,115,35,244,48,251,72,28,200,253,20,62,212,7,50,63,71,15,181,129,204,143,
94061210,67,237,128,115,35,244,176,251,104,28,200,253,52,62,220,7,50,63,79,15,
94062183,129,204,143,212,67,237,0,115,35,245,48,251,72,28,200,253,84,62,212,7,
9406350,63,87,15,181,129,204,143,214,67,237,128,115,35,245,176,251,104,28,200,
94064253,116,62,220,7,50,63,95,15,183,129,204,143,217,67,247,64,115,35,246,112,
9406528,136,28,200,253,164,7,12,7,50,63,109,1,200,129,161,15,219,224,114,32,104,
9406664,115,35,247,144,28,136,28,200,254,20,63,148,7,50,63,135,1,203,129,204,
94067143,226,64,113,32,115,35,248,208,28,184,26,16,254,62,7,46,6,132,7,50,63,
94068153,1,203,129,204,143,233,96,115,32,97,0,96,3,250,120,28,200,24,64,24,8,
94069254,180,7,50,6,132,63,175,129,204,129,132,1,161,15,241,96,116,160,97,0,96,
940703,252,120,29,40,24,64,24,8,255,36,7,66,6,38,63,205,1,210,129,161,15,243,
94071224,116,160,97,0,104,67,254,80,255,208,28,200,255,156,7,82,7,50,63,233,1,
94072199,129,204,143,251,64,117,32,104,67,254,248,29,72,26,16,28,200,255,228,7,
9407382,7,51,246,1,0,35,0,35,125,128,192,8,192,9,63,96,80,2,48,2,103,216,30,0,
94074140,0,140,0,147,246,9,128,35,0,35,0,38,125,130,192,10,96,10,159,96,208,2,
94075152,2,167,216,156,10,136,10,141,246,41,2,162,2,154,253,138,192,168,128,167,
94076127,98,208,42,112,42,55,216,188,10,136,10,122,
94077};
94078const duk_uint8_t duk_unicode_caseconv_lc[706] = {
94079160,3,0,3,128,184,6,192,7,192,112,24,144,37,96,64,54,32,81,64,128,226,0,
94080235,65,129,199,1,230,130,3,145,3,177,34,7,70,7,134,36,15,244,13,236,24,32,
940810,34,129,0,65,0,67,4,0,166,32,172,41,132,40,11,64,19,9,208,85,184,80,19,
94082240,19,248,12,57,32,33,160,172,114,244,67,244,24,248,64,248,0,129,241,129,
94083241,0,195,229,3,228,2,7,206,7,204,4,15,164,15,160,6,31,104,31,96,16,63,16,
9408463,0,32,126,96,126,64,64,253,64,253,0,129,251,129,251,0,67,247,67,238,0,
94085135,242,7,220,130,15,236,15,232,2,31,218,31,118,4,63,208,63,192,8,127,168,
94086125,232,16,255,192,251,192,33,255,161,247,192,68,44,4,46,4,9,45,137,52,13,
9408722,0,22,24,47,44,126,2,63,5,254,67,254,130,106,48,16,0,16,19,0,38,64,38,96,
94088192,78,64,78,132,0,165,0,165,151,1,121,1,122,6,3,4,3,6,8,6,128,6,132,24,13,
94089152,13,160,32,28,176,28,193,32,59,192,59,226,64,124,128,124,193,0,252,0,
94090252,148,2,34,2,35,18,4,140,4,142,20,13,192,13,196,16,30,192,30,200,192,70,
940910,70,18,32,145,64,145,102,193,48,65,48,131,130,104,2,104,176,30,0,30,1,150,
9409261,64,61,66,192,125,100,125,68,33,99,57,99,64,50,200,2,200,22,69,157,101,
94093157,128,169,144,41,144,75,211,64,83,64,142,167,34,167,35,15,78,101,78,102,
94094126,157,230,157,232,21,59,245,59,248,90,121,10,121,16,84,242,212,242,226,
94095169,237,41,237,67,12,3,76,5,0,8,6,176,6,180,16,14,32,14,48,48,28,80,28,96,
9409664,126,224,127,0,139,28,139,28,193,6,3,14,3,16,8,6,224,6,228,21,61,80,19,
9409748,32,3,1,150,2,105,4,4,118,4,120,8,67,28,180,156,23,240,192,94,0,63,192,
9409896,64,148,192,97,128,149,0,99,128,119,64,99,192,150,64,100,0,150,192,100,
9409964,100,128,100,192,152,0,101,0,152,192,101,192,154,0,102,0,102,64,103,64,
94100156,128,103,192,157,64,105,192,106,0,107,128,162,0,109,192,164,128,124,64,
94101124,192,125,128,101,64,125,192,111,192,136,0,103,128,142,139,25,64,143,64,
94102102,128,143,139,25,128,144,192,96,0,145,0,162,64,145,64,163,0,221,128,221,
94103192,223,192,252,192,225,128,235,0,227,0,243,0,243,192,245,192,253,0,238,0,
94104254,64,252,129,48,1,51,199,167,128,55,199,239,7,236,199,243,7,240,199,251,
941057,249,71,255,7,252,200,73,128,242,72,74,128,26,200,74,192,57,72,76,136,83,
94106136,96,200,97,11,24,11,24,75,24,128,154,203,24,199,95,75,25,0,159,75,27,64,
94107148,75,27,128,156,75,27,192,148,11,28,0,148,139,60,139,60,233,223,71,94,
94108105,226,233,227,41,227,64,153,105,234,192,151,41,235,0,152,105,235,64,155,
9410941,236,0,167,169,236,64,161,233,236,128,167,105,236,234,212,233,240,169,
94110240,233,241,41,229,41,241,64,160,169,241,135,99,128,128,152,64,13,32,96,
94111224,
94112};
94113
94114#if defined(DUK_USE_REGEXP_CANON_WORKAROUND)
94115/*
94116 * Automatically generated by extract_caseconv.py, do not edit!
94117 */
94118
94119const duk_uint16_t duk_unicode_re_canon_lookup[65536] = {
941200,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,
9412128,29,30,31,32,33,34,35,36,37,38,39,40,41,42,43,44,45,46,47,48,49,50,51,52,
9412253,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,70,71,72,73,74,75,76,77,
9412378,79,80,81,82,83,84,85,86,87,88,89,90,91,92,93,94,95,96,65,66,67,68,69,70,
9412471,72,73,74,75,76,77,78,79,80,81,82,83,84,85,86,87,88,89,90,123,124,125,
94125126,127,128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,
94126144,145,146,147,148,149,150,151,152,153,154,155,156,157,158,159,160,161,
94127162,163,164,165,166,167,168,169,170,171,172,173,174,175,176,177,178,179,
94128180,924,182,183,184,185,186,187,188,189,190,191,192,193,194,195,196,197,
94129198,199,200,201,202,203,204,205,206,207,208,209,210,211,212,213,214,215,
94130216,217,218,219,220,221,222,223,192,193,194,195,196,197,198,199,200,201,
94131202,203,204,205,206,207,208,209,210,211,212,213,214,247,216,217,218,219,
94132220,221,222,376,256,256,258,258,260,260,262,262,264,264,266,266,268,268,
94133270,270,272,272,274,274,276,276,278,278,280,280,282,282,284,284,286,286,
94134288,288,290,290,292,292,294,294,296,296,298,298,300,300,302,302,304,305,
94135306,306,308,308,310,310,312,313,313,315,315,317,317,319,319,321,321,323,
94136323,325,325,327,327,329,330,330,332,332,334,334,336,336,338,338,340,340,
94137342,342,344,344,346,346,348,348,350,350,352,352,354,354,356,356,358,358,
94138360,360,362,362,364,364,366,366,368,368,370,370,372,372,374,374,376,377,
94139377,379,379,381,381,383,579,385,386,386,388,388,390,391,391,393,394,395,
94140395,397,398,399,400,401,401,403,404,502,406,407,408,408,573,411,412,413,
94141544,415,416,416,418,418,420,420,422,423,423,425,426,427,428,428,430,431,
94142431,433,434,435,435,437,437,439,440,440,442,443,444,444,446,503,448,449,
94143450,451,452,452,452,455,455,455,458,458,458,461,461,463,463,465,465,467,
94144467,469,469,471,471,473,473,475,475,398,478,478,480,480,482,482,484,484,
94145486,486,488,488,490,490,492,492,494,494,496,497,497,497,500,500,502,503,
94146504,504,506,506,508,508,510,510,512,512,514,514,516,516,518,518,520,520,
94147522,522,524,524,526,526,528,528,530,530,532,532,534,534,536,536,538,538,
94148540,540,542,542,544,545,546,546,548,548,550,550,552,552,554,554,556,556,
94149558,558,560,560,562,562,564,565,566,567,568,569,570,571,571,573,574,11390,
9415011391,577,577,579,580,581,582,582,584,584,586,586,588,588,590,590,11375,
9415111373,11376,385,390,597,393,394,600,399,602,400,42923L,605,606,607,403,
9415242924L,610,404,612,42893L,42922L,615,407,406,42926L,11362,42925L,621,622,
94153412,624,11374,413,627,628,415,630,631,632,633,634,635,636,11364,638,639,
94154422,641,42949L,425,644,645,646,42929L,430,580,433,434,581,653,654,655,656,
94155657,439,659,660,661,662,663,664,665,666,667,668,42930L,42928L,671,672,673,
94156674,675,676,677,678,679,680,681,682,683,684,685,686,687,688,689,690,691,
94157692,693,694,695,696,697,698,699,700,701,702,703,704,705,706,707,708,709,
94158710,711,712,713,714,715,716,717,718,719,720,721,722,723,724,725,726,727,
94159728,729,730,731,732,733,734,735,736,737,738,739,740,741,742,743,744,745,
94160746,747,748,749,750,751,752,753,754,755,756,757,758,759,760,761,762,763,
94161764,765,766,767,768,769,770,771,772,773,774,775,776,777,778,779,780,781,
94162782,783,784,785,786,787,788,789,790,791,792,793,794,795,796,797,798,799,
94163800,801,802,803,804,805,806,807,808,809,810,811,812,813,814,815,816,817,
94164818,819,820,821,822,823,824,825,826,827,828,829,830,831,832,833,834,835,
94165836,921,838,839,840,841,842,843,844,845,846,847,848,849,850,851,852,853,
94166854,855,856,857,858,859,860,861,862,863,864,865,866,867,868,869,870,871,
94167872,873,874,875,876,877,878,879,880,880,882,882,884,885,886,886,888,889,
94168890,1021,1022,1023,894,895,896,897,898,899,900,901,902,903,904,905,906,907,
94169908,909,910,911,912,913,914,915,916,917,918,919,920,921,922,923,924,925,
94170926,927,928,929,930,931,932,933,934,935,936,937,938,939,902,904,905,906,
94171944,913,914,915,916,917,918,919,920,921,922,923,924,925,926,927,928,929,
94172931,931,932,933,934,935,936,937,938,939,908,910,911,975,914,920,978,979,
94173980,934,928,975,984,984,986,986,988,988,990,990,992,992,994,994,996,996,
94174998,998,1000,1000,1002,1002,1004,1004,1006,1006,922,929,1017,895,1012,917,
941751014,1015,1015,1017,1018,1018,1020,1021,1022,1023,1024,1025,1026,1027,1028,
941761029,1030,1031,1032,1033,1034,1035,1036,1037,1038,1039,1040,1041,1042,1043,
941771044,1045,1046,1047,1048,1049,1050,1051,1052,1053,1054,1055,1056,1057,1058,
941781059,1060,1061,1062,1063,1064,1065,1066,1067,1068,1069,1070,1071,1040,1041,
941791042,1043,1044,1045,1046,1047,1048,1049,1050,1051,1052,1053,1054,1055,1056,
941801057,1058,1059,1060,1061,1062,1063,1064,1065,1066,1067,1068,1069,1070,1071,
941811024,1025,1026,1027,1028,1029,1030,1031,1032,1033,1034,1035,1036,1037,1038,
941821039,1120,1120,1122,1122,1124,1124,1126,1126,1128,1128,1130,1130,1132,1132,
941831134,1134,1136,1136,1138,1138,1140,1140,1142,1142,1144,1144,1146,1146,1148,
941841148,1150,1150,1152,1152,1154,1155,1156,1157,1158,1159,1160,1161,1162,1162,
941851164,1164,1166,1166,1168,1168,1170,1170,1172,1172,1174,1174,1176,1176,1178,
941861178,1180,1180,1182,1182,1184,1184,1186,1186,1188,1188,1190,1190,1192,1192,
941871194,1194,1196,1196,1198,1198,1200,1200,1202,1202,1204,1204,1206,1206,1208,
941881208,1210,1210,1212,1212,1214,1214,1216,1217,1217,1219,1219,1221,1221,1223,
941891223,1225,1225,1227,1227,1229,1229,1216,1232,1232,1234,1234,1236,1236,1238,
941901238,1240,1240,1242,1242,1244,1244,1246,1246,1248,1248,1250,1250,1252,1252,
941911254,1254,1256,1256,1258,1258,1260,1260,1262,1262,1264,1264,1266,1266,1268,
941921268,1270,1270,1272,1272,1274,1274,1276,1276,1278,1278,1280,1280,1282,1282,
941931284,1284,1286,1286,1288,1288,1290,1290,1292,1292,1294,1294,1296,1296,1298,
941941298,1300,1300,1302,1302,1304,1304,1306,1306,1308,1308,1310,1310,1312,1312,
941951314,1314,1316,1316,1318,1318,1320,1320,1322,1322,1324,1324,1326,1326,1328,
941961329,1330,1331,1332,1333,1334,1335,1336,1337,1338,1339,1340,1341,1342,1343,
941971344,1345,1346,1347,1348,1349,1350,1351,1352,1353,1354,1355,1356,1357,1358,
941981359,1360,1361,1362,1363,1364,1365,1366,1367,1368,1369,1370,1371,1372,1373,
941991374,1375,1376,1329,1330,1331,1332,1333,1334,1335,1336,1337,1338,1339,1340,
942001341,1342,1343,1344,1345,1346,1347,1348,1349,1350,1351,1352,1353,1354,1355,
942011356,1357,1358,1359,1360,1361,1362,1363,1364,1365,1366,1415,1416,1417,1418,
942021419,1420,1421,1422,1423,1424,1425,1426,1427,1428,1429,1430,1431,1432,1433,
942031434,1435,1436,1437,1438,1439,1440,1441,1442,1443,1444,1445,1446,1447,1448,
942041449,1450,1451,1452,1453,1454,1455,1456,1457,1458,1459,1460,1461,1462,1463,
942051464,1465,1466,1467,1468,1469,1470,1471,1472,1473,1474,1475,1476,1477,1478,
942061479,1480,1481,1482,1483,1484,1485,1486,1487,1488,1489,1490,1491,1492,1493,
942071494,1495,1496,1497,1498,1499,1500,1501,1502,1503,1504,1505,1506,1507,1508,
942081509,1510,1511,1512,1513,1514,1515,1516,1517,1518,1519,1520,1521,1522,1523,
942091524,1525,1526,1527,1528,1529,1530,1531,1532,1533,1534,1535,1536,1537,1538,
942101539,1540,1541,1542,1543,1544,1545,1546,1547,1548,1549,1550,1551,1552,1553,
942111554,1555,1556,1557,1558,1559,1560,1561,1562,1563,1564,1565,1566,1567,1568,
942121569,1570,1571,1572,1573,1574,1575,1576,1577,1578,1579,1580,1581,1582,1583,
942131584,1585,1586,1587,1588,1589,1590,1591,1592,1593,1594,1595,1596,1597,1598,
942141599,1600,1601,1602,1603,1604,1605,1606,1607,1608,1609,1610,1611,1612,1613,
942151614,1615,1616,1617,1618,1619,1620,1621,1622,1623,1624,1625,1626,1627,1628,
942161629,1630,1631,1632,1633,1634,1635,1636,1637,1638,1639,1640,1641,1642,1643,
942171644,1645,1646,1647,1648,1649,1650,1651,1652,1653,1654,1655,1656,1657,1658,
942181659,1660,1661,1662,1663,1664,1665,1666,1667,1668,1669,1670,1671,1672,1673,
942191674,1675,1676,1677,1678,1679,1680,1681,1682,1683,1684,1685,1686,1687,1688,
942201689,1690,1691,1692,1693,1694,1695,1696,1697,1698,1699,1700,1701,1702,1703,
942211704,1705,1706,1707,1708,1709,1710,1711,1712,1713,1714,1715,1716,1717,1718,
942221719,1720,1721,1722,1723,1724,1725,1726,1727,1728,1729,1730,1731,1732,1733,
942231734,1735,1736,1737,1738,1739,1740,1741,1742,1743,1744,1745,1746,1747,1748,
942241749,1750,1751,1752,1753,1754,1755,1756,1757,1758,1759,1760,1761,1762,1763,
942251764,1765,1766,1767,1768,1769,1770,1771,1772,1773,1774,1775,1776,1777,1778,
942261779,1780,1781,1782,1783,1784,1785,1786,1787,1788,1789,1790,1791,1792,1793,
942271794,1795,1796,1797,1798,1799,1800,1801,1802,1803,1804,1805,1806,1807,1808,
942281809,1810,1811,1812,1813,1814,1815,1816,1817,1818,1819,1820,1821,1822,1823,
942291824,1825,1826,1827,1828,1829,1830,1831,1832,1833,1834,1835,1836,1837,1838,
942301839,1840,1841,1842,1843,1844,1845,1846,1847,1848,1849,1850,1851,1852,1853,
942311854,1855,1856,1857,1858,1859,1860,1861,1862,1863,1864,1865,1866,1867,1868,
942321869,1870,1871,1872,1873,1874,1875,1876,1877,1878,1879,1880,1881,1882,1883,
942331884,1885,1886,1887,1888,1889,1890,1891,1892,1893,1894,1895,1896,1897,1898,
942341899,1900,1901,1902,1903,1904,1905,1906,1907,1908,1909,1910,1911,1912,1913,
942351914,1915,1916,1917,1918,1919,1920,1921,1922,1923,1924,1925,1926,1927,1928,
942361929,1930,1931,1932,1933,1934,1935,1936,1937,1938,1939,1940,1941,1942,1943,
942371944,1945,1946,1947,1948,1949,1950,1951,1952,1953,1954,1955,1956,1957,1958,
942381959,1960,1961,1962,1963,1964,1965,1966,1967,1968,1969,1970,1971,1972,1973,
942391974,1975,1976,1977,1978,1979,1980,1981,1982,1983,1984,1985,1986,1987,1988,
942401989,1990,1991,1992,1993,1994,1995,1996,1997,1998,1999,2000,2001,2002,2003,
942412004,2005,2006,2007,2008,2009,2010,2011,2012,2013,2014,2015,2016,2017,2018,
942422019,2020,2021,2022,2023,2024,2025,2026,2027,2028,2029,2030,2031,2032,2033,
942432034,2035,2036,2037,2038,2039,2040,2041,2042,2043,2044,2045,2046,2047,2048,
942442049,2050,2051,2052,2053,2054,2055,2056,2057,2058,2059,2060,2061,2062,2063,
942452064,2065,2066,2067,2068,2069,2070,2071,2072,2073,2074,2075,2076,2077,2078,
942462079,2080,2081,2082,2083,2084,2085,2086,2087,2088,2089,2090,2091,2092,2093,
942472094,2095,2096,2097,2098,2099,2100,2101,2102,2103,2104,2105,2106,2107,2108,
942482109,2110,2111,2112,2113,2114,2115,2116,2117,2118,2119,2120,2121,2122,2123,
942492124,2125,2126,2127,2128,2129,2130,2131,2132,2133,2134,2135,2136,2137,2138,
942502139,2140,2141,2142,2143,2144,2145,2146,2147,2148,2149,2150,2151,2152,2153,
942512154,2155,2156,2157,2158,2159,2160,2161,2162,2163,2164,2165,2166,2167,2168,
942522169,2170,2171,2172,2173,2174,2175,2176,2177,2178,2179,2180,2181,2182,2183,
942532184,2185,2186,2187,2188,2189,2190,2191,2192,2193,2194,2195,2196,2197,2198,
942542199,2200,2201,2202,2203,2204,2205,2206,2207,2208,2209,2210,2211,2212,2213,
942552214,2215,2216,2217,2218,2219,2220,2221,2222,2223,2224,2225,2226,2227,2228,
942562229,2230,2231,2232,2233,2234,2235,2236,2237,2238,2239,2240,2241,2242,2243,
942572244,2245,2246,2247,2248,2249,2250,2251,2252,2253,2254,2255,2256,2257,2258,
942582259,2260,2261,2262,2263,2264,2265,2266,2267,2268,2269,2270,2271,2272,2273,
942592274,2275,2276,2277,2278,2279,2280,2281,2282,2283,2284,2285,2286,2287,2288,
942602289,2290,2291,2292,2293,2294,2295,2296,2297,2298,2299,2300,2301,2302,2303,
942612304,2305,2306,2307,2308,2309,2310,2311,2312,2313,2314,2315,2316,2317,2318,
942622319,2320,2321,2322,2323,2324,2325,2326,2327,2328,2329,2330,2331,2332,2333,
942632334,2335,2336,2337,2338,2339,2340,2341,2342,2343,2344,2345,2346,2347,2348,
942642349,2350,2351,2352,2353,2354,2355,2356,2357,2358,2359,2360,2361,2362,2363,
942652364,2365,2366,2367,2368,2369,2370,2371,2372,2373,2374,2375,2376,2377,2378,
942662379,2380,2381,2382,2383,2384,2385,2386,2387,2388,2389,2390,2391,2392,2393,
942672394,2395,2396,2397,2398,2399,2400,2401,2402,2403,2404,2405,2406,2407,2408,
942682409,2410,2411,2412,2413,2414,2415,2416,2417,2418,2419,2420,2421,2422,2423,
942692424,2425,2426,2427,2428,2429,2430,2431,2432,2433,2434,2435,2436,2437,2438,
942702439,2440,2441,2442,2443,2444,2445,2446,2447,2448,2449,2450,2451,2452,2453,
942712454,2455,2456,2457,2458,2459,2460,2461,2462,2463,2464,2465,2466,2467,2468,
942722469,2470,2471,2472,2473,2474,2475,2476,2477,2478,2479,2480,2481,2482,2483,
942732484,2485,2486,2487,2488,2489,2490,2491,2492,2493,2494,2495,2496,2497,2498,
942742499,2500,2501,2502,2503,2504,2505,2506,2507,2508,2509,2510,2511,2512,2513,
942752514,2515,2516,2517,2518,2519,2520,2521,2522,2523,2524,2525,2526,2527,2528,
942762529,2530,2531,2532,2533,2534,2535,2536,2537,2538,2539,2540,2541,2542,2543,
942772544,2545,2546,2547,2548,2549,2550,2551,2552,2553,2554,2555,2556,2557,2558,
942782559,2560,2561,2562,2563,2564,2565,2566,2567,2568,2569,2570,2571,2572,2573,
942792574,2575,2576,2577,2578,2579,2580,2581,2582,2583,2584,2585,2586,2587,2588,
942802589,2590,2591,2592,2593,2594,2595,2596,2597,2598,2599,2600,2601,2602,2603,
942812604,2605,2606,2607,2608,2609,2610,2611,2612,2613,2614,2615,2616,2617,2618,
942822619,2620,2621,2622,2623,2624,2625,2626,2627,2628,2629,2630,2631,2632,2633,
942832634,2635,2636,2637,2638,2639,2640,2641,2642,2643,2644,2645,2646,2647,2648,
942842649,2650,2651,2652,2653,2654,2655,2656,2657,2658,2659,2660,2661,2662,2663,
942852664,2665,2666,2667,2668,2669,2670,2671,2672,2673,2674,2675,2676,2677,2678,
942862679,2680,2681,2682,2683,2684,2685,2686,2687,2688,2689,2690,2691,2692,2693,
942872694,2695,2696,2697,2698,2699,2700,2701,2702,2703,2704,2705,2706,2707,2708,
942882709,2710,2711,2712,2713,2714,2715,2716,2717,2718,2719,2720,2721,2722,2723,
942892724,2725,2726,2727,2728,2729,2730,2731,2732,2733,2734,2735,2736,2737,2738,
942902739,2740,2741,2742,2743,2744,2745,2746,2747,2748,2749,2750,2751,2752,2753,
942912754,2755,2756,2757,2758,2759,2760,2761,2762,2763,2764,2765,2766,2767,2768,
942922769,2770,2771,2772,2773,2774,2775,2776,2777,2778,2779,2780,2781,2782,2783,
942932784,2785,2786,2787,2788,2789,2790,2791,2792,2793,2794,2795,2796,2797,2798,
942942799,2800,2801,2802,2803,2804,2805,2806,2807,2808,2809,2810,2811,2812,2813,
942952814,2815,2816,2817,2818,2819,2820,2821,2822,2823,2824,2825,2826,2827,2828,
942962829,2830,2831,2832,2833,2834,2835,2836,2837,2838,2839,2840,2841,2842,2843,
942972844,2845,2846,2847,2848,2849,2850,2851,2852,2853,2854,2855,2856,2857,2858,
942982859,2860,2861,2862,2863,2864,2865,2866,2867,2868,2869,2870,2871,2872,2873,
942992874,2875,2876,2877,2878,2879,2880,2881,2882,2883,2884,2885,2886,2887,2888,
943002889,2890,2891,2892,2893,2894,2895,2896,2897,2898,2899,2900,2901,2902,2903,
943012904,2905,2906,2907,2908,2909,2910,2911,2912,2913,2914,2915,2916,2917,2918,
943022919,2920,2921,2922,2923,2924,2925,2926,2927,2928,2929,2930,2931,2932,2933,
943032934,2935,2936,2937,2938,2939,2940,2941,2942,2943,2944,2945,2946,2947,2948,
943042949,2950,2951,2952,2953,2954,2955,2956,2957,2958,2959,2960,2961,2962,2963,
943052964,2965,2966,2967,2968,2969,2970,2971,2972,2973,2974,2975,2976,2977,2978,
943062979,2980,2981,2982,2983,2984,2985,2986,2987,2988,2989,2990,2991,2992,2993,
943072994,2995,2996,2997,2998,2999,3000,3001,3002,3003,3004,3005,3006,3007,3008,
943083009,3010,3011,3012,3013,3014,3015,3016,3017,3018,3019,3020,3021,3022,3023,
943093024,3025,3026,3027,3028,3029,3030,3031,3032,3033,3034,3035,3036,3037,3038,
943103039,3040,3041,3042,3043,3044,3045,3046,3047,3048,3049,3050,3051,3052,3053,
943113054,3055,3056,3057,3058,3059,3060,3061,3062,3063,3064,3065,3066,3067,3068,
943123069,3070,3071,3072,3073,3074,3075,3076,3077,3078,3079,3080,3081,3082,3083,
943133084,3085,3086,3087,3088,3089,3090,3091,3092,3093,3094,3095,3096,3097,3098,
943143099,3100,3101,3102,3103,3104,3105,3106,3107,3108,3109,3110,3111,3112,3113,
943153114,3115,3116,3117,3118,3119,3120,3121,3122,3123,3124,3125,3126,3127,3128,
943163129,3130,3131,3132,3133,3134,3135,3136,3137,3138,3139,3140,3141,3142,3143,
943173144,3145,3146,3147,3148,3149,3150,3151,3152,3153,3154,3155,3156,3157,3158,
943183159,3160,3161,3162,3163,3164,3165,3166,3167,3168,3169,3170,3171,3172,3173,
943193174,3175,3176,3177,3178,3179,3180,3181,3182,3183,3184,3185,3186,3187,3188,
943203189,3190,3191,3192,3193,3194,3195,3196,3197,3198,3199,3200,3201,3202,3203,
943213204,3205,3206,3207,3208,3209,3210,3211,3212,3213,3214,3215,3216,3217,3218,
943223219,3220,3221,3222,3223,3224,3225,3226,3227,3228,3229,3230,3231,3232,3233,
943233234,3235,3236,3237,3238,3239,3240,3241,3242,3243,3244,3245,3246,3247,3248,
943243249,3250,3251,3252,3253,3254,3255,3256,3257,3258,3259,3260,3261,3262,3263,
943253264,3265,3266,3267,3268,3269,3270,3271,3272,3273,3274,3275,3276,3277,3278,
943263279,3280,3281,3282,3283,3284,3285,3286,3287,3288,3289,3290,3291,3292,3293,
943273294,3295,3296,3297,3298,3299,3300,3301,3302,3303,3304,3305,3306,3307,3308,
943283309,3310,3311,3312,3313,3314,3315,3316,3317,3318,3319,3320,3321,3322,3323,
943293324,3325,3326,3327,3328,3329,3330,3331,3332,3333,3334,3335,3336,3337,3338,
943303339,3340,3341,3342,3343,3344,3345,3346,3347,3348,3349,3350,3351,3352,3353,
943313354,3355,3356,3357,3358,3359,3360,3361,3362,3363,3364,3365,3366,3367,3368,
943323369,3370,3371,3372,3373,3374,3375,3376,3377,3378,3379,3380,3381,3382,3383,
943333384,3385,3386,3387,3388,3389,3390,3391,3392,3393,3394,3395,3396,3397,3398,
943343399,3400,3401,3402,3403,3404,3405,3406,3407,3408,3409,3410,3411,3412,3413,
943353414,3415,3416,3417,3418,3419,3420,3421,3422,3423,3424,3425,3426,3427,3428,
943363429,3430,3431,3432,3433,3434,3435,3436,3437,3438,3439,3440,3441,3442,3443,
943373444,3445,3446,3447,3448,3449,3450,3451,3452,3453,3454,3455,3456,3457,3458,
943383459,3460,3461,3462,3463,3464,3465,3466,3467,3468,3469,3470,3471,3472,3473,
943393474,3475,3476,3477,3478,3479,3480,3481,3482,3483,3484,3485,3486,3487,3488,
943403489,3490,3491,3492,3493,3494,3495,3496,3497,3498,3499,3500,3501,3502,3503,
943413504,3505,3506,3507,3508,3509,3510,3511,3512,3513,3514,3515,3516,3517,3518,
943423519,3520,3521,3522,3523,3524,3525,3526,3527,3528,3529,3530,3531,3532,3533,
943433534,3535,3536,3537,3538,3539,3540,3541,3542,3543,3544,3545,3546,3547,3548,
943443549,3550,3551,3552,3553,3554,3555,3556,3557,3558,3559,3560,3561,3562,3563,
943453564,3565,3566,3567,3568,3569,3570,3571,3572,3573,3574,3575,3576,3577,3578,
943463579,3580,3581,3582,3583,3584,3585,3586,3587,3588,3589,3590,3591,3592,3593,
943473594,3595,3596,3597,3598,3599,3600,3601,3602,3603,3604,3605,3606,3607,3608,
943483609,3610,3611,3612,3613,3614,3615,3616,3617,3618,3619,3620,3621,3622,3623,
943493624,3625,3626,3627,3628,3629,3630,3631,3632,3633,3634,3635,3636,3637,3638,
943503639,3640,3641,3642,3643,3644,3645,3646,3647,3648,3649,3650,3651,3652,3653,
943513654,3655,3656,3657,3658,3659,3660,3661,3662,3663,3664,3665,3666,3667,3668,
943523669,3670,3671,3672,3673,3674,3675,3676,3677,3678,3679,3680,3681,3682,3683,
943533684,3685,3686,3687,3688,3689,3690,3691,3692,3693,3694,3695,3696,3697,3698,
943543699,3700,3701,3702,3703,3704,3705,3706,3707,3708,3709,3710,3711,3712,3713,
943553714,3715,3716,3717,3718,3719,3720,3721,3722,3723,3724,3725,3726,3727,3728,
943563729,3730,3731,3732,3733,3734,3735,3736,3737,3738,3739,3740,3741,3742,3743,
943573744,3745,3746,3747,3748,3749,3750,3751,3752,3753,3754,3755,3756,3757,3758,
943583759,3760,3761,3762,3763,3764,3765,3766,3767,3768,3769,3770,3771,3772,3773,
943593774,3775,3776,3777,3778,3779,3780,3781,3782,3783,3784,3785,3786,3787,3788,
943603789,3790,3791,3792,3793,3794,3795,3796,3797,3798,3799,3800,3801,3802,3803,
943613804,3805,3806,3807,3808,3809,3810,3811,3812,3813,3814,3815,3816,3817,3818,
943623819,3820,3821,3822,3823,3824,3825,3826,3827,3828,3829,3830,3831,3832,3833,
943633834,3835,3836,3837,3838,3839,3840,3841,3842,3843,3844,3845,3846,3847,3848,
943643849,3850,3851,3852,3853,3854,3855,3856,3857,3858,3859,3860,3861,3862,3863,
943653864,3865,3866,3867,3868,3869,3870,3871,3872,3873,3874,3875,3876,3877,3878,
943663879,3880,3881,3882,3883,3884,3885,3886,3887,3888,3889,3890,3891,3892,3893,
943673894,3895,3896,3897,3898,3899,3900,3901,3902,3903,3904,3905,3906,3907,3908,
943683909,3910,3911,3912,3913,3914,3915,3916,3917,3918,3919,3920,3921,3922,3923,
943693924,3925,3926,3927,3928,3929,3930,3931,3932,3933,3934,3935,3936,3937,3938,
943703939,3940,3941,3942,3943,3944,3945,3946,3947,3948,3949,3950,3951,3952,3953,
943713954,3955,3956,3957,3958,3959,3960,3961,3962,3963,3964,3965,3966,3967,3968,
943723969,3970,3971,3972,3973,3974,3975,3976,3977,3978,3979,3980,3981,3982,3983,
943733984,3985,3986,3987,3988,3989,3990,3991,3992,3993,3994,3995,3996,3997,3998,
943743999,4000,4001,4002,4003,4004,4005,4006,4007,4008,4009,4010,4011,4012,4013,
943754014,4015,4016,4017,4018,4019,4020,4021,4022,4023,4024,4025,4026,4027,4028,
943764029,4030,4031,4032,4033,4034,4035,4036,4037,4038,4039,4040,4041,4042,4043,
943774044,4045,4046,4047,4048,4049,4050,4051,4052,4053,4054,4055,4056,4057,4058,
943784059,4060,4061,4062,4063,4064,4065,4066,4067,4068,4069,4070,4071,4072,4073,
943794074,4075,4076,4077,4078,4079,4080,4081,4082,4083,4084,4085,4086,4087,4088,
943804089,4090,4091,4092,4093,4094,4095,4096,4097,4098,4099,4100,4101,4102,4103,
943814104,4105,4106,4107,4108,4109,4110,4111,4112,4113,4114,4115,4116,4117,4118,
943824119,4120,4121,4122,4123,4124,4125,4126,4127,4128,4129,4130,4131,4132,4133,
943834134,4135,4136,4137,4138,4139,4140,4141,4142,4143,4144,4145,4146,4147,4148,
943844149,4150,4151,4152,4153,4154,4155,4156,4157,4158,4159,4160,4161,4162,4163,
943854164,4165,4166,4167,4168,4169,4170,4171,4172,4173,4174,4175,4176,4177,4178,
943864179,4180,4181,4182,4183,4184,4185,4186,4187,4188,4189,4190,4191,4192,4193,
943874194,4195,4196,4197,4198,4199,4200,4201,4202,4203,4204,4205,4206,4207,4208,
943884209,4210,4211,4212,4213,4214,4215,4216,4217,4218,4219,4220,4221,4222,4223,
943894224,4225,4226,4227,4228,4229,4230,4231,4232,4233,4234,4235,4236,4237,4238,
943904239,4240,4241,4242,4243,4244,4245,4246,4247,4248,4249,4250,4251,4252,4253,
943914254,4255,4256,4257,4258,4259,4260,4261,4262,4263,4264,4265,4266,4267,4268,
943924269,4270,4271,4272,4273,4274,4275,4276,4277,4278,4279,4280,4281,4282,4283,
943934284,4285,4286,4287,4288,4289,4290,4291,4292,4293,4294,4295,4296,4297,4298,
943944299,4300,4301,4302,4303,7312,7313,7314,7315,7316,7317,7318,7319,7320,7321,
943957322,7323,7324,7325,7326,7327,7328,7329,7330,7331,7332,7333,7334,7335,7336,
943967337,7338,7339,7340,7341,7342,7343,7344,7345,7346,7347,7348,7349,7350,7351,
943977352,7353,7354,4347,4348,7357,7358,7359,4352,4353,4354,4355,4356,4357,4358,
943984359,4360,4361,4362,4363,4364,4365,4366,4367,4368,4369,4370,4371,4372,4373,
943994374,4375,4376,4377,4378,4379,4380,4381,4382,4383,4384,4385,4386,4387,4388,
944004389,4390,4391,4392,4393,4394,4395,4396,4397,4398,4399,4400,4401,4402,4403,
944014404,4405,4406,4407,4408,4409,4410,4411,4412,4413,4414,4415,4416,4417,4418,
944024419,4420,4421,4422,4423,4424,4425,4426,4427,4428,4429,4430,4431,4432,4433,
944034434,4435,4436,4437,4438,4439,4440,4441,4442,4443,4444,4445,4446,4447,4448,
944044449,4450,4451,4452,4453,4454,4455,4456,4457,4458,4459,4460,4461,4462,4463,
944054464,4465,4466,4467,4468,4469,4470,4471,4472,4473,4474,4475,4476,4477,4478,
944064479,4480,4481,4482,4483,4484,4485,4486,4487,4488,4489,4490,4491,4492,4493,
944074494,4495,4496,4497,4498,4499,4500,4501,4502,4503,4504,4505,4506,4507,4508,
944084509,4510,4511,4512,4513,4514,4515,4516,4517,4518,4519,4520,4521,4522,4523,
944094524,4525,4526,4527,4528,4529,4530,4531,4532,4533,4534,4535,4536,4537,4538,
944104539,4540,4541,4542,4543,4544,4545,4546,4547,4548,4549,4550,4551,4552,4553,
944114554,4555,4556,4557,4558,4559,4560,4561,4562,4563,4564,4565,4566,4567,4568,
944124569,4570,4571,4572,4573,4574,4575,4576,4577,4578,4579,4580,4581,4582,4583,
944134584,4585,4586,4587,4588,4589,4590,4591,4592,4593,4594,4595,4596,4597,4598,
944144599,4600,4601,4602,4603,4604,4605,4606,4607,4608,4609,4610,4611,4612,4613,
944154614,4615,4616,4617,4618,4619,4620,4621,4622,4623,4624,4625,4626,4627,4628,
944164629,4630,4631,4632,4633,4634,4635,4636,4637,4638,4639,4640,4641,4642,4643,
944174644,4645,4646,4647,4648,4649,4650,4651,4652,4653,4654,4655,4656,4657,4658,
944184659,4660,4661,4662,4663,4664,4665,4666,4667,4668,4669,4670,4671,4672,4673,
944194674,4675,4676,4677,4678,4679,4680,4681,4682,4683,4684,4685,4686,4687,4688,
944204689,4690,4691,4692,4693,4694,4695,4696,4697,4698,4699,4700,4701,4702,4703,
944214704,4705,4706,4707,4708,4709,4710,4711,4712,4713,4714,4715,4716,4717,4718,
944224719,4720,4721,4722,4723,4724,4725,4726,4727,4728,4729,4730,4731,4732,4733,
944234734,4735,4736,4737,4738,4739,4740,4741,4742,4743,4744,4745,4746,4747,4748,
944244749,4750,4751,4752,4753,4754,4755,4756,4757,4758,4759,4760,4761,4762,4763,
944254764,4765,4766,4767,4768,4769,4770,4771,4772,4773,4774,4775,4776,4777,4778,
944264779,4780,4781,4782,4783,4784,4785,4786,4787,4788,4789,4790,4791,4792,4793,
944274794,4795,4796,4797,4798,4799,4800,4801,4802,4803,4804,4805,4806,4807,4808,
944284809,4810,4811,4812,4813,4814,4815,4816,4817,4818,4819,4820,4821,4822,4823,
944294824,4825,4826,4827,4828,4829,4830,4831,4832,4833,4834,4835,4836,4837,4838,
944304839,4840,4841,4842,4843,4844,4845,4846,4847,4848,4849,4850,4851,4852,4853,
944314854,4855,4856,4857,4858,4859,4860,4861,4862,4863,4864,4865,4866,4867,4868,
944324869,4870,4871,4872,4873,4874,4875,4876,4877,4878,4879,4880,4881,4882,4883,
944334884,4885,4886,4887,4888,4889,4890,4891,4892,4893,4894,4895,4896,4897,4898,
944344899,4900,4901,4902,4903,4904,4905,4906,4907,4908,4909,4910,4911,4912,4913,
944354914,4915,4916,4917,4918,4919,4920,4921,4922,4923,4924,4925,4926,4927,4928,
944364929,4930,4931,4932,4933,4934,4935,4936,4937,4938,4939,4940,4941,4942,4943,
944374944,4945,4946,4947,4948,4949,4950,4951,4952,4953,4954,4955,4956,4957,4958,
944384959,4960,4961,4962,4963,4964,4965,4966,4967,4968,4969,4970,4971,4972,4973,
944394974,4975,4976,4977,4978,4979,4980,4981,4982,4983,4984,4985,4986,4987,4988,
944404989,4990,4991,4992,4993,4994,4995,4996,4997,4998,4999,5000,5001,5002,5003,
944415004,5005,5006,5007,5008,5009,5010,5011,5012,5013,5014,5015,5016,5017,5018,
944425019,5020,5021,5022,5023,5024,5025,5026,5027,5028,5029,5030,5031,5032,5033,
944435034,5035,5036,5037,5038,5039,5040,5041,5042,5043,5044,5045,5046,5047,5048,
944445049,5050,5051,5052,5053,5054,5055,5056,5057,5058,5059,5060,5061,5062,5063,
944455064,5065,5066,5067,5068,5069,5070,5071,5072,5073,5074,5075,5076,5077,5078,
944465079,5080,5081,5082,5083,5084,5085,5086,5087,5088,5089,5090,5091,5092,5093,
944475094,5095,5096,5097,5098,5099,5100,5101,5102,5103,5104,5105,5106,5107,5108,
944485109,5110,5111,5104,5105,5106,5107,5108,5109,5118,5119,5120,5121,5122,5123,
944495124,5125,5126,5127,5128,5129,5130,5131,5132,5133,5134,5135,5136,5137,5138,
944505139,5140,5141,5142,5143,5144,5145,5146,5147,5148,5149,5150,5151,5152,5153,
944515154,5155,5156,5157,5158,5159,5160,5161,5162,5163,5164,5165,5166,5167,5168,
944525169,5170,5171,5172,5173,5174,5175,5176,5177,5178,5179,5180,5181,5182,5183,
944535184,5185,5186,5187,5188,5189,5190,5191,5192,5193,5194,5195,5196,5197,5198,
944545199,5200,5201,5202,5203,5204,5205,5206,5207,5208,5209,5210,5211,5212,5213,
944555214,5215,5216,5217,5218,5219,5220,5221,5222,5223,5224,5225,5226,5227,5228,
944565229,5230,5231,5232,5233,5234,5235,5236,5237,5238,5239,5240,5241,5242,5243,
944575244,5245,5246,5247,5248,5249,5250,5251,5252,5253,5254,5255,5256,5257,5258,
944585259,5260,5261,5262,5263,5264,5265,5266,5267,5268,5269,5270,5271,5272,5273,
944595274,5275,5276,5277,5278,5279,5280,5281,5282,5283,5284,5285,5286,5287,5288,
944605289,5290,5291,5292,5293,5294,5295,5296,5297,5298,5299,5300,5301,5302,5303,
944615304,5305,5306,5307,5308,5309,5310,5311,5312,5313,5314,5315,5316,5317,5318,
944625319,5320,5321,5322,5323,5324,5325,5326,5327,5328,5329,5330,5331,5332,5333,
944635334,5335,5336,5337,5338,5339,5340,5341,5342,5343,5344,5345,5346,5347,5348,
944645349,5350,5351,5352,5353,5354,5355,5356,5357,5358,5359,5360,5361,5362,5363,
944655364,5365,5366,5367,5368,5369,5370,5371,5372,5373,5374,5375,5376,5377,5378,
944665379,5380,5381,5382,5383,5384,5385,5386,5387,5388,5389,5390,5391,5392,5393,
944675394,5395,5396,5397,5398,5399,5400,5401,5402,5403,5404,5405,5406,5407,5408,
944685409,5410,5411,5412,5413,5414,5415,5416,5417,5418,5419,5420,5421,5422,5423,
944695424,5425,5426,5427,5428,5429,5430,5431,5432,5433,5434,5435,5436,5437,5438,
944705439,5440,5441,5442,5443,5444,5445,5446,5447,5448,5449,5450,5451,5452,5453,
944715454,5455,5456,5457,5458,5459,5460,5461,5462,5463,5464,5465,5466,5467,5468,
944725469,5470,5471,5472,5473,5474,5475,5476,5477,5478,5479,5480,5481,5482,5483,
944735484,5485,5486,5487,5488,5489,5490,5491,5492,5493,5494,5495,5496,5497,5498,
944745499,5500,5501,5502,5503,5504,5505,5506,5507,5508,5509,5510,5511,5512,5513,
944755514,5515,5516,5517,5518,5519,5520,5521,5522,5523,5524,5525,5526,5527,5528,
944765529,5530,5531,5532,5533,5534,5535,5536,5537,5538,5539,5540,5541,5542,5543,
944775544,5545,5546,5547,5548,5549,5550,5551,5552,5553,5554,5555,5556,5557,5558,
944785559,5560,5561,5562,5563,5564,5565,5566,5567,5568,5569,5570,5571,5572,5573,
944795574,5575,5576,5577,5578,5579,5580,5581,5582,5583,5584,5585,5586,5587,5588,
944805589,5590,5591,5592,5593,5594,5595,5596,5597,5598,5599,5600,5601,5602,5603,
944815604,5605,5606,5607,5608,5609,5610,5611,5612,5613,5614,5615,5616,5617,5618,
944825619,5620,5621,5622,5623,5624,5625,5626,5627,5628,5629,5630,5631,5632,5633,
944835634,5635,5636,5637,5638,5639,5640,5641,5642,5643,5644,5645,5646,5647,5648,
944845649,5650,5651,5652,5653,5654,5655,5656,5657,5658,5659,5660,5661,5662,5663,
944855664,5665,5666,5667,5668,5669,5670,5671,5672,5673,5674,5675,5676,5677,5678,
944865679,5680,5681,5682,5683,5684,5685,5686,5687,5688,5689,5690,5691,5692,5693,
944875694,5695,5696,5697,5698,5699,5700,5701,5702,5703,5704,5705,5706,5707,5708,
944885709,5710,5711,5712,5713,5714,5715,5716,5717,5718,5719,5720,5721,5722,5723,
944895724,5725,5726,5727,5728,5729,5730,5731,5732,5733,5734,5735,5736,5737,5738,
944905739,5740,5741,5742,5743,5744,5745,5746,5747,5748,5749,5750,5751,5752,5753,
944915754,5755,5756,5757,5758,5759,5760,5761,5762,5763,5764,5765,5766,5767,5768,
944925769,5770,5771,5772,5773,5774,5775,5776,5777,5778,5779,5780,5781,5782,5783,
944935784,5785,5786,5787,5788,5789,5790,5791,5792,5793,5794,5795,5796,5797,5798,
944945799,5800,5801,5802,5803,5804,5805,5806,5807,5808,5809,5810,5811,5812,5813,
944955814,5815,5816,5817,5818,5819,5820,5821,5822,5823,5824,5825,5826,5827,5828,
944965829,5830,5831,5832,5833,5834,5835,5836,5837,5838,5839,5840,5841,5842,5843,
944975844,5845,5846,5847,5848,5849,5850,5851,5852,5853,5854,5855,5856,5857,5858,
944985859,5860,5861,5862,5863,5864,5865,5866,5867,5868,5869,5870,5871,5872,5873,
944995874,5875,5876,5877,5878,5879,5880,5881,5882,5883,5884,5885,5886,5887,5888,
945005889,5890,5891,5892,5893,5894,5895,5896,5897,5898,5899,5900,5901,5902,5903,
945015904,5905,5906,5907,5908,5909,5910,5911,5912,5913,5914,5915,5916,5917,5918,
945025919,5920,5921,5922,5923,5924,5925,5926,5927,5928,5929,5930,5931,5932,5933,
945035934,5935,5936,5937,5938,5939,5940,5941,5942,5943,5944,5945,5946,5947,5948,
945045949,5950,5951,5952,5953,5954,5955,5956,5957,5958,5959,5960,5961,5962,5963,
945055964,5965,5966,5967,5968,5969,5970,5971,5972,5973,5974,5975,5976,5977,5978,
945065979,5980,5981,5982,5983,5984,5985,5986,5987,5988,5989,5990,5991,5992,5993,
945075994,5995,5996,5997,5998,5999,6000,6001,6002,6003,6004,6005,6006,6007,6008,
945086009,6010,6011,6012,6013,6014,6015,6016,6017,6018,6019,6020,6021,6022,6023,
945096024,6025,6026,6027,6028,6029,6030,6031,6032,6033,6034,6035,6036,6037,6038,
945106039,6040,6041,6042,6043,6044,6045,6046,6047,6048,6049,6050,6051,6052,6053,
945116054,6055,6056,6057,6058,6059,6060,6061,6062,6063,6064,6065,6066,6067,6068,
945126069,6070,6071,6072,6073,6074,6075,6076,6077,6078,6079,6080,6081,6082,6083,
945136084,6085,6086,6087,6088,6089,6090,6091,6092,6093,6094,6095,6096,6097,6098,
945146099,6100,6101,6102,6103,6104,6105,6106,6107,6108,6109,6110,6111,6112,6113,
945156114,6115,6116,6117,6118,6119,6120,6121,6122,6123,6124,6125,6126,6127,6128,
945166129,6130,6131,6132,6133,6134,6135,6136,6137,6138,6139,6140,6141,6142,6143,
945176144,6145,6146,6147,6148,6149,6150,6151,6152,6153,6154,6155,6156,6157,6158,
945186159,6160,6161,6162,6163,6164,6165,6166,6167,6168,6169,6170,6171,6172,6173,
945196174,6175,6176,6177,6178,6179,6180,6181,6182,6183,6184,6185,6186,6187,6188,
945206189,6190,6191,6192,6193,6194,6195,6196,6197,6198,6199,6200,6201,6202,6203,
945216204,6205,6206,6207,6208,6209,6210,6211,6212,6213,6214,6215,6216,6217,6218,
945226219,6220,6221,6222,6223,6224,6225,6226,6227,6228,6229,6230,6231,6232,6233,
945236234,6235,6236,6237,6238,6239,6240,6241,6242,6243,6244,6245,6246,6247,6248,
945246249,6250,6251,6252,6253,6254,6255,6256,6257,6258,6259,6260,6261,6262,6263,
945256264,6265,6266,6267,6268,6269,6270,6271,6272,6273,6274,6275,6276,6277,6278,
945266279,6280,6281,6282,6283,6284,6285,6286,6287,6288,6289,6290,6291,6292,6293,
945276294,6295,6296,6297,6298,6299,6300,6301,6302,6303,6304,6305,6306,6307,6308,
945286309,6310,6311,6312,6313,6314,6315,6316,6317,6318,6319,6320,6321,6322,6323,
945296324,6325,6326,6327,6328,6329,6330,6331,6332,6333,6334,6335,6336,6337,6338,
945306339,6340,6341,6342,6343,6344,6345,6346,6347,6348,6349,6350,6351,6352,6353,
945316354,6355,6356,6357,6358,6359,6360,6361,6362,6363,6364,6365,6366,6367,6368,
945326369,6370,6371,6372,6373,6374,6375,6376,6377,6378,6379,6380,6381,6382,6383,
945336384,6385,6386,6387,6388,6389,6390,6391,6392,6393,6394,6395,6396,6397,6398,
945346399,6400,6401,6402,6403,6404,6405,6406,6407,6408,6409,6410,6411,6412,6413,
945356414,6415,6416,6417,6418,6419,6420,6421,6422,6423,6424,6425,6426,6427,6428,
945366429,6430,6431,6432,6433,6434,6435,6436,6437,6438,6439,6440,6441,6442,6443,
945376444,6445,6446,6447,6448,6449,6450,6451,6452,6453,6454,6455,6456,6457,6458,
945386459,6460,6461,6462,6463,6464,6465,6466,6467,6468,6469,6470,6471,6472,6473,
945396474,6475,6476,6477,6478,6479,6480,6481,6482,6483,6484,6485,6486,6487,6488,
945406489,6490,6491,6492,6493,6494,6495,6496,6497,6498,6499,6500,6501,6502,6503,
945416504,6505,6506,6507,6508,6509,6510,6511,6512,6513,6514,6515,6516,6517,6518,
945426519,6520,6521,6522,6523,6524,6525,6526,6527,6528,6529,6530,6531,6532,6533,
945436534,6535,6536,6537,6538,6539,6540,6541,6542,6543,6544,6545,6546,6547,6548,
945446549,6550,6551,6552,6553,6554,6555,6556,6557,6558,6559,6560,6561,6562,6563,
945456564,6565,6566,6567,6568,6569,6570,6571,6572,6573,6574,6575,6576,6577,6578,
945466579,6580,6581,6582,6583,6584,6585,6586,6587,6588,6589,6590,6591,6592,6593,
945476594,6595,6596,6597,6598,6599,6600,6601,6602,6603,6604,6605,6606,6607,6608,
945486609,6610,6611,6612,6613,6614,6615,6616,6617,6618,6619,6620,6621,6622,6623,
945496624,6625,6626,6627,6628,6629,6630,6631,6632,6633,6634,6635,6636,6637,6638,
945506639,6640,6641,6642,6643,6644,6645,6646,6647,6648,6649,6650,6651,6652,6653,
945516654,6655,6656,6657,6658,6659,6660,6661,6662,6663,6664,6665,6666,6667,6668,
945526669,6670,6671,6672,6673,6674,6675,6676,6677,6678,6679,6680,6681,6682,6683,
945536684,6685,6686,6687,6688,6689,6690,6691,6692,6693,6694,6695,6696,6697,6698,
945546699,6700,6701,6702,6703,6704,6705,6706,6707,6708,6709,6710,6711,6712,6713,
945556714,6715,6716,6717,6718,6719,6720,6721,6722,6723,6724,6725,6726,6727,6728,
945566729,6730,6731,6732,6733,6734,6735,6736,6737,6738,6739,6740,6741,6742,6743,
945576744,6745,6746,6747,6748,6749,6750,6751,6752,6753,6754,6755,6756,6757,6758,
945586759,6760,6761,6762,6763,6764,6765,6766,6767,6768,6769,6770,6771,6772,6773,
945596774,6775,6776,6777,6778,6779,6780,6781,6782,6783,6784,6785,6786,6787,6788,
945606789,6790,6791,6792,6793,6794,6795,6796,6797,6798,6799,6800,6801,6802,6803,
945616804,6805,6806,6807,6808,6809,6810,6811,6812,6813,6814,6815,6816,6817,6818,
945626819,6820,6821,6822,6823,6824,6825,6826,6827,6828,6829,6830,6831,6832,6833,
945636834,6835,6836,6837,6838,6839,6840,6841,6842,6843,6844,6845,6846,6847,6848,
945646849,6850,6851,6852,6853,6854,6855,6856,6857,6858,6859,6860,6861,6862,6863,
945656864,6865,6866,6867,6868,6869,6870,6871,6872,6873,6874,6875,6876,6877,6878,
945666879,6880,6881,6882,6883,6884,6885,6886,6887,6888,6889,6890,6891,6892,6893,
945676894,6895,6896,6897,6898,6899,6900,6901,6902,6903,6904,6905,6906,6907,6908,
945686909,6910,6911,6912,6913,6914,6915,6916,6917,6918,6919,6920,6921,6922,6923,
945696924,6925,6926,6927,6928,6929,6930,6931,6932,6933,6934,6935,6936,6937,6938,
945706939,6940,6941,6942,6943,6944,6945,6946,6947,6948,6949,6950,6951,6952,6953,
945716954,6955,6956,6957,6958,6959,6960,6961,6962,6963,6964,6965,6966,6967,6968,
945726969,6970,6971,6972,6973,6974,6975,6976,6977,6978,6979,6980,6981,6982,6983,
945736984,6985,6986,6987,6988,6989,6990,6991,6992,6993,6994,6995,6996,6997,6998,
945746999,7000,7001,7002,7003,7004,7005,7006,7007,7008,7009,7010,7011,7012,7013,
945757014,7015,7016,7017,7018,7019,7020,7021,7022,7023,7024,7025,7026,7027,7028,
945767029,7030,7031,7032,7033,7034,7035,7036,7037,7038,7039,7040,7041,7042,7043,
945777044,7045,7046,7047,7048,7049,7050,7051,7052,7053,7054,7055,7056,7057,7058,
945787059,7060,7061,7062,7063,7064,7065,7066,7067,7068,7069,7070,7071,7072,7073,
945797074,7075,7076,7077,7078,7079,7080,7081,7082,7083,7084,7085,7086,7087,7088,
945807089,7090,7091,7092,7093,7094,7095,7096,7097,7098,7099,7100,7101,7102,7103,
945817104,7105,7106,7107,7108,7109,7110,7111,7112,7113,7114,7115,7116,7117,7118,
945827119,7120,7121,7122,7123,7124,7125,7126,7127,7128,7129,7130,7131,7132,7133,
945837134,7135,7136,7137,7138,7139,7140,7141,7142,7143,7144,7145,7146,7147,7148,
945847149,7150,7151,7152,7153,7154,7155,7156,7157,7158,7159,7160,7161,7162,7163,
945857164,7165,7166,7167,7168,7169,7170,7171,7172,7173,7174,7175,7176,7177,7178,
945867179,7180,7181,7182,7183,7184,7185,7186,7187,7188,7189,7190,7191,7192,7193,
945877194,7195,7196,7197,7198,7199,7200,7201,7202,7203,7204,7205,7206,7207,7208,
945887209,7210,7211,7212,7213,7214,7215,7216,7217,7218,7219,7220,7221,7222,7223,
945897224,7225,7226,7227,7228,7229,7230,7231,7232,7233,7234,7235,7236,7237,7238,
945907239,7240,7241,7242,7243,7244,7245,7246,7247,7248,7249,7250,7251,7252,7253,
945917254,7255,7256,7257,7258,7259,7260,7261,7262,7263,7264,7265,7266,7267,7268,
945927269,7270,7271,7272,7273,7274,7275,7276,7277,7278,7279,7280,7281,7282,7283,
945937284,7285,7286,7287,7288,7289,7290,7291,7292,7293,7294,7295,1042,1044,1054,
945941057,1058,1058,1066,1122,42570L,7305,7306,7307,7308,7309,7310,7311,7312,
945957313,7314,7315,7316,7317,7318,7319,7320,7321,7322,7323,7324,7325,7326,7327,
945967328,7329,7330,7331,7332,7333,7334,7335,7336,7337,7338,7339,7340,7341,7342,
945977343,7344,7345,7346,7347,7348,7349,7350,7351,7352,7353,7354,7355,7356,7357,
945987358,7359,7360,7361,7362,7363,7364,7365,7366,7367,7368,7369,7370,7371,7372,
945997373,7374,7375,7376,7377,7378,7379,7380,7381,7382,7383,7384,7385,7386,7387,
946007388,7389,7390,7391,7392,7393,7394,7395,7396,7397,7398,7399,7400,7401,7402,
946017403,7404,7405,7406,7407,7408,7409,7410,7411,7412,7413,7414,7415,7416,7417,
946027418,7419,7420,7421,7422,7423,7424,7425,7426,7427,7428,7429,7430,7431,7432,
946037433,7434,7435,7436,7437,7438,7439,7440,7441,7442,7443,7444,7445,7446,7447,
946047448,7449,7450,7451,7452,7453,7454,7455,7456,7457,7458,7459,7460,7461,7462,
946057463,7464,7465,7466,7467,7468,7469,7470,7471,7472,7473,7474,7475,7476,7477,
946067478,7479,7480,7481,7482,7483,7484,7485,7486,7487,7488,7489,7490,7491,7492,
946077493,7494,7495,7496,7497,7498,7499,7500,7501,7502,7503,7504,7505,7506,7507,
946087508,7509,7510,7511,7512,7513,7514,7515,7516,7517,7518,7519,7520,7521,7522,
946097523,7524,7525,7526,7527,7528,7529,7530,7531,7532,7533,7534,7535,7536,7537,
946107538,7539,7540,7541,7542,7543,7544,42877L,7546,7547,7548,11363,7550,7551,
946117552,7553,7554,7555,7556,7557,7558,7559,7560,7561,7562,7563,7564,7565,
9461242950L,7567,7568,7569,7570,7571,7572,7573,7574,7575,7576,7577,7578,7579,
946137580,7581,7582,7583,7584,7585,7586,7587,7588,7589,7590,7591,7592,7593,7594,
946147595,7596,7597,7598,7599,7600,7601,7602,7603,7604,7605,7606,7607,7608,7609,
946157610,7611,7612,7613,7614,7615,7616,7617,7618,7619,7620,7621,7622,7623,7624,
946167625,7626,7627,7628,7629,7630,7631,7632,7633,7634,7635,7636,7637,7638,7639,
946177640,7641,7642,7643,7644,7645,7646,7647,7648,7649,7650,7651,7652,7653,7654,
946187655,7656,7657,7658,7659,7660,7661,7662,7663,7664,7665,7666,7667,7668,7669,
946197670,7671,7672,7673,7674,7675,7676,7677,7678,7679,7680,7680,7682,7682,7684,
946207684,7686,7686,7688,7688,7690,7690,7692,7692,7694,7694,7696,7696,7698,7698,
946217700,7700,7702,7702,7704,7704,7706,7706,7708,7708,7710,7710,7712,7712,7714,
946227714,7716,7716,7718,7718,7720,7720,7722,7722,7724,7724,7726,7726,7728,7728,
946237730,7730,7732,7732,7734,7734,7736,7736,7738,7738,7740,7740,7742,7742,7744,
946247744,7746,7746,7748,7748,7750,7750,7752,7752,7754,7754,7756,7756,7758,7758,
946257760,7760,7762,7762,7764,7764,7766,7766,7768,7768,7770,7770,7772,7772,7774,
946267774,7776,7776,7778,7778,7780,7780,7782,7782,7784,7784,7786,7786,7788,7788,
946277790,7790,7792,7792,7794,7794,7796,7796,7798,7798,7800,7800,7802,7802,7804,
946287804,7806,7806,7808,7808,7810,7810,7812,7812,7814,7814,7816,7816,7818,7818,
946297820,7820,7822,7822,7824,7824,7826,7826,7828,7828,7830,7831,7832,7833,7834,
946307776,7836,7837,7838,7839,7840,7840,7842,7842,7844,7844,7846,7846,7848,7848,
946317850,7850,7852,7852,7854,7854,7856,7856,7858,7858,7860,7860,7862,7862,7864,
946327864,7866,7866,7868,7868,7870,7870,7872,7872,7874,7874,7876,7876,7878,7878,
946337880,7880,7882,7882,7884,7884,7886,7886,7888,7888,7890,7890,7892,7892,7894,
946347894,7896,7896,7898,7898,7900,7900,7902,7902,7904,7904,7906,7906,7908,7908,
946357910,7910,7912,7912,7914,7914,7916,7916,7918,7918,7920,7920,7922,7922,7924,
946367924,7926,7926,7928,7928,7930,7930,7932,7932,7934,7934,7944,7945,7946,7947,
946377948,7949,7950,7951,7944,7945,7946,7947,7948,7949,7950,7951,7960,7961,7962,
946387963,7964,7965,7958,7959,7960,7961,7962,7963,7964,7965,7966,7967,7976,7977,
946397978,7979,7980,7981,7982,7983,7976,7977,7978,7979,7980,7981,7982,7983,7992,
946407993,7994,7995,7996,7997,7998,7999,7992,7993,7994,7995,7996,7997,7998,7999,
946418008,8009,8010,8011,8012,8013,8006,8007,8008,8009,8010,8011,8012,8013,8014,
946428015,8016,8025,8018,8027,8020,8029,8022,8031,8024,8025,8026,8027,8028,8029,
946438030,8031,8040,8041,8042,8043,8044,8045,8046,8047,8040,8041,8042,8043,8044,
946448045,8046,8047,8122,8123,8136,8137,8138,8139,8154,8155,8184,8185,8170,8171,
946458186,8187,8062,8063,8064,8065,8066,8067,8068,8069,8070,8071,8072,8073,8074,
946468075,8076,8077,8078,8079,8080,8081,8082,8083,8084,8085,8086,8087,8088,8089,
946478090,8091,8092,8093,8094,8095,8096,8097,8098,8099,8100,8101,8102,8103,8104,
946488105,8106,8107,8108,8109,8110,8111,8120,8121,8114,8115,8116,8117,8118,8119,
946498120,8121,8122,8123,8124,8125,921,8127,8128,8129,8130,8131,8132,8133,8134,
946508135,8136,8137,8138,8139,8140,8141,8142,8143,8152,8153,8146,8147,8148,8149,
946518150,8151,8152,8153,8154,8155,8156,8157,8158,8159,8168,8169,8162,8163,8164,
946528172,8166,8167,8168,8169,8170,8171,8172,8173,8174,8175,8176,8177,8178,8179,
946538180,8181,8182,8183,8184,8185,8186,8187,8188,8189,8190,8191,8192,8193,8194,
946548195,8196,8197,8198,8199,8200,8201,8202,8203,8204,8205,8206,8207,8208,8209,
946558210,8211,8212,8213,8214,8215,8216,8217,8218,8219,8220,8221,8222,8223,8224,
946568225,8226,8227,8228,8229,8230,8231,8232,8233,8234,8235,8236,8237,8238,8239,
946578240,8241,8242,8243,8244,8245,8246,8247,8248,8249,8250,8251,8252,8253,8254,
946588255,8256,8257,8258,8259,8260,8261,8262,8263,8264,8265,8266,8267,8268,8269,
946598270,8271,8272,8273,8274,8275,8276,8277,8278,8279,8280,8281,8282,8283,8284,
946608285,8286,8287,8288,8289,8290,8291,8292,8293,8294,8295,8296,8297,8298,8299,
946618300,8301,8302,8303,8304,8305,8306,8307,8308,8309,8310,8311,8312,8313,8314,
946628315,8316,8317,8318,8319,8320,8321,8322,8323,8324,8325,8326,8327,8328,8329,
946638330,8331,8332,8333,8334,8335,8336,8337,8338,8339,8340,8341,8342,8343,8344,
946648345,8346,8347,8348,8349,8350,8351,8352,8353,8354,8355,8356,8357,8358,8359,
946658360,8361,8362,8363,8364,8365,8366,8367,8368,8369,8370,8371,8372,8373,8374,
946668375,8376,8377,8378,8379,8380,8381,8382,8383,8384,8385,8386,8387,8388,8389,
946678390,8391,8392,8393,8394,8395,8396,8397,8398,8399,8400,8401,8402,8403,8404,
946688405,8406,8407,8408,8409,8410,8411,8412,8413,8414,8415,8416,8417,8418,8419,
946698420,8421,8422,8423,8424,8425,8426,8427,8428,8429,8430,8431,8432,8433,8434,
946708435,8436,8437,8438,8439,8440,8441,8442,8443,8444,8445,8446,8447,8448,8449,
946718450,8451,8452,8453,8454,8455,8456,8457,8458,8459,8460,8461,8462,8463,8464,
946728465,8466,8467,8468,8469,8470,8471,8472,8473,8474,8475,8476,8477,8478,8479,
946738480,8481,8482,8483,8484,8485,8486,8487,8488,8489,8490,8491,8492,8493,8494,
946748495,8496,8497,8498,8499,8500,8501,8502,8503,8504,8505,8506,8507,8508,8509,
946758510,8511,8512,8513,8514,8515,8516,8517,8518,8519,8520,8521,8522,8523,8524,
946768525,8498,8527,8528,8529,8530,8531,8532,8533,8534,8535,8536,8537,8538,8539,
946778540,8541,8542,8543,8544,8545,8546,8547,8548,8549,8550,8551,8552,8553,8554,
946788555,8556,8557,8558,8559,8544,8545,8546,8547,8548,8549,8550,8551,8552,8553,
946798554,8555,8556,8557,8558,8559,8576,8577,8578,8579,8579,8581,8582,8583,8584,
946808585,8586,8587,8588,8589,8590,8591,8592,8593,8594,8595,8596,8597,8598,8599,
946818600,8601,8602,8603,8604,8605,8606,8607,8608,8609,8610,8611,8612,8613,8614,
946828615,8616,8617,8618,8619,8620,8621,8622,8623,8624,8625,8626,8627,8628,8629,
946838630,8631,8632,8633,8634,8635,8636,8637,8638,8639,8640,8641,8642,8643,8644,
946848645,8646,8647,8648,8649,8650,8651,8652,8653,8654,8655,8656,8657,8658,8659,
946858660,8661,8662,8663,8664,8665,8666,8667,8668,8669,8670,8671,8672,8673,8674,
946868675,8676,8677,8678,8679,8680,8681,8682,8683,8684,8685,8686,8687,8688,8689,
946878690,8691,8692,8693,8694,8695,8696,8697,8698,8699,8700,8701,8702,8703,8704,
946888705,8706,8707,8708,8709,8710,8711,8712,8713,8714,8715,8716,8717,8718,8719,
946898720,8721,8722,8723,8724,8725,8726,8727,8728,8729,8730,8731,8732,8733,8734,
946908735,8736,8737,8738,8739,8740,8741,8742,8743,8744,8745,8746,8747,8748,8749,
946918750,8751,8752,8753,8754,8755,8756,8757,8758,8759,8760,8761,8762,8763,8764,
946928765,8766,8767,8768,8769,8770,8771,8772,8773,8774,8775,8776,8777,8778,8779,
946938780,8781,8782,8783,8784,8785,8786,8787,8788,8789,8790,8791,8792,8793,8794,
946948795,8796,8797,8798,8799,8800,8801,8802,8803,8804,8805,8806,8807,8808,8809,
946958810,8811,8812,8813,8814,8815,8816,8817,8818,8819,8820,8821,8822,8823,8824,
946968825,8826,8827,8828,8829,8830,8831,8832,8833,8834,8835,8836,8837,8838,8839,
946978840,8841,8842,8843,8844,8845,8846,8847,8848,8849,8850,8851,8852,8853,8854,
946988855,8856,8857,8858,8859,8860,8861,8862,8863,8864,8865,8866,8867,8868,8869,
946998870,8871,8872,8873,8874,8875,8876,8877,8878,8879,8880,8881,8882,8883,8884,
947008885,8886,8887,8888,8889,8890,8891,8892,8893,8894,8895,8896,8897,8898,8899,
947018900,8901,8902,8903,8904,8905,8906,8907,8908,8909,8910,8911,8912,8913,8914,
947028915,8916,8917,8918,8919,8920,8921,8922,8923,8924,8925,8926,8927,8928,8929,
947038930,8931,8932,8933,8934,8935,8936,8937,8938,8939,8940,8941,8942,8943,8944,
947048945,8946,8947,8948,8949,8950,8951,8952,8953,8954,8955,8956,8957,8958,8959,
947058960,8961,8962,8963,8964,8965,8966,8967,8968,8969,8970,8971,8972,8973,8974,
947068975,8976,8977,8978,8979,8980,8981,8982,8983,8984,8985,8986,8987,8988,8989,
947078990,8991,8992,8993,8994,8995,8996,8997,8998,8999,9000,9001,9002,9003,9004,
947089005,9006,9007,9008,9009,9010,9011,9012,9013,9014,9015,9016,9017,9018,9019,
947099020,9021,9022,9023,9024,9025,9026,9027,9028,9029,9030,9031,9032,9033,9034,
947109035,9036,9037,9038,9039,9040,9041,9042,9043,9044,9045,9046,9047,9048,9049,
947119050,9051,9052,9053,9054,9055,9056,9057,9058,9059,9060,9061,9062,9063,9064,
947129065,9066,9067,9068,9069,9070,9071,9072,9073,9074,9075,9076,9077,9078,9079,
947139080,9081,9082,9083,9084,9085,9086,9087,9088,9089,9090,9091,9092,9093,9094,
947149095,9096,9097,9098,9099,9100,9101,9102,9103,9104,9105,9106,9107,9108,9109,
947159110,9111,9112,9113,9114,9115,9116,9117,9118,9119,9120,9121,9122,9123,9124,
947169125,9126,9127,9128,9129,9130,9131,9132,9133,9134,9135,9136,9137,9138,9139,
947179140,9141,9142,9143,9144,9145,9146,9147,9148,9149,9150,9151,9152,9153,9154,
947189155,9156,9157,9158,9159,9160,9161,9162,9163,9164,9165,9166,9167,9168,9169,
947199170,9171,9172,9173,9174,9175,9176,9177,9178,9179,9180,9181,9182,9183,9184,
947209185,9186,9187,9188,9189,9190,9191,9192,9193,9194,9195,9196,9197,9198,9199,
947219200,9201,9202,9203,9204,9205,9206,9207,9208,9209,9210,9211,9212,9213,9214,
947229215,9216,9217,9218,9219,9220,9221,9222,9223,9224,9225,9226,9227,9228,9229,
947239230,9231,9232,9233,9234,9235,9236,9237,9238,9239,9240,9241,9242,9243,9244,
947249245,9246,9247,9248,9249,9250,9251,9252,9253,9254,9255,9256,9257,9258,9259,
947259260,9261,9262,9263,9264,9265,9266,9267,9268,9269,9270,9271,9272,9273,9274,
947269275,9276,9277,9278,9279,9280,9281,9282,9283,9284,9285,9286,9287,9288,9289,
947279290,9291,9292,9293,9294,9295,9296,9297,9298,9299,9300,9301,9302,9303,9304,
947289305,9306,9307,9308,9309,9310,9311,9312,9313,9314,9315,9316,9317,9318,9319,
947299320,9321,9322,9323,9324,9325,9326,9327,9328,9329,9330,9331,9332,9333,9334,
947309335,9336,9337,9338,9339,9340,9341,9342,9343,9344,9345,9346,9347,9348,9349,
947319350,9351,9352,9353,9354,9355,9356,9357,9358,9359,9360,9361,9362,9363,9364,
947329365,9366,9367,9368,9369,9370,9371,9372,9373,9374,9375,9376,9377,9378,9379,
947339380,9381,9382,9383,9384,9385,9386,9387,9388,9389,9390,9391,9392,9393,9394,
947349395,9396,9397,9398,9399,9400,9401,9402,9403,9404,9405,9406,9407,9408,9409,
947359410,9411,9412,9413,9414,9415,9416,9417,9418,9419,9420,9421,9422,9423,9398,
947369399,9400,9401,9402,9403,9404,9405,9406,9407,9408,9409,9410,9411,9412,9413,
947379414,9415,9416,9417,9418,9419,9420,9421,9422,9423,9450,9451,9452,9453,9454,
947389455,9456,9457,9458,9459,9460,9461,9462,9463,9464,9465,9466,9467,9468,9469,
947399470,9471,9472,9473,9474,9475,9476,9477,9478,9479,9480,9481,9482,9483,9484,
947409485,9486,9487,9488,9489,9490,9491,9492,9493,9494,9495,9496,9497,9498,9499,
947419500,9501,9502,9503,9504,9505,9506,9507,9508,9509,9510,9511,9512,9513,9514,
947429515,9516,9517,9518,9519,9520,9521,9522,9523,9524,9525,9526,9527,9528,9529,
947439530,9531,9532,9533,9534,9535,9536,9537,9538,9539,9540,9541,9542,9543,9544,
947449545,9546,9547,9548,9549,9550,9551,9552,9553,9554,9555,9556,9557,9558,9559,
947459560,9561,9562,9563,9564,9565,9566,9567,9568,9569,9570,9571,9572,9573,9574,
947469575,9576,9577,9578,9579,9580,9581,9582,9583,9584,9585,9586,9587,9588,9589,
947479590,9591,9592,9593,9594,9595,9596,9597,9598,9599,9600,9601,9602,9603,9604,
947489605,9606,9607,9608,9609,9610,9611,9612,9613,9614,9615,9616,9617,9618,9619,
947499620,9621,9622,9623,9624,9625,9626,9627,9628,9629,9630,9631,9632,9633,9634,
947509635,9636,9637,9638,9639,9640,9641,9642,9643,9644,9645,9646,9647,9648,9649,
947519650,9651,9652,9653,9654,9655,9656,9657,9658,9659,9660,9661,9662,9663,9664,
947529665,9666,9667,9668,9669,9670,9671,9672,9673,9674,9675,9676,9677,9678,9679,
947539680,9681,9682,9683,9684,9685,9686,9687,9688,9689,9690,9691,9692,9693,9694,
947549695,9696,9697,9698,9699,9700,9701,9702,9703,9704,9705,9706,9707,9708,9709,
947559710,9711,9712,9713,9714,9715,9716,9717,9718,9719,9720,9721,9722,9723,9724,
947569725,9726,9727,9728,9729,9730,9731,9732,9733,9734,9735,9736,9737,9738,9739,
947579740,9741,9742,9743,9744,9745,9746,9747,9748,9749,9750,9751,9752,9753,9754,
947589755,9756,9757,9758,9759,9760,9761,9762,9763,9764,9765,9766,9767,9768,9769,
947599770,9771,9772,9773,9774,9775,9776,9777,9778,9779,9780,9781,9782,9783,9784,
947609785,9786,9787,9788,9789,9790,9791,9792,9793,9794,9795,9796,9797,9798,9799,
947619800,9801,9802,9803,9804,9805,9806,9807,9808,9809,9810,9811,9812,9813,9814,
947629815,9816,9817,9818,9819,9820,9821,9822,9823,9824,9825,9826,9827,9828,9829,
947639830,9831,9832,9833,9834,9835,9836,9837,9838,9839,9840,9841,9842,9843,9844,
947649845,9846,9847,9848,9849,9850,9851,9852,9853,9854,9855,9856,9857,9858,9859,
947659860,9861,9862,9863,9864,9865,9866,9867,9868,9869,9870,9871,9872,9873,9874,
947669875,9876,9877,9878,9879,9880,9881,9882,9883,9884,9885,9886,9887,9888,9889,
947679890,9891,9892,9893,9894,9895,9896,9897,9898,9899,9900,9901,9902,9903,9904,
947689905,9906,9907,9908,9909,9910,9911,9912,9913,9914,9915,9916,9917,9918,9919,
947699920,9921,9922,9923,9924,9925,9926,9927,9928,9929,9930,9931,9932,9933,9934,
947709935,9936,9937,9938,9939,9940,9941,9942,9943,9944,9945,9946,9947,9948,9949,
947719950,9951,9952,9953,9954,9955,9956,9957,9958,9959,9960,9961,9962,9963,9964,
947729965,9966,9967,9968,9969,9970,9971,9972,9973,9974,9975,9976,9977,9978,9979,
947739980,9981,9982,9983,9984,9985,9986,9987,9988,9989,9990,9991,9992,9993,9994,
947749995,9996,9997,9998,9999,10000,10001,10002,10003,10004,10005,10006,10007,
9477510008,10009,10010,10011,10012,10013,10014,10015,10016,10017,10018,10019,
9477610020,10021,10022,10023,10024,10025,10026,10027,10028,10029,10030,10031,
9477710032,10033,10034,10035,10036,10037,10038,10039,10040,10041,10042,10043,
9477810044,10045,10046,10047,10048,10049,10050,10051,10052,10053,10054,10055,
9477910056,10057,10058,10059,10060,10061,10062,10063,10064,10065,10066,10067,
9478010068,10069,10070,10071,10072,10073,10074,10075,10076,10077,10078,10079,
9478110080,10081,10082,10083,10084,10085,10086,10087,10088,10089,10090,10091,
9478210092,10093,10094,10095,10096,10097,10098,10099,10100,10101,10102,10103,
9478310104,10105,10106,10107,10108,10109,10110,10111,10112,10113,10114,10115,
9478410116,10117,10118,10119,10120,10121,10122,10123,10124,10125,10126,10127,
9478510128,10129,10130,10131,10132,10133,10134,10135,10136,10137,10138,10139,
9478610140,10141,10142,10143,10144,10145,10146,10147,10148,10149,10150,10151,
9478710152,10153,10154,10155,10156,10157,10158,10159,10160,10161,10162,10163,
9478810164,10165,10166,10167,10168,10169,10170,10171,10172,10173,10174,10175,
9478910176,10177,10178,10179,10180,10181,10182,10183,10184,10185,10186,10187,
9479010188,10189,10190,10191,10192,10193,10194,10195,10196,10197,10198,10199,
9479110200,10201,10202,10203,10204,10205,10206,10207,10208,10209,10210,10211,
9479210212,10213,10214,10215,10216,10217,10218,10219,10220,10221,10222,10223,
9479310224,10225,10226,10227,10228,10229,10230,10231,10232,10233,10234,10235,
9479410236,10237,10238,10239,10240,10241,10242,10243,10244,10245,10246,10247,
9479510248,10249,10250,10251,10252,10253,10254,10255,10256,10257,10258,10259,
9479610260,10261,10262,10263,10264,10265,10266,10267,10268,10269,10270,10271,
9479710272,10273,10274,10275,10276,10277,10278,10279,10280,10281,10282,10283,
9479810284,10285,10286,10287,10288,10289,10290,10291,10292,10293,10294,10295,
9479910296,10297,10298,10299,10300,10301,10302,10303,10304,10305,10306,10307,
9480010308,10309,10310,10311,10312,10313,10314,10315,10316,10317,10318,10319,
9480110320,10321,10322,10323,10324,10325,10326,10327,10328,10329,10330,10331,
9480210332,10333,10334,10335,10336,10337,10338,10339,10340,10341,10342,10343,
9480310344,10345,10346,10347,10348,10349,10350,10351,10352,10353,10354,10355,
9480410356,10357,10358,10359,10360,10361,10362,10363,10364,10365,10366,10367,
9480510368,10369,10370,10371,10372,10373,10374,10375,10376,10377,10378,10379,
9480610380,10381,10382,10383,10384,10385,10386,10387,10388,10389,10390,10391,
9480710392,10393,10394,10395,10396,10397,10398,10399,10400,10401,10402,10403,
9480810404,10405,10406,10407,10408,10409,10410,10411,10412,10413,10414,10415,
9480910416,10417,10418,10419,10420,10421,10422,10423,10424,10425,10426,10427,
9481010428,10429,10430,10431,10432,10433,10434,10435,10436,10437,10438,10439,
9481110440,10441,10442,10443,10444,10445,10446,10447,10448,10449,10450,10451,
9481210452,10453,10454,10455,10456,10457,10458,10459,10460,10461,10462,10463,
9481310464,10465,10466,10467,10468,10469,10470,10471,10472,10473,10474,10475,
9481410476,10477,10478,10479,10480,10481,10482,10483,10484,10485,10486,10487,
9481510488,10489,10490,10491,10492,10493,10494,10495,10496,10497,10498,10499,
9481610500,10501,10502,10503,10504,10505,10506,10507,10508,10509,10510,10511,
9481710512,10513,10514,10515,10516,10517,10518,10519,10520,10521,10522,10523,
9481810524,10525,10526,10527,10528,10529,10530,10531,10532,10533,10534,10535,
9481910536,10537,10538,10539,10540,10541,10542,10543,10544,10545,10546,10547,
9482010548,10549,10550,10551,10552,10553,10554,10555,10556,10557,10558,10559,
9482110560,10561,10562,10563,10564,10565,10566,10567,10568,10569,10570,10571,
9482210572,10573,10574,10575,10576,10577,10578,10579,10580,10581,10582,10583,
9482310584,10585,10586,10587,10588,10589,10590,10591,10592,10593,10594,10595,
9482410596,10597,10598,10599,10600,10601,10602,10603,10604,10605,10606,10607,
9482510608,10609,10610,10611,10612,10613,10614,10615,10616,10617,10618,10619,
9482610620,10621,10622,10623,10624,10625,10626,10627,10628,10629,10630,10631,
9482710632,10633,10634,10635,10636,10637,10638,10639,10640,10641,10642,10643,
9482810644,10645,10646,10647,10648,10649,10650,10651,10652,10653,10654,10655,
9482910656,10657,10658,10659,10660,10661,10662,10663,10664,10665,10666,10667,
9483010668,10669,10670,10671,10672,10673,10674,10675,10676,10677,10678,10679,
9483110680,10681,10682,10683,10684,10685,10686,10687,10688,10689,10690,10691,
9483210692,10693,10694,10695,10696,10697,10698,10699,10700,10701,10702,10703,
9483310704,10705,10706,10707,10708,10709,10710,10711,10712,10713,10714,10715,
9483410716,10717,10718,10719,10720,10721,10722,10723,10724,10725,10726,10727,
9483510728,10729,10730,10731,10732,10733,10734,10735,10736,10737,10738,10739,
9483610740,10741,10742,10743,10744,10745,10746,10747,10748,10749,10750,10751,
9483710752,10753,10754,10755,10756,10757,10758,10759,10760,10761,10762,10763,
9483810764,10765,10766,10767,10768,10769,10770,10771,10772,10773,10774,10775,
9483910776,10777,10778,10779,10780,10781,10782,10783,10784,10785,10786,10787,
9484010788,10789,10790,10791,10792,10793,10794,10795,10796,10797,10798,10799,
9484110800,10801,10802,10803,10804,10805,10806,10807,10808,10809,10810,10811,
9484210812,10813,10814,10815,10816,10817,10818,10819,10820,10821,10822,10823,
9484310824,10825,10826,10827,10828,10829,10830,10831,10832,10833,10834,10835,
9484410836,10837,10838,10839,10840,10841,10842,10843,10844,10845,10846,10847,
9484510848,10849,10850,10851,10852,10853,10854,10855,10856,10857,10858,10859,
9484610860,10861,10862,10863,10864,10865,10866,10867,10868,10869,10870,10871,
9484710872,10873,10874,10875,10876,10877,10878,10879,10880,10881,10882,10883,
9484810884,10885,10886,10887,10888,10889,10890,10891,10892,10893,10894,10895,
9484910896,10897,10898,10899,10900,10901,10902,10903,10904,10905,10906,10907,
9485010908,10909,10910,10911,10912,10913,10914,10915,10916,10917,10918,10919,
9485110920,10921,10922,10923,10924,10925,10926,10927,10928,10929,10930,10931,
9485210932,10933,10934,10935,10936,10937,10938,10939,10940,10941,10942,10943,
9485310944,10945,10946,10947,10948,10949,10950,10951,10952,10953,10954,10955,
9485410956,10957,10958,10959,10960,10961,10962,10963,10964,10965,10966,10967,
9485510968,10969,10970,10971,10972,10973,10974,10975,10976,10977,10978,10979,
9485610980,10981,10982,10983,10984,10985,10986,10987,10988,10989,10990,10991,
9485710992,10993,10994,10995,10996,10997,10998,10999,11000,11001,11002,11003,
9485811004,11005,11006,11007,11008,11009,11010,11011,11012,11013,11014,11015,
9485911016,11017,11018,11019,11020,11021,11022,11023,11024,11025,11026,11027,
9486011028,11029,11030,11031,11032,11033,11034,11035,11036,11037,11038,11039,
9486111040,11041,11042,11043,11044,11045,11046,11047,11048,11049,11050,11051,
9486211052,11053,11054,11055,11056,11057,11058,11059,11060,11061,11062,11063,
9486311064,11065,11066,11067,11068,11069,11070,11071,11072,11073,11074,11075,
9486411076,11077,11078,11079,11080,11081,11082,11083,11084,11085,11086,11087,
9486511088,11089,11090,11091,11092,11093,11094,11095,11096,11097,11098,11099,
9486611100,11101,11102,11103,11104,11105,11106,11107,11108,11109,11110,11111,
9486711112,11113,11114,11115,11116,11117,11118,11119,11120,11121,11122,11123,
9486811124,11125,11126,11127,11128,11129,11130,11131,11132,11133,11134,11135,
9486911136,11137,11138,11139,11140,11141,11142,11143,11144,11145,11146,11147,
9487011148,11149,11150,11151,11152,11153,11154,11155,11156,11157,11158,11159,
9487111160,11161,11162,11163,11164,11165,11166,11167,11168,11169,11170,11171,
9487211172,11173,11174,11175,11176,11177,11178,11179,11180,11181,11182,11183,
9487311184,11185,11186,11187,11188,11189,11190,11191,11192,11193,11194,11195,
9487411196,11197,11198,11199,11200,11201,11202,11203,11204,11205,11206,11207,
9487511208,11209,11210,11211,11212,11213,11214,11215,11216,11217,11218,11219,
9487611220,11221,11222,11223,11224,11225,11226,11227,11228,11229,11230,11231,
9487711232,11233,11234,11235,11236,11237,11238,11239,11240,11241,11242,11243,
9487811244,11245,11246,11247,11248,11249,11250,11251,11252,11253,11254,11255,
9487911256,11257,11258,11259,11260,11261,11262,11263,11264,11265,11266,11267,
9488011268,11269,11270,11271,11272,11273,11274,11275,11276,11277,11278,11279,
9488111280,11281,11282,11283,11284,11285,11286,11287,11288,11289,11290,11291,
9488211292,11293,11294,11295,11296,11297,11298,11299,11300,11301,11302,11303,
9488311304,11305,11306,11307,11308,11309,11310,11311,11264,11265,11266,11267,
9488411268,11269,11270,11271,11272,11273,11274,11275,11276,11277,11278,11279,
9488511280,11281,11282,11283,11284,11285,11286,11287,11288,11289,11290,11291,
9488611292,11293,11294,11295,11296,11297,11298,11299,11300,11301,11302,11303,
9488711304,11305,11306,11307,11308,11309,11310,11359,11360,11360,11362,11363,
9488811364,570,574,11367,11367,11369,11369,11371,11371,11373,11374,11375,11376,
9488911377,11378,11378,11380,11381,11381,11383,11384,11385,11386,11387,11388,
9489011389,11390,11391,11392,11392,11394,11394,11396,11396,11398,11398,11400,
9489111400,11402,11402,11404,11404,11406,11406,11408,11408,11410,11410,11412,
9489211412,11414,11414,11416,11416,11418,11418,11420,11420,11422,11422,11424,
9489311424,11426,11426,11428,11428,11430,11430,11432,11432,11434,11434,11436,
9489411436,11438,11438,11440,11440,11442,11442,11444,11444,11446,11446,11448,
9489511448,11450,11450,11452,11452,11454,11454,11456,11456,11458,11458,11460,
9489611460,11462,11462,11464,11464,11466,11466,11468,11468,11470,11470,11472,
9489711472,11474,11474,11476,11476,11478,11478,11480,11480,11482,11482,11484,
9489811484,11486,11486,11488,11488,11490,11490,11492,11493,11494,11495,11496,
9489911497,11498,11499,11499,11501,11501,11503,11504,11505,11506,11506,11508,
9490011509,11510,11511,11512,11513,11514,11515,11516,11517,11518,11519,4256,
949014257,4258,4259,4260,4261,4262,4263,4264,4265,4266,4267,4268,4269,4270,4271,
949024272,4273,4274,4275,4276,4277,4278,4279,4280,4281,4282,4283,4284,4285,4286,
949034287,4288,4289,4290,4291,4292,4293,11558,4295,11560,11561,11562,11563,
9490411564,4301,11566,11567,11568,11569,11570,11571,11572,11573,11574,11575,
9490511576,11577,11578,11579,11580,11581,11582,11583,11584,11585,11586,11587,
9490611588,11589,11590,11591,11592,11593,11594,11595,11596,11597,11598,11599,
9490711600,11601,11602,11603,11604,11605,11606,11607,11608,11609,11610,11611,
9490811612,11613,11614,11615,11616,11617,11618,11619,11620,11621,11622,11623,
9490911624,11625,11626,11627,11628,11629,11630,11631,11632,11633,11634,11635,
9491011636,11637,11638,11639,11640,11641,11642,11643,11644,11645,11646,11647,
9491111648,11649,11650,11651,11652,11653,11654,11655,11656,11657,11658,11659,
9491211660,11661,11662,11663,11664,11665,11666,11667,11668,11669,11670,11671,
9491311672,11673,11674,11675,11676,11677,11678,11679,11680,11681,11682,11683,
9491411684,11685,11686,11687,11688,11689,11690,11691,11692,11693,11694,11695,
9491511696,11697,11698,11699,11700,11701,11702,11703,11704,11705,11706,11707,
9491611708,11709,11710,11711,11712,11713,11714,11715,11716,11717,11718,11719,
9491711720,11721,11722,11723,11724,11725,11726,11727,11728,11729,11730,11731,
9491811732,11733,11734,11735,11736,11737,11738,11739,11740,11741,11742,11743,
9491911744,11745,11746,11747,11748,11749,11750,11751,11752,11753,11754,11755,
9492011756,11757,11758,11759,11760,11761,11762,11763,11764,11765,11766,11767,
9492111768,11769,11770,11771,11772,11773,11774,11775,11776,11777,11778,11779,
9492211780,11781,11782,11783,11784,11785,11786,11787,11788,11789,11790,11791,
9492311792,11793,11794,11795,11796,11797,11798,11799,11800,11801,11802,11803,
9492411804,11805,11806,11807,11808,11809,11810,11811,11812,11813,11814,11815,
9492511816,11817,11818,11819,11820,11821,11822,11823,11824,11825,11826,11827,
9492611828,11829,11830,11831,11832,11833,11834,11835,11836,11837,11838,11839,
9492711840,11841,11842,11843,11844,11845,11846,11847,11848,11849,11850,11851,
9492811852,11853,11854,11855,11856,11857,11858,11859,11860,11861,11862,11863,
9492911864,11865,11866,11867,11868,11869,11870,11871,11872,11873,11874,11875,
9493011876,11877,11878,11879,11880,11881,11882,11883,11884,11885,11886,11887,
9493111888,11889,11890,11891,11892,11893,11894,11895,11896,11897,11898,11899,
9493211900,11901,11902,11903,11904,11905,11906,11907,11908,11909,11910,11911,
9493311912,11913,11914,11915,11916,11917,11918,11919,11920,11921,11922,11923,
9493411924,11925,11926,11927,11928,11929,11930,11931,11932,11933,11934,11935,
9493511936,11937,11938,11939,11940,11941,11942,11943,11944,11945,11946,11947,
9493611948,11949,11950,11951,11952,11953,11954,11955,11956,11957,11958,11959,
9493711960,11961,11962,11963,11964,11965,11966,11967,11968,11969,11970,11971,
9493811972,11973,11974,11975,11976,11977,11978,11979,11980,11981,11982,11983,
9493911984,11985,11986,11987,11988,11989,11990,11991,11992,11993,11994,11995,
9494011996,11997,11998,11999,12000,12001,12002,12003,12004,12005,12006,12007,
9494112008,12009,12010,12011,12012,12013,12014,12015,12016,12017,12018,12019,
9494212020,12021,12022,12023,12024,12025,12026,12027,12028,12029,12030,12031,
9494312032,12033,12034,12035,12036,12037,12038,12039,12040,12041,12042,12043,
9494412044,12045,12046,12047,12048,12049,12050,12051,12052,12053,12054,12055,
9494512056,12057,12058,12059,12060,12061,12062,12063,12064,12065,12066,12067,
9494612068,12069,12070,12071,12072,12073,12074,12075,12076,12077,12078,12079,
9494712080,12081,12082,12083,12084,12085,12086,12087,12088,12089,12090,12091,
9494812092,12093,12094,12095,12096,12097,12098,12099,12100,12101,12102,12103,
9494912104,12105,12106,12107,12108,12109,12110,12111,12112,12113,12114,12115,
9495012116,12117,12118,12119,12120,12121,12122,12123,12124,12125,12126,12127,
9495112128,12129,12130,12131,12132,12133,12134,12135,12136,12137,12138,12139,
9495212140,12141,12142,12143,12144,12145,12146,12147,12148,12149,12150,12151,
9495312152,12153,12154,12155,12156,12157,12158,12159,12160,12161,12162,12163,
9495412164,12165,12166,12167,12168,12169,12170,12171,12172,12173,12174,12175,
9495512176,12177,12178,12179,12180,12181,12182,12183,12184,12185,12186,12187,
9495612188,12189,12190,12191,12192,12193,12194,12195,12196,12197,12198,12199,
9495712200,12201,12202,12203,12204,12205,12206,12207,12208,12209,12210,12211,
9495812212,12213,12214,12215,12216,12217,12218,12219,12220,12221,12222,12223,
9495912224,12225,12226,12227,12228,12229,12230,12231,12232,12233,12234,12235,
9496012236,12237,12238,12239,12240,12241,12242,12243,12244,12245,12246,12247,
9496112248,12249,12250,12251,12252,12253,12254,12255,12256,12257,12258,12259,
9496212260,12261,12262,12263,12264,12265,12266,12267,12268,12269,12270,12271,
9496312272,12273,12274,12275,12276,12277,12278,12279,12280,12281,12282,12283,
9496412284,12285,12286,12287,12288,12289,12290,12291,12292,12293,12294,12295,
9496512296,12297,12298,12299,12300,12301,12302,12303,12304,12305,12306,12307,
9496612308,12309,12310,12311,12312,12313,12314,12315,12316,12317,12318,12319,
9496712320,12321,12322,12323,12324,12325,12326,12327,12328,12329,12330,12331,
9496812332,12333,12334,12335,12336,12337,12338,12339,12340,12341,12342,12343,
9496912344,12345,12346,12347,12348,12349,12350,12351,12352,12353,12354,12355,
9497012356,12357,12358,12359,12360,12361,12362,12363,12364,12365,12366,12367,
9497112368,12369,12370,12371,12372,12373,12374,12375,12376,12377,12378,12379,
9497212380,12381,12382,12383,12384,12385,12386,12387,12388,12389,12390,12391,
9497312392,12393,12394,12395,12396,12397,12398,12399,12400,12401,12402,12403,
9497412404,12405,12406,12407,12408,12409,12410,12411,12412,12413,12414,12415,
9497512416,12417,12418,12419,12420,12421,12422,12423,12424,12425,12426,12427,
9497612428,12429,12430,12431,12432,12433,12434,12435,12436,12437,12438,12439,
9497712440,12441,12442,12443,12444,12445,12446,12447,12448,12449,12450,12451,
9497812452,12453,12454,12455,12456,12457,12458,12459,12460,12461,12462,12463,
9497912464,12465,12466,12467,12468,12469,12470,12471,12472,12473,12474,12475,
9498012476,12477,12478,12479,12480,12481,12482,12483,12484,12485,12486,12487,
9498112488,12489,12490,12491,12492,12493,12494,12495,12496,12497,12498,12499,
9498212500,12501,12502,12503,12504,12505,12506,12507,12508,12509,12510,12511,
9498312512,12513,12514,12515,12516,12517,12518,12519,12520,12521,12522,12523,
9498412524,12525,12526,12527,12528,12529,12530,12531,12532,12533,12534,12535,
9498512536,12537,12538,12539,12540,12541,12542,12543,12544,12545,12546,12547,
9498612548,12549,12550,12551,12552,12553,12554,12555,12556,12557,12558,12559,
9498712560,12561,12562,12563,12564,12565,12566,12567,12568,12569,12570,12571,
9498812572,12573,12574,12575,12576,12577,12578,12579,12580,12581,12582,12583,
9498912584,12585,12586,12587,12588,12589,12590,12591,12592,12593,12594,12595,
9499012596,12597,12598,12599,12600,12601,12602,12603,12604,12605,12606,12607,
9499112608,12609,12610,12611,12612,12613,12614,12615,12616,12617,12618,12619,
9499212620,12621,12622,12623,12624,12625,12626,12627,12628,12629,12630,12631,
9499312632,12633,12634,12635,12636,12637,12638,12639,12640,12641,12642,12643,
9499412644,12645,12646,12647,12648,12649,12650,12651,12652,12653,12654,12655,
9499512656,12657,12658,12659,12660,12661,12662,12663,12664,12665,12666,12667,
9499612668,12669,12670,12671,12672,12673,12674,12675,12676,12677,12678,12679,
9499712680,12681,12682,12683,12684,12685,12686,12687,12688,12689,12690,12691,
9499812692,12693,12694,12695,12696,12697,12698,12699,12700,12701,12702,12703,
9499912704,12705,12706,12707,12708,12709,12710,12711,12712,12713,12714,12715,
9500012716,12717,12718,12719,12720,12721,12722,12723,12724,12725,12726,12727,
9500112728,12729,12730,12731,12732,12733,12734,12735,12736,12737,12738,12739,
9500212740,12741,12742,12743,12744,12745,12746,12747,12748,12749,12750,12751,
9500312752,12753,12754,12755,12756,12757,12758,12759,12760,12761,12762,12763,
9500412764,12765,12766,12767,12768,12769,12770,12771,12772,12773,12774,12775,
9500512776,12777,12778,12779,12780,12781,12782,12783,12784,12785,12786,12787,
9500612788,12789,12790,12791,12792,12793,12794,12795,12796,12797,12798,12799,
9500712800,12801,12802,12803,12804,12805,12806,12807,12808,12809,12810,12811,
9500812812,12813,12814,12815,12816,12817,12818,12819,12820,12821,12822,12823,
9500912824,12825,12826,12827,12828,12829,12830,12831,12832,12833,12834,12835,
9501012836,12837,12838,12839,12840,12841,12842,12843,12844,12845,12846,12847,
9501112848,12849,12850,12851,12852,12853,12854,12855,12856,12857,12858,12859,
9501212860,12861,12862,12863,12864,12865,12866,12867,12868,12869,12870,12871,
9501312872,12873,12874,12875,12876,12877,12878,12879,12880,12881,12882,12883,
9501412884,12885,12886,12887,12888,12889,12890,12891,12892,12893,12894,12895,
9501512896,12897,12898,12899,12900,12901,12902,12903,12904,12905,12906,12907,
9501612908,12909,12910,12911,12912,12913,12914,12915,12916,12917,12918,12919,
9501712920,12921,12922,12923,12924,12925,12926,12927,12928,12929,12930,12931,
9501812932,12933,12934,12935,12936,12937,12938,12939,12940,12941,12942,12943,
9501912944,12945,12946,12947,12948,12949,12950,12951,12952,12953,12954,12955,
9502012956,12957,12958,12959,12960,12961,12962,12963,12964,12965,12966,12967,
9502112968,12969,12970,12971,12972,12973,12974,12975,12976,12977,12978,12979,
9502212980,12981,12982,12983,12984,12985,12986,12987,12988,12989,12990,12991,
9502312992,12993,12994,12995,12996,12997,12998,12999,13000,13001,13002,13003,
9502413004,13005,13006,13007,13008,13009,13010,13011,13012,13013,13014,13015,
9502513016,13017,13018,13019,13020,13021,13022,13023,13024,13025,13026,13027,
9502613028,13029,13030,13031,13032,13033,13034,13035,13036,13037,13038,13039,
9502713040,13041,13042,13043,13044,13045,13046,13047,13048,13049,13050,13051,
9502813052,13053,13054,13055,13056,13057,13058,13059,13060,13061,13062,13063,
9502913064,13065,13066,13067,13068,13069,13070,13071,13072,13073,13074,13075,
9503013076,13077,13078,13079,13080,13081,13082,13083,13084,13085,13086,13087,
9503113088,13089,13090,13091,13092,13093,13094,13095,13096,13097,13098,13099,
9503213100,13101,13102,13103,13104,13105,13106,13107,13108,13109,13110,13111,
9503313112,13113,13114,13115,13116,13117,13118,13119,13120,13121,13122,13123,
9503413124,13125,13126,13127,13128,13129,13130,13131,13132,13133,13134,13135,
9503513136,13137,13138,13139,13140,13141,13142,13143,13144,13145,13146,13147,
9503613148,13149,13150,13151,13152,13153,13154,13155,13156,13157,13158,13159,
9503713160,13161,13162,13163,13164,13165,13166,13167,13168,13169,13170,13171,
9503813172,13173,13174,13175,13176,13177,13178,13179,13180,13181,13182,13183,
9503913184,13185,13186,13187,13188,13189,13190,13191,13192,13193,13194,13195,
9504013196,13197,13198,13199,13200,13201,13202,13203,13204,13205,13206,13207,
9504113208,13209,13210,13211,13212,13213,13214,13215,13216,13217,13218,13219,
9504213220,13221,13222,13223,13224,13225,13226,13227,13228,13229,13230,13231,
9504313232,13233,13234,13235,13236,13237,13238,13239,13240,13241,13242,13243,
9504413244,13245,13246,13247,13248,13249,13250,13251,13252,13253,13254,13255,
9504513256,13257,13258,13259,13260,13261,13262,13263,13264,13265,13266,13267,
9504613268,13269,13270,13271,13272,13273,13274,13275,13276,13277,13278,13279,
9504713280,13281,13282,13283,13284,13285,13286,13287,13288,13289,13290,13291,
9504813292,13293,13294,13295,13296,13297,13298,13299,13300,13301,13302,13303,
9504913304,13305,13306,13307,13308,13309,13310,13311,13312,13313,13314,13315,
9505013316,13317,13318,13319,13320,13321,13322,13323,13324,13325,13326,13327,
9505113328,13329,13330,13331,13332,13333,13334,13335,13336,13337,13338,13339,
9505213340,13341,13342,13343,13344,13345,13346,13347,13348,13349,13350,13351,
9505313352,13353,13354,13355,13356,13357,13358,13359,13360,13361,13362,13363,
9505413364,13365,13366,13367,13368,13369,13370,13371,13372,13373,13374,13375,
9505513376,13377,13378,13379,13380,13381,13382,13383,13384,13385,13386,13387,
9505613388,13389,13390,13391,13392,13393,13394,13395,13396,13397,13398,13399,
9505713400,13401,13402,13403,13404,13405,13406,13407,13408,13409,13410,13411,
9505813412,13413,13414,13415,13416,13417,13418,13419,13420,13421,13422,13423,
9505913424,13425,13426,13427,13428,13429,13430,13431,13432,13433,13434,13435,
9506013436,13437,13438,13439,13440,13441,13442,13443,13444,13445,13446,13447,
9506113448,13449,13450,13451,13452,13453,13454,13455,13456,13457,13458,13459,
9506213460,13461,13462,13463,13464,13465,13466,13467,13468,13469,13470,13471,
9506313472,13473,13474,13475,13476,13477,13478,13479,13480,13481,13482,13483,
9506413484,13485,13486,13487,13488,13489,13490,13491,13492,13493,13494,13495,
9506513496,13497,13498,13499,13500,13501,13502,13503,13504,13505,13506,13507,
9506613508,13509,13510,13511,13512,13513,13514,13515,13516,13517,13518,13519,
9506713520,13521,13522,13523,13524,13525,13526,13527,13528,13529,13530,13531,
9506813532,13533,13534,13535,13536,13537,13538,13539,13540,13541,13542,13543,
9506913544,13545,13546,13547,13548,13549,13550,13551,13552,13553,13554,13555,
9507013556,13557,13558,13559,13560,13561,13562,13563,13564,13565,13566,13567,
9507113568,13569,13570,13571,13572,13573,13574,13575,13576,13577,13578,13579,
9507213580,13581,13582,13583,13584,13585,13586,13587,13588,13589,13590,13591,
9507313592,13593,13594,13595,13596,13597,13598,13599,13600,13601,13602,13603,
9507413604,13605,13606,13607,13608,13609,13610,13611,13612,13613,13614,13615,
9507513616,13617,13618,13619,13620,13621,13622,13623,13624,13625,13626,13627,
9507613628,13629,13630,13631,13632,13633,13634,13635,13636,13637,13638,13639,
9507713640,13641,13642,13643,13644,13645,13646,13647,13648,13649,13650,13651,
9507813652,13653,13654,13655,13656,13657,13658,13659,13660,13661,13662,13663,
9507913664,13665,13666,13667,13668,13669,13670,13671,13672,13673,13674,13675,
9508013676,13677,13678,13679,13680,13681,13682,13683,13684,13685,13686,13687,
9508113688,13689,13690,13691,13692,13693,13694,13695,13696,13697,13698,13699,
9508213700,13701,13702,13703,13704,13705,13706,13707,13708,13709,13710,13711,
9508313712,13713,13714,13715,13716,13717,13718,13719,13720,13721,13722,13723,
9508413724,13725,13726,13727,13728,13729,13730,13731,13732,13733,13734,13735,
9508513736,13737,13738,13739,13740,13741,13742,13743,13744,13745,13746,13747,
9508613748,13749,13750,13751,13752,13753,13754,13755,13756,13757,13758,13759,
9508713760,13761,13762,13763,13764,13765,13766,13767,13768,13769,13770,13771,
9508813772,13773,13774,13775,13776,13777,13778,13779,13780,13781,13782,13783,
9508913784,13785,13786,13787,13788,13789,13790,13791,13792,13793,13794,13795,
9509013796,13797,13798,13799,13800,13801,13802,13803,13804,13805,13806,13807,
9509113808,13809,13810,13811,13812,13813,13814,13815,13816,13817,13818,13819,
9509213820,13821,13822,13823,13824,13825,13826,13827,13828,13829,13830,13831,
9509313832,13833,13834,13835,13836,13837,13838,13839,13840,13841,13842,13843,
9509413844,13845,13846,13847,13848,13849,13850,13851,13852,13853,13854,13855,
9509513856,13857,13858,13859,13860,13861,13862,13863,13864,13865,13866,13867,
9509613868,13869,13870,13871,13872,13873,13874,13875,13876,13877,13878,13879,
9509713880,13881,13882,13883,13884,13885,13886,13887,13888,13889,13890,13891,
9509813892,13893,13894,13895,13896,13897,13898,13899,13900,13901,13902,13903,
9509913904,13905,13906,13907,13908,13909,13910,13911,13912,13913,13914,13915,
9510013916,13917,13918,13919,13920,13921,13922,13923,13924,13925,13926,13927,
9510113928,13929,13930,13931,13932,13933,13934,13935,13936,13937,13938,13939,
9510213940,13941,13942,13943,13944,13945,13946,13947,13948,13949,13950,13951,
9510313952,13953,13954,13955,13956,13957,13958,13959,13960,13961,13962,13963,
9510413964,13965,13966,13967,13968,13969,13970,13971,13972,13973,13974,13975,
9510513976,13977,13978,13979,13980,13981,13982,13983,13984,13985,13986,13987,
9510613988,13989,13990,13991,13992,13993,13994,13995,13996,13997,13998,13999,
9510714000,14001,14002,14003,14004,14005,14006,14007,14008,14009,14010,14011,
9510814012,14013,14014,14015,14016,14017,14018,14019,14020,14021,14022,14023,
9510914024,14025,14026,14027,14028,14029,14030,14031,14032,14033,14034,14035,
9511014036,14037,14038,14039,14040,14041,14042,14043,14044,14045,14046,14047,
9511114048,14049,14050,14051,14052,14053,14054,14055,14056,14057,14058,14059,
9511214060,14061,14062,14063,14064,14065,14066,14067,14068,14069,14070,14071,
9511314072,14073,14074,14075,14076,14077,14078,14079,14080,14081,14082,14083,
9511414084,14085,14086,14087,14088,14089,14090,14091,14092,14093,14094,14095,
9511514096,14097,14098,14099,14100,14101,14102,14103,14104,14105,14106,14107,
9511614108,14109,14110,14111,14112,14113,14114,14115,14116,14117,14118,14119,
9511714120,14121,14122,14123,14124,14125,14126,14127,14128,14129,14130,14131,
9511814132,14133,14134,14135,14136,14137,14138,14139,14140,14141,14142,14143,
9511914144,14145,14146,14147,14148,14149,14150,14151,14152,14153,14154,14155,
9512014156,14157,14158,14159,14160,14161,14162,14163,14164,14165,14166,14167,
9512114168,14169,14170,14171,14172,14173,14174,14175,14176,14177,14178,14179,
9512214180,14181,14182,14183,14184,14185,14186,14187,14188,14189,14190,14191,
9512314192,14193,14194,14195,14196,14197,14198,14199,14200,14201,14202,14203,
9512414204,14205,14206,14207,14208,14209,14210,14211,14212,14213,14214,14215,
9512514216,14217,14218,14219,14220,14221,14222,14223,14224,14225,14226,14227,
9512614228,14229,14230,14231,14232,14233,14234,14235,14236,14237,14238,14239,
9512714240,14241,14242,14243,14244,14245,14246,14247,14248,14249,14250,14251,
9512814252,14253,14254,14255,14256,14257,14258,14259,14260,14261,14262,14263,
9512914264,14265,14266,14267,14268,14269,14270,14271,14272,14273,14274,14275,
9513014276,14277,14278,14279,14280,14281,14282,14283,14284,14285,14286,14287,
9513114288,14289,14290,14291,14292,14293,14294,14295,14296,14297,14298,14299,
9513214300,14301,14302,14303,14304,14305,14306,14307,14308,14309,14310,14311,
9513314312,14313,14314,14315,14316,14317,14318,14319,14320,14321,14322,14323,
9513414324,14325,14326,14327,14328,14329,14330,14331,14332,14333,14334,14335,
9513514336,14337,14338,14339,14340,14341,14342,14343,14344,14345,14346,14347,
9513614348,14349,14350,14351,14352,14353,14354,14355,14356,14357,14358,14359,
9513714360,14361,14362,14363,14364,14365,14366,14367,14368,14369,14370,14371,
9513814372,14373,14374,14375,14376,14377,14378,14379,14380,14381,14382,14383,
9513914384,14385,14386,14387,14388,14389,14390,14391,14392,14393,14394,14395,
9514014396,14397,14398,14399,14400,14401,14402,14403,14404,14405,14406,14407,
9514114408,14409,14410,14411,14412,14413,14414,14415,14416,14417,14418,14419,
9514214420,14421,14422,14423,14424,14425,14426,14427,14428,14429,14430,14431,
9514314432,14433,14434,14435,14436,14437,14438,14439,14440,14441,14442,14443,
9514414444,14445,14446,14447,14448,14449,14450,14451,14452,14453,14454,14455,
9514514456,14457,14458,14459,14460,14461,14462,14463,14464,14465,14466,14467,
9514614468,14469,14470,14471,14472,14473,14474,14475,14476,14477,14478,14479,
9514714480,14481,14482,14483,14484,14485,14486,14487,14488,14489,14490,14491,
9514814492,14493,14494,14495,14496,14497,14498,14499,14500,14501,14502,14503,
9514914504,14505,14506,14507,14508,14509,14510,14511,14512,14513,14514,14515,
9515014516,14517,14518,14519,14520,14521,14522,14523,14524,14525,14526,14527,
9515114528,14529,14530,14531,14532,14533,14534,14535,14536,14537,14538,14539,
9515214540,14541,14542,14543,14544,14545,14546,14547,14548,14549,14550,14551,
9515314552,14553,14554,14555,14556,14557,14558,14559,14560,14561,14562,14563,
9515414564,14565,14566,14567,14568,14569,14570,14571,14572,14573,14574,14575,
9515514576,14577,14578,14579,14580,14581,14582,14583,14584,14585,14586,14587,
9515614588,14589,14590,14591,14592,14593,14594,14595,14596,14597,14598,14599,
9515714600,14601,14602,14603,14604,14605,14606,14607,14608,14609,14610,14611,
9515814612,14613,14614,14615,14616,14617,14618,14619,14620,14621,14622,14623,
9515914624,14625,14626,14627,14628,14629,14630,14631,14632,14633,14634,14635,
9516014636,14637,14638,14639,14640,14641,14642,14643,14644,14645,14646,14647,
9516114648,14649,14650,14651,14652,14653,14654,14655,14656,14657,14658,14659,
9516214660,14661,14662,14663,14664,14665,14666,14667,14668,14669,14670,14671,
9516314672,14673,14674,14675,14676,14677,14678,14679,14680,14681,14682,14683,
9516414684,14685,14686,14687,14688,14689,14690,14691,14692,14693,14694,14695,
9516514696,14697,14698,14699,14700,14701,14702,14703,14704,14705,14706,14707,
9516614708,14709,14710,14711,14712,14713,14714,14715,14716,14717,14718,14719,
9516714720,14721,14722,14723,14724,14725,14726,14727,14728,14729,14730,14731,
9516814732,14733,14734,14735,14736,14737,14738,14739,14740,14741,14742,14743,
9516914744,14745,14746,14747,14748,14749,14750,14751,14752,14753,14754,14755,
9517014756,14757,14758,14759,14760,14761,14762,14763,14764,14765,14766,14767,
9517114768,14769,14770,14771,14772,14773,14774,14775,14776,14777,14778,14779,
9517214780,14781,14782,14783,14784,14785,14786,14787,14788,14789,14790,14791,
9517314792,14793,14794,14795,14796,14797,14798,14799,14800,14801,14802,14803,
9517414804,14805,14806,14807,14808,14809,14810,14811,14812,14813,14814,14815,
9517514816,14817,14818,14819,14820,14821,14822,14823,14824,14825,14826,14827,
9517614828,14829,14830,14831,14832,14833,14834,14835,14836,14837,14838,14839,
9517714840,14841,14842,14843,14844,14845,14846,14847,14848,14849,14850,14851,
9517814852,14853,14854,14855,14856,14857,14858,14859,14860,14861,14862,14863,
9517914864,14865,14866,14867,14868,14869,14870,14871,14872,14873,14874,14875,
9518014876,14877,14878,14879,14880,14881,14882,14883,14884,14885,14886,14887,
9518114888,14889,14890,14891,14892,14893,14894,14895,14896,14897,14898,14899,
9518214900,14901,14902,14903,14904,14905,14906,14907,14908,14909,14910,14911,
9518314912,14913,14914,14915,14916,14917,14918,14919,14920,14921,14922,14923,
9518414924,14925,14926,14927,14928,14929,14930,14931,14932,14933,14934,14935,
9518514936,14937,14938,14939,14940,14941,14942,14943,14944,14945,14946,14947,
9518614948,14949,14950,14951,14952,14953,14954,14955,14956,14957,14958,14959,
9518714960,14961,14962,14963,14964,14965,14966,14967,14968,14969,14970,14971,
9518814972,14973,14974,14975,14976,14977,14978,14979,14980,14981,14982,14983,
9518914984,14985,14986,14987,14988,14989,14990,14991,14992,14993,14994,14995,
9519014996,14997,14998,14999,15000,15001,15002,15003,15004,15005,15006,15007,
9519115008,15009,15010,15011,15012,15013,15014,15015,15016,15017,15018,15019,
9519215020,15021,15022,15023,15024,15025,15026,15027,15028,15029,15030,15031,
9519315032,15033,15034,15035,15036,15037,15038,15039,15040,15041,15042,15043,
9519415044,15045,15046,15047,15048,15049,15050,15051,15052,15053,15054,15055,
9519515056,15057,15058,15059,15060,15061,15062,15063,15064,15065,15066,15067,
9519615068,15069,15070,15071,15072,15073,15074,15075,15076,15077,15078,15079,
9519715080,15081,15082,15083,15084,15085,15086,15087,15088,15089,15090,15091,
9519815092,15093,15094,15095,15096,15097,15098,15099,15100,15101,15102,15103,
9519915104,15105,15106,15107,15108,15109,15110,15111,15112,15113,15114,15115,
9520015116,15117,15118,15119,15120,15121,15122,15123,15124,15125,15126,15127,
9520115128,15129,15130,15131,15132,15133,15134,15135,15136,15137,15138,15139,
9520215140,15141,15142,15143,15144,15145,15146,15147,15148,15149,15150,15151,
9520315152,15153,15154,15155,15156,15157,15158,15159,15160,15161,15162,15163,
9520415164,15165,15166,15167,15168,15169,15170,15171,15172,15173,15174,15175,
9520515176,15177,15178,15179,15180,15181,15182,15183,15184,15185,15186,15187,
9520615188,15189,15190,15191,15192,15193,15194,15195,15196,15197,15198,15199,
9520715200,15201,15202,15203,15204,15205,15206,15207,15208,15209,15210,15211,
9520815212,15213,15214,15215,15216,15217,15218,15219,15220,15221,15222,15223,
9520915224,15225,15226,15227,15228,15229,15230,15231,15232,15233,15234,15235,
9521015236,15237,15238,15239,15240,15241,15242,15243,15244,15245,15246,15247,
9521115248,15249,15250,15251,15252,15253,15254,15255,15256,15257,15258,15259,
9521215260,15261,15262,15263,15264,15265,15266,15267,15268,15269,15270,15271,
9521315272,15273,15274,15275,15276,15277,15278,15279,15280,15281,15282,15283,
9521415284,15285,15286,15287,15288,15289,15290,15291,15292,15293,15294,15295,
9521515296,15297,15298,15299,15300,15301,15302,15303,15304,15305,15306,15307,
9521615308,15309,15310,15311,15312,15313,15314,15315,15316,15317,15318,15319,
9521715320,15321,15322,15323,15324,15325,15326,15327,15328,15329,15330,15331,
9521815332,15333,15334,15335,15336,15337,15338,15339,15340,15341,15342,15343,
9521915344,15345,15346,15347,15348,15349,15350,15351,15352,15353,15354,15355,
9522015356,15357,15358,15359,15360,15361,15362,15363,15364,15365,15366,15367,
9522115368,15369,15370,15371,15372,15373,15374,15375,15376,15377,15378,15379,
9522215380,15381,15382,15383,15384,15385,15386,15387,15388,15389,15390,15391,
9522315392,15393,15394,15395,15396,15397,15398,15399,15400,15401,15402,15403,
9522415404,15405,15406,15407,15408,15409,15410,15411,15412,15413,15414,15415,
9522515416,15417,15418,15419,15420,15421,15422,15423,15424,15425,15426,15427,
9522615428,15429,15430,15431,15432,15433,15434,15435,15436,15437,15438,15439,
9522715440,15441,15442,15443,15444,15445,15446,15447,15448,15449,15450,15451,
9522815452,15453,15454,15455,15456,15457,15458,15459,15460,15461,15462,15463,
9522915464,15465,15466,15467,15468,15469,15470,15471,15472,15473,15474,15475,
9523015476,15477,15478,15479,15480,15481,15482,15483,15484,15485,15486,15487,
9523115488,15489,15490,15491,15492,15493,15494,15495,15496,15497,15498,15499,
9523215500,15501,15502,15503,15504,15505,15506,15507,15508,15509,15510,15511,
9523315512,15513,15514,15515,15516,15517,15518,15519,15520,15521,15522,15523,
9523415524,15525,15526,15527,15528,15529,15530,15531,15532,15533,15534,15535,
9523515536,15537,15538,15539,15540,15541,15542,15543,15544,15545,15546,15547,
9523615548,15549,15550,15551,15552,15553,15554,15555,15556,15557,15558,15559,
9523715560,15561,15562,15563,15564,15565,15566,15567,15568,15569,15570,15571,
9523815572,15573,15574,15575,15576,15577,15578,15579,15580,15581,15582,15583,
9523915584,15585,15586,15587,15588,15589,15590,15591,15592,15593,15594,15595,
9524015596,15597,15598,15599,15600,15601,15602,15603,15604,15605,15606,15607,
9524115608,15609,15610,15611,15612,15613,15614,15615,15616,15617,15618,15619,
9524215620,15621,15622,15623,15624,15625,15626,15627,15628,15629,15630,15631,
9524315632,15633,15634,15635,15636,15637,15638,15639,15640,15641,15642,15643,
9524415644,15645,15646,15647,15648,15649,15650,15651,15652,15653,15654,15655,
9524515656,15657,15658,15659,15660,15661,15662,15663,15664,15665,15666,15667,
9524615668,15669,15670,15671,15672,15673,15674,15675,15676,15677,15678,15679,
9524715680,15681,15682,15683,15684,15685,15686,15687,15688,15689,15690,15691,
9524815692,15693,15694,15695,15696,15697,15698,15699,15700,15701,15702,15703,
9524915704,15705,15706,15707,15708,15709,15710,15711,15712,15713,15714,15715,
9525015716,15717,15718,15719,15720,15721,15722,15723,15724,15725,15726,15727,
9525115728,15729,15730,15731,15732,15733,15734,15735,15736,15737,15738,15739,
9525215740,15741,15742,15743,15744,15745,15746,15747,15748,15749,15750,15751,
9525315752,15753,15754,15755,15756,15757,15758,15759,15760,15761,15762,15763,
9525415764,15765,15766,15767,15768,15769,15770,15771,15772,15773,15774,15775,
9525515776,15777,15778,15779,15780,15781,15782,15783,15784,15785,15786,15787,
9525615788,15789,15790,15791,15792,15793,15794,15795,15796,15797,15798,15799,
9525715800,15801,15802,15803,15804,15805,15806,15807,15808,15809,15810,15811,
9525815812,15813,15814,15815,15816,15817,15818,15819,15820,15821,15822,15823,
9525915824,15825,15826,15827,15828,15829,15830,15831,15832,15833,15834,15835,
9526015836,15837,15838,15839,15840,15841,15842,15843,15844,15845,15846,15847,
9526115848,15849,15850,15851,15852,15853,15854,15855,15856,15857,15858,15859,
9526215860,15861,15862,15863,15864,15865,15866,15867,15868,15869,15870,15871,
9526315872,15873,15874,15875,15876,15877,15878,15879,15880,15881,15882,15883,
9526415884,15885,15886,15887,15888,15889,15890,15891,15892,15893,15894,15895,
9526515896,15897,15898,15899,15900,15901,15902,15903,15904,15905,15906,15907,
9526615908,15909,15910,15911,15912,15913,15914,15915,15916,15917,15918,15919,
9526715920,15921,15922,15923,15924,15925,15926,15927,15928,15929,15930,15931,
9526815932,15933,15934,15935,15936,15937,15938,15939,15940,15941,15942,15943,
9526915944,15945,15946,15947,15948,15949,15950,15951,15952,15953,15954,15955,
9527015956,15957,15958,15959,15960,15961,15962,15963,15964,15965,15966,15967,
9527115968,15969,15970,15971,15972,15973,15974,15975,15976,15977,15978,15979,
9527215980,15981,15982,15983,15984,15985,15986,15987,15988,15989,15990,15991,
9527315992,15993,15994,15995,15996,15997,15998,15999,16000,16001,16002,16003,
9527416004,16005,16006,16007,16008,16009,16010,16011,16012,16013,16014,16015,
9527516016,16017,16018,16019,16020,16021,16022,16023,16024,16025,16026,16027,
9527616028,16029,16030,16031,16032,16033,16034,16035,16036,16037,16038,16039,
9527716040,16041,16042,16043,16044,16045,16046,16047,16048,16049,16050,16051,
9527816052,16053,16054,16055,16056,16057,16058,16059,16060,16061,16062,16063,
9527916064,16065,16066,16067,16068,16069,16070,16071,16072,16073,16074,16075,
9528016076,16077,16078,16079,16080,16081,16082,16083,16084,16085,16086,16087,
9528116088,16089,16090,16091,16092,16093,16094,16095,16096,16097,16098,16099,
9528216100,16101,16102,16103,16104,16105,16106,16107,16108,16109,16110,16111,
9528316112,16113,16114,16115,16116,16117,16118,16119,16120,16121,16122,16123,
9528416124,16125,16126,16127,16128,16129,16130,16131,16132,16133,16134,16135,
9528516136,16137,16138,16139,16140,16141,16142,16143,16144,16145,16146,16147,
9528616148,16149,16150,16151,16152,16153,16154,16155,16156,16157,16158,16159,
9528716160,16161,16162,16163,16164,16165,16166,16167,16168,16169,16170,16171,
9528816172,16173,16174,16175,16176,16177,16178,16179,16180,16181,16182,16183,
9528916184,16185,16186,16187,16188,16189,16190,16191,16192,16193,16194,16195,
9529016196,16197,16198,16199,16200,16201,16202,16203,16204,16205,16206,16207,
9529116208,16209,16210,16211,16212,16213,16214,16215,16216,16217,16218,16219,
9529216220,16221,16222,16223,16224,16225,16226,16227,16228,16229,16230,16231,
9529316232,16233,16234,16235,16236,16237,16238,16239,16240,16241,16242,16243,
9529416244,16245,16246,16247,16248,16249,16250,16251,16252,16253,16254,16255,
9529516256,16257,16258,16259,16260,16261,16262,16263,16264,16265,16266,16267,
9529616268,16269,16270,16271,16272,16273,16274,16275,16276,16277,16278,16279,
9529716280,16281,16282,16283,16284,16285,16286,16287,16288,16289,16290,16291,
9529816292,16293,16294,16295,16296,16297,16298,16299,16300,16301,16302,16303,
9529916304,16305,16306,16307,16308,16309,16310,16311,16312,16313,16314,16315,
9530016316,16317,16318,16319,16320,16321,16322,16323,16324,16325,16326,16327,
9530116328,16329,16330,16331,16332,16333,16334,16335,16336,16337,16338,16339,
9530216340,16341,16342,16343,16344,16345,16346,16347,16348,16349,16350,16351,
9530316352,16353,16354,16355,16356,16357,16358,16359,16360,16361,16362,16363,
9530416364,16365,16366,16367,16368,16369,16370,16371,16372,16373,16374,16375,
9530516376,16377,16378,16379,16380,16381,16382,16383,16384,16385,16386,16387,
9530616388,16389,16390,16391,16392,16393,16394,16395,16396,16397,16398,16399,
9530716400,16401,16402,16403,16404,16405,16406,16407,16408,16409,16410,16411,
9530816412,16413,16414,16415,16416,16417,16418,16419,16420,16421,16422,16423,
9530916424,16425,16426,16427,16428,16429,16430,16431,16432,16433,16434,16435,
9531016436,16437,16438,16439,16440,16441,16442,16443,16444,16445,16446,16447,
9531116448,16449,16450,16451,16452,16453,16454,16455,16456,16457,16458,16459,
9531216460,16461,16462,16463,16464,16465,16466,16467,16468,16469,16470,16471,
9531316472,16473,16474,16475,16476,16477,16478,16479,16480,16481,16482,16483,
9531416484,16485,16486,16487,16488,16489,16490,16491,16492,16493,16494,16495,
9531516496,16497,16498,16499,16500,16501,16502,16503,16504,16505,16506,16507,
9531616508,16509,16510,16511,16512,16513,16514,16515,16516,16517,16518,16519,
9531716520,16521,16522,16523,16524,16525,16526,16527,16528,16529,16530,16531,
9531816532,16533,16534,16535,16536,16537,16538,16539,16540,16541,16542,16543,
9531916544,16545,16546,16547,16548,16549,16550,16551,16552,16553,16554,16555,
9532016556,16557,16558,16559,16560,16561,16562,16563,16564,16565,16566,16567,
9532116568,16569,16570,16571,16572,16573,16574,16575,16576,16577,16578,16579,
9532216580,16581,16582,16583,16584,16585,16586,16587,16588,16589,16590,16591,
9532316592,16593,16594,16595,16596,16597,16598,16599,16600,16601,16602,16603,
9532416604,16605,16606,16607,16608,16609,16610,16611,16612,16613,16614,16615,
9532516616,16617,16618,16619,16620,16621,16622,16623,16624,16625,16626,16627,
9532616628,16629,16630,16631,16632,16633,16634,16635,16636,16637,16638,16639,
9532716640,16641,16642,16643,16644,16645,16646,16647,16648,16649,16650,16651,
9532816652,16653,16654,16655,16656,16657,16658,16659,16660,16661,16662,16663,
9532916664,16665,16666,16667,16668,16669,16670,16671,16672,16673,16674,16675,
9533016676,16677,16678,16679,16680,16681,16682,16683,16684,16685,16686,16687,
9533116688,16689,16690,16691,16692,16693,16694,16695,16696,16697,16698,16699,
9533216700,16701,16702,16703,16704,16705,16706,16707,16708,16709,16710,16711,
9533316712,16713,16714,16715,16716,16717,16718,16719,16720,16721,16722,16723,
9533416724,16725,16726,16727,16728,16729,16730,16731,16732,16733,16734,16735,
9533516736,16737,16738,16739,16740,16741,16742,16743,16744,16745,16746,16747,
9533616748,16749,16750,16751,16752,16753,16754,16755,16756,16757,16758,16759,
9533716760,16761,16762,16763,16764,16765,16766,16767,16768,16769,16770,16771,
9533816772,16773,16774,16775,16776,16777,16778,16779,16780,16781,16782,16783,
9533916784,16785,16786,16787,16788,16789,16790,16791,16792,16793,16794,16795,
9534016796,16797,16798,16799,16800,16801,16802,16803,16804,16805,16806,16807,
9534116808,16809,16810,16811,16812,16813,16814,16815,16816,16817,16818,16819,
9534216820,16821,16822,16823,16824,16825,16826,16827,16828,16829,16830,16831,
9534316832,16833,16834,16835,16836,16837,16838,16839,16840,16841,16842,16843,
9534416844,16845,16846,16847,16848,16849,16850,16851,16852,16853,16854,16855,
9534516856,16857,16858,16859,16860,16861,16862,16863,16864,16865,16866,16867,
9534616868,16869,16870,16871,16872,16873,16874,16875,16876,16877,16878,16879,
9534716880,16881,16882,16883,16884,16885,16886,16887,16888,16889,16890,16891,
9534816892,16893,16894,16895,16896,16897,16898,16899,16900,16901,16902,16903,
9534916904,16905,16906,16907,16908,16909,16910,16911,16912,16913,16914,16915,
9535016916,16917,16918,16919,16920,16921,16922,16923,16924,16925,16926,16927,
9535116928,16929,16930,16931,16932,16933,16934,16935,16936,16937,16938,16939,
9535216940,16941,16942,16943,16944,16945,16946,16947,16948,16949,16950,16951,
9535316952,16953,16954,16955,16956,16957,16958,16959,16960,16961,16962,16963,
9535416964,16965,16966,16967,16968,16969,16970,16971,16972,16973,16974,16975,
9535516976,16977,16978,16979,16980,16981,16982,16983,16984,16985,16986,16987,
9535616988,16989,16990,16991,16992,16993,16994,16995,16996,16997,16998,16999,
9535717000,17001,17002,17003,17004,17005,17006,17007,17008,17009,17010,17011,
9535817012,17013,17014,17015,17016,17017,17018,17019,17020,17021,17022,17023,
9535917024,17025,17026,17027,17028,17029,17030,17031,17032,17033,17034,17035,
9536017036,17037,17038,17039,17040,17041,17042,17043,17044,17045,17046,17047,
9536117048,17049,17050,17051,17052,17053,17054,17055,17056,17057,17058,17059,
9536217060,17061,17062,17063,17064,17065,17066,17067,17068,17069,17070,17071,
9536317072,17073,17074,17075,17076,17077,17078,17079,17080,17081,17082,17083,
9536417084,17085,17086,17087,17088,17089,17090,17091,17092,17093,17094,17095,
9536517096,17097,17098,17099,17100,17101,17102,17103,17104,17105,17106,17107,
9536617108,17109,17110,17111,17112,17113,17114,17115,17116,17117,17118,17119,
9536717120,17121,17122,17123,17124,17125,17126,17127,17128,17129,17130,17131,
9536817132,17133,17134,17135,17136,17137,17138,17139,17140,17141,17142,17143,
9536917144,17145,17146,17147,17148,17149,17150,17151,17152,17153,17154,17155,
9537017156,17157,17158,17159,17160,17161,17162,17163,17164,17165,17166,17167,
9537117168,17169,17170,17171,17172,17173,17174,17175,17176,17177,17178,17179,
9537217180,17181,17182,17183,17184,17185,17186,17187,17188,17189,17190,17191,
9537317192,17193,17194,17195,17196,17197,17198,17199,17200,17201,17202,17203,
9537417204,17205,17206,17207,17208,17209,17210,17211,17212,17213,17214,17215,
9537517216,17217,17218,17219,17220,17221,17222,17223,17224,17225,17226,17227,
9537617228,17229,17230,17231,17232,17233,17234,17235,17236,17237,17238,17239,
9537717240,17241,17242,17243,17244,17245,17246,17247,17248,17249,17250,17251,
9537817252,17253,17254,17255,17256,17257,17258,17259,17260,17261,17262,17263,
9537917264,17265,17266,17267,17268,17269,17270,17271,17272,17273,17274,17275,
9538017276,17277,17278,17279,17280,17281,17282,17283,17284,17285,17286,17287,
9538117288,17289,17290,17291,17292,17293,17294,17295,17296,17297,17298,17299,
9538217300,17301,17302,17303,17304,17305,17306,17307,17308,17309,17310,17311,
9538317312,17313,17314,17315,17316,17317,17318,17319,17320,17321,17322,17323,
9538417324,17325,17326,17327,17328,17329,17330,17331,17332,17333,17334,17335,
9538517336,17337,17338,17339,17340,17341,17342,17343,17344,17345,17346,17347,
9538617348,17349,17350,17351,17352,17353,17354,17355,17356,17357,17358,17359,
9538717360,17361,17362,17363,17364,17365,17366,17367,17368,17369,17370,17371,
9538817372,17373,17374,17375,17376,17377,17378,17379,17380,17381,17382,17383,
9538917384,17385,17386,17387,17388,17389,17390,17391,17392,17393,17394,17395,
9539017396,17397,17398,17399,17400,17401,17402,17403,17404,17405,17406,17407,
9539117408,17409,17410,17411,17412,17413,17414,17415,17416,17417,17418,17419,
9539217420,17421,17422,17423,17424,17425,17426,17427,17428,17429,17430,17431,
9539317432,17433,17434,17435,17436,17437,17438,17439,17440,17441,17442,17443,
9539417444,17445,17446,17447,17448,17449,17450,17451,17452,17453,17454,17455,
9539517456,17457,17458,17459,17460,17461,17462,17463,17464,17465,17466,17467,
9539617468,17469,17470,17471,17472,17473,17474,17475,17476,17477,17478,17479,
9539717480,17481,17482,17483,17484,17485,17486,17487,17488,17489,17490,17491,
9539817492,17493,17494,17495,17496,17497,17498,17499,17500,17501,17502,17503,
9539917504,17505,17506,17507,17508,17509,17510,17511,17512,17513,17514,17515,
9540017516,17517,17518,17519,17520,17521,17522,17523,17524,17525,17526,17527,
9540117528,17529,17530,17531,17532,17533,17534,17535,17536,17537,17538,17539,
9540217540,17541,17542,17543,17544,17545,17546,17547,17548,17549,17550,17551,
9540317552,17553,17554,17555,17556,17557,17558,17559,17560,17561,17562,17563,
9540417564,17565,17566,17567,17568,17569,17570,17571,17572,17573,17574,17575,
9540517576,17577,17578,17579,17580,17581,17582,17583,17584,17585,17586,17587,
9540617588,17589,17590,17591,17592,17593,17594,17595,17596,17597,17598,17599,
9540717600,17601,17602,17603,17604,17605,17606,17607,17608,17609,17610,17611,
9540817612,17613,17614,17615,17616,17617,17618,17619,17620,17621,17622,17623,
9540917624,17625,17626,17627,17628,17629,17630,17631,17632,17633,17634,17635,
9541017636,17637,17638,17639,17640,17641,17642,17643,17644,17645,17646,17647,
9541117648,17649,17650,17651,17652,17653,17654,17655,17656,17657,17658,17659,
9541217660,17661,17662,17663,17664,17665,17666,17667,17668,17669,17670,17671,
9541317672,17673,17674,17675,17676,17677,17678,17679,17680,17681,17682,17683,
9541417684,17685,17686,17687,17688,17689,17690,17691,17692,17693,17694,17695,
9541517696,17697,17698,17699,17700,17701,17702,17703,17704,17705,17706,17707,
9541617708,17709,17710,17711,17712,17713,17714,17715,17716,17717,17718,17719,
9541717720,17721,17722,17723,17724,17725,17726,17727,17728,17729,17730,17731,
9541817732,17733,17734,17735,17736,17737,17738,17739,17740,17741,17742,17743,
9541917744,17745,17746,17747,17748,17749,17750,17751,17752,17753,17754,17755,
9542017756,17757,17758,17759,17760,17761,17762,17763,17764,17765,17766,17767,
9542117768,17769,17770,17771,17772,17773,17774,17775,17776,17777,17778,17779,
9542217780,17781,17782,17783,17784,17785,17786,17787,17788,17789,17790,17791,
9542317792,17793,17794,17795,17796,17797,17798,17799,17800,17801,17802,17803,
9542417804,17805,17806,17807,17808,17809,17810,17811,17812,17813,17814,17815,
9542517816,17817,17818,17819,17820,17821,17822,17823,17824,17825,17826,17827,
9542617828,17829,17830,17831,17832,17833,17834,17835,17836,17837,17838,17839,
9542717840,17841,17842,17843,17844,17845,17846,17847,17848,17849,17850,17851,
9542817852,17853,17854,17855,17856,17857,17858,17859,17860,17861,17862,17863,
9542917864,17865,17866,17867,17868,17869,17870,17871,17872,17873,17874,17875,
9543017876,17877,17878,17879,17880,17881,17882,17883,17884,17885,17886,17887,
9543117888,17889,17890,17891,17892,17893,17894,17895,17896,17897,17898,17899,
9543217900,17901,17902,17903,17904,17905,17906,17907,17908,17909,17910,17911,
9543317912,17913,17914,17915,17916,17917,17918,17919,17920,17921,17922,17923,
9543417924,17925,17926,17927,17928,17929,17930,17931,17932,17933,17934,17935,
9543517936,17937,17938,17939,17940,17941,17942,17943,17944,17945,17946,17947,
9543617948,17949,17950,17951,17952,17953,17954,17955,17956,17957,17958,17959,
9543717960,17961,17962,17963,17964,17965,17966,17967,17968,17969,17970,17971,
9543817972,17973,17974,17975,17976,17977,17978,17979,17980,17981,17982,17983,
9543917984,17985,17986,17987,17988,17989,17990,17991,17992,17993,17994,17995,
9544017996,17997,17998,17999,18000,18001,18002,18003,18004,18005,18006,18007,
9544118008,18009,18010,18011,18012,18013,18014,18015,18016,18017,18018,18019,
9544218020,18021,18022,18023,18024,18025,18026,18027,18028,18029,18030,18031,
9544318032,18033,18034,18035,18036,18037,18038,18039,18040,18041,18042,18043,
9544418044,18045,18046,18047,18048,18049,18050,18051,18052,18053,18054,18055,
9544518056,18057,18058,18059,18060,18061,18062,18063,18064,18065,18066,18067,
9544618068,18069,18070,18071,18072,18073,18074,18075,18076,18077,18078,18079,
9544718080,18081,18082,18083,18084,18085,18086,18087,18088,18089,18090,18091,
9544818092,18093,18094,18095,18096,18097,18098,18099,18100,18101,18102,18103,
9544918104,18105,18106,18107,18108,18109,18110,18111,18112,18113,18114,18115,
9545018116,18117,18118,18119,18120,18121,18122,18123,18124,18125,18126,18127,
9545118128,18129,18130,18131,18132,18133,18134,18135,18136,18137,18138,18139,
9545218140,18141,18142,18143,18144,18145,18146,18147,18148,18149,18150,18151,
9545318152,18153,18154,18155,18156,18157,18158,18159,18160,18161,18162,18163,
9545418164,18165,18166,18167,18168,18169,18170,18171,18172,18173,18174,18175,
9545518176,18177,18178,18179,18180,18181,18182,18183,18184,18185,18186,18187,
9545618188,18189,18190,18191,18192,18193,18194,18195,18196,18197,18198,18199,
9545718200,18201,18202,18203,18204,18205,18206,18207,18208,18209,18210,18211,
9545818212,18213,18214,18215,18216,18217,18218,18219,18220,18221,18222,18223,
9545918224,18225,18226,18227,18228,18229,18230,18231,18232,18233,18234,18235,
9546018236,18237,18238,18239,18240,18241,18242,18243,18244,18245,18246,18247,
9546118248,18249,18250,18251,18252,18253,18254,18255,18256,18257,18258,18259,
9546218260,18261,18262,18263,18264,18265,18266,18267,18268,18269,18270,18271,
9546318272,18273,18274,18275,18276,18277,18278,18279,18280,18281,18282,18283,
9546418284,18285,18286,18287,18288,18289,18290,18291,18292,18293,18294,18295,
9546518296,18297,18298,18299,18300,18301,18302,18303,18304,18305,18306,18307,
9546618308,18309,18310,18311,18312,18313,18314,18315,18316,18317,18318,18319,
9546718320,18321,18322,18323,18324,18325,18326,18327,18328,18329,18330,18331,
9546818332,18333,18334,18335,18336,18337,18338,18339,18340,18341,18342,18343,
9546918344,18345,18346,18347,18348,18349,18350,18351,18352,18353,18354,18355,
9547018356,18357,18358,18359,18360,18361,18362,18363,18364,18365,18366,18367,
9547118368,18369,18370,18371,18372,18373,18374,18375,18376,18377,18378,18379,
9547218380,18381,18382,18383,18384,18385,18386,18387,18388,18389,18390,18391,
9547318392,18393,18394,18395,18396,18397,18398,18399,18400,18401,18402,18403,
9547418404,18405,18406,18407,18408,18409,18410,18411,18412,18413,18414,18415,
9547518416,18417,18418,18419,18420,18421,18422,18423,18424,18425,18426,18427,
9547618428,18429,18430,18431,18432,18433,18434,18435,18436,18437,18438,18439,
9547718440,18441,18442,18443,18444,18445,18446,18447,18448,18449,18450,18451,
9547818452,18453,18454,18455,18456,18457,18458,18459,18460,18461,18462,18463,
9547918464,18465,18466,18467,18468,18469,18470,18471,18472,18473,18474,18475,
9548018476,18477,18478,18479,18480,18481,18482,18483,18484,18485,18486,18487,
9548118488,18489,18490,18491,18492,18493,18494,18495,18496,18497,18498,18499,
9548218500,18501,18502,18503,18504,18505,18506,18507,18508,18509,18510,18511,
9548318512,18513,18514,18515,18516,18517,18518,18519,18520,18521,18522,18523,
9548418524,18525,18526,18527,18528,18529,18530,18531,18532,18533,18534,18535,
9548518536,18537,18538,18539,18540,18541,18542,18543,18544,18545,18546,18547,
9548618548,18549,18550,18551,18552,18553,18554,18555,18556,18557,18558,18559,
9548718560,18561,18562,18563,18564,18565,18566,18567,18568,18569,18570,18571,
9548818572,18573,18574,18575,18576,18577,18578,18579,18580,18581,18582,18583,
9548918584,18585,18586,18587,18588,18589,18590,18591,18592,18593,18594,18595,
9549018596,18597,18598,18599,18600,18601,18602,18603,18604,18605,18606,18607,
9549118608,18609,18610,18611,18612,18613,18614,18615,18616,18617,18618,18619,
9549218620,18621,18622,18623,18624,18625,18626,18627,18628,18629,18630,18631,
9549318632,18633,18634,18635,18636,18637,18638,18639,18640,18641,18642,18643,
9549418644,18645,18646,18647,18648,18649,18650,18651,18652,18653,18654,18655,
9549518656,18657,18658,18659,18660,18661,18662,18663,18664,18665,18666,18667,
9549618668,18669,18670,18671,18672,18673,18674,18675,18676,18677,18678,18679,
9549718680,18681,18682,18683,18684,18685,18686,18687,18688,18689,18690,18691,
9549818692,18693,18694,18695,18696,18697,18698,18699,18700,18701,18702,18703,
9549918704,18705,18706,18707,18708,18709,18710,18711,18712,18713,18714,18715,
9550018716,18717,18718,18719,18720,18721,18722,18723,18724,18725,18726,18727,
9550118728,18729,18730,18731,18732,18733,18734,18735,18736,18737,18738,18739,
9550218740,18741,18742,18743,18744,18745,18746,18747,18748,18749,18750,18751,
9550318752,18753,18754,18755,18756,18757,18758,18759,18760,18761,18762,18763,
9550418764,18765,18766,18767,18768,18769,18770,18771,18772,18773,18774,18775,
9550518776,18777,18778,18779,18780,18781,18782,18783,18784,18785,18786,18787,
9550618788,18789,18790,18791,18792,18793,18794,18795,18796,18797,18798,18799,
9550718800,18801,18802,18803,18804,18805,18806,18807,18808,18809,18810,18811,
9550818812,18813,18814,18815,18816,18817,18818,18819,18820,18821,18822,18823,
9550918824,18825,18826,18827,18828,18829,18830,18831,18832,18833,18834,18835,
9551018836,18837,18838,18839,18840,18841,18842,18843,18844,18845,18846,18847,
9551118848,18849,18850,18851,18852,18853,18854,18855,18856,18857,18858,18859,
9551218860,18861,18862,18863,18864,18865,18866,18867,18868,18869,18870,18871,
9551318872,18873,18874,18875,18876,18877,18878,18879,18880,18881,18882,18883,
9551418884,18885,18886,18887,18888,18889,18890,18891,18892,18893,18894,18895,
9551518896,18897,18898,18899,18900,18901,18902,18903,18904,18905,18906,18907,
9551618908,18909,18910,18911,18912,18913,18914,18915,18916,18917,18918,18919,
9551718920,18921,18922,18923,18924,18925,18926,18927,18928,18929,18930,18931,
9551818932,18933,18934,18935,18936,18937,18938,18939,18940,18941,18942,18943,
9551918944,18945,18946,18947,18948,18949,18950,18951,18952,18953,18954,18955,
9552018956,18957,18958,18959,18960,18961,18962,18963,18964,18965,18966,18967,
9552118968,18969,18970,18971,18972,18973,18974,18975,18976,18977,18978,18979,
9552218980,18981,18982,18983,18984,18985,18986,18987,18988,18989,18990,18991,
9552318992,18993,18994,18995,18996,18997,18998,18999,19000,19001,19002,19003,
9552419004,19005,19006,19007,19008,19009,19010,19011,19012,19013,19014,19015,
9552519016,19017,19018,19019,19020,19021,19022,19023,19024,19025,19026,19027,
9552619028,19029,19030,19031,19032,19033,19034,19035,19036,19037,19038,19039,
9552719040,19041,19042,19043,19044,19045,19046,19047,19048,19049,19050,19051,
9552819052,19053,19054,19055,19056,19057,19058,19059,19060,19061,19062,19063,
9552919064,19065,19066,19067,19068,19069,19070,19071,19072,19073,19074,19075,
9553019076,19077,19078,19079,19080,19081,19082,19083,19084,19085,19086,19087,
9553119088,19089,19090,19091,19092,19093,19094,19095,19096,19097,19098,19099,
9553219100,19101,19102,19103,19104,19105,19106,19107,19108,19109,19110,19111,
9553319112,19113,19114,19115,19116,19117,19118,19119,19120,19121,19122,19123,
9553419124,19125,19126,19127,19128,19129,19130,19131,19132,19133,19134,19135,
9553519136,19137,19138,19139,19140,19141,19142,19143,19144,19145,19146,19147,
9553619148,19149,19150,19151,19152,19153,19154,19155,19156,19157,19158,19159,
9553719160,19161,19162,19163,19164,19165,19166,19167,19168,19169,19170,19171,
9553819172,19173,19174,19175,19176,19177,19178,19179,19180,19181,19182,19183,
9553919184,19185,19186,19187,19188,19189,19190,19191,19192,19193,19194,19195,
9554019196,19197,19198,19199,19200,19201,19202,19203,19204,19205,19206,19207,
9554119208,19209,19210,19211,19212,19213,19214,19215,19216,19217,19218,19219,
9554219220,19221,19222,19223,19224,19225,19226,19227,19228,19229,19230,19231,
9554319232,19233,19234,19235,19236,19237,19238,19239,19240,19241,19242,19243,
9554419244,19245,19246,19247,19248,19249,19250,19251,19252,19253,19254,19255,
9554519256,19257,19258,19259,19260,19261,19262,19263,19264,19265,19266,19267,
9554619268,19269,19270,19271,19272,19273,19274,19275,19276,19277,19278,19279,
9554719280,19281,19282,19283,19284,19285,19286,19287,19288,19289,19290,19291,
9554819292,19293,19294,19295,19296,19297,19298,19299,19300,19301,19302,19303,
9554919304,19305,19306,19307,19308,19309,19310,19311,19312,19313,19314,19315,
9555019316,19317,19318,19319,19320,19321,19322,19323,19324,19325,19326,19327,
9555119328,19329,19330,19331,19332,19333,19334,19335,19336,19337,19338,19339,
9555219340,19341,19342,19343,19344,19345,19346,19347,19348,19349,19350,19351,
9555319352,19353,19354,19355,19356,19357,19358,19359,19360,19361,19362,19363,
9555419364,19365,19366,19367,19368,19369,19370,19371,19372,19373,19374,19375,
9555519376,19377,19378,19379,19380,19381,19382,19383,19384,19385,19386,19387,
9555619388,19389,19390,19391,19392,19393,19394,19395,19396,19397,19398,19399,
9555719400,19401,19402,19403,19404,19405,19406,19407,19408,19409,19410,19411,
9555819412,19413,19414,19415,19416,19417,19418,19419,19420,19421,19422,19423,
9555919424,19425,19426,19427,19428,19429,19430,19431,19432,19433,19434,19435,
9556019436,19437,19438,19439,19440,19441,19442,19443,19444,19445,19446,19447,
9556119448,19449,19450,19451,19452,19453,19454,19455,19456,19457,19458,19459,
9556219460,19461,19462,19463,19464,19465,19466,19467,19468,19469,19470,19471,
9556319472,19473,19474,19475,19476,19477,19478,19479,19480,19481,19482,19483,
9556419484,19485,19486,19487,19488,19489,19490,19491,19492,19493,19494,19495,
9556519496,19497,19498,19499,19500,19501,19502,19503,19504,19505,19506,19507,
9556619508,19509,19510,19511,19512,19513,19514,19515,19516,19517,19518,19519,
9556719520,19521,19522,19523,19524,19525,19526,19527,19528,19529,19530,19531,
9556819532,19533,19534,19535,19536,19537,19538,19539,19540,19541,19542,19543,
9556919544,19545,19546,19547,19548,19549,19550,19551,19552,19553,19554,19555,
9557019556,19557,19558,19559,19560,19561,19562,19563,19564,19565,19566,19567,
9557119568,19569,19570,19571,19572,19573,19574,19575,19576,19577,19578,19579,
9557219580,19581,19582,19583,19584,19585,19586,19587,19588,19589,19590,19591,
9557319592,19593,19594,19595,19596,19597,19598,19599,19600,19601,19602,19603,
9557419604,19605,19606,19607,19608,19609,19610,19611,19612,19613,19614,19615,
9557519616,19617,19618,19619,19620,19621,19622,19623,19624,19625,19626,19627,
9557619628,19629,19630,19631,19632,19633,19634,19635,19636,19637,19638,19639,
9557719640,19641,19642,19643,19644,19645,19646,19647,19648,19649,19650,19651,
9557819652,19653,19654,19655,19656,19657,19658,19659,19660,19661,19662,19663,
9557919664,19665,19666,19667,19668,19669,19670,19671,19672,19673,19674,19675,
9558019676,19677,19678,19679,19680,19681,19682,19683,19684,19685,19686,19687,
9558119688,19689,19690,19691,19692,19693,19694,19695,19696,19697,19698,19699,
9558219700,19701,19702,19703,19704,19705,19706,19707,19708,19709,19710,19711,
9558319712,19713,19714,19715,19716,19717,19718,19719,19720,19721,19722,19723,
9558419724,19725,19726,19727,19728,19729,19730,19731,19732,19733,19734,19735,
9558519736,19737,19738,19739,19740,19741,19742,19743,19744,19745,19746,19747,
9558619748,19749,19750,19751,19752,19753,19754,19755,19756,19757,19758,19759,
9558719760,19761,19762,19763,19764,19765,19766,19767,19768,19769,19770,19771,
9558819772,19773,19774,19775,19776,19777,19778,19779,19780,19781,19782,19783,
9558919784,19785,19786,19787,19788,19789,19790,19791,19792,19793,19794,19795,
9559019796,19797,19798,19799,19800,19801,19802,19803,19804,19805,19806,19807,
9559119808,19809,19810,19811,19812,19813,19814,19815,19816,19817,19818,19819,
9559219820,19821,19822,19823,19824,19825,19826,19827,19828,19829,19830,19831,
9559319832,19833,19834,19835,19836,19837,19838,19839,19840,19841,19842,19843,
9559419844,19845,19846,19847,19848,19849,19850,19851,19852,19853,19854,19855,
9559519856,19857,19858,19859,19860,19861,19862,19863,19864,19865,19866,19867,
9559619868,19869,19870,19871,19872,19873,19874,19875,19876,19877,19878,19879,
9559719880,19881,19882,19883,19884,19885,19886,19887,19888,19889,19890,19891,
9559819892,19893,19894,19895,19896,19897,19898,19899,19900,19901,19902,19903,
9559919904,19905,19906,19907,19908,19909,19910,19911,19912,19913,19914,19915,
9560019916,19917,19918,19919,19920,19921,19922,19923,19924,19925,19926,19927,
9560119928,19929,19930,19931,19932,19933,19934,19935,19936,19937,19938,19939,
9560219940,19941,19942,19943,19944,19945,19946,19947,19948,19949,19950,19951,
9560319952,19953,19954,19955,19956,19957,19958,19959,19960,19961,19962,19963,
9560419964,19965,19966,19967,19968,19969,19970,19971,19972,19973,19974,19975,
9560519976,19977,19978,19979,19980,19981,19982,19983,19984,19985,19986,19987,
9560619988,19989,19990,19991,19992,19993,19994,19995,19996,19997,19998,19999,
9560720000,20001,20002,20003,20004,20005,20006,20007,20008,20009,20010,20011,
9560820012,20013,20014,20015,20016,20017,20018,20019,20020,20021,20022,20023,
9560920024,20025,20026,20027,20028,20029,20030,20031,20032,20033,20034,20035,
9561020036,20037,20038,20039,20040,20041,20042,20043,20044,20045,20046,20047,
9561120048,20049,20050,20051,20052,20053,20054,20055,20056,20057,20058,20059,
9561220060,20061,20062,20063,20064,20065,20066,20067,20068,20069,20070,20071,
9561320072,20073,20074,20075,20076,20077,20078,20079,20080,20081,20082,20083,
9561420084,20085,20086,20087,20088,20089,20090,20091,20092,20093,20094,20095,
9561520096,20097,20098,20099,20100,20101,20102,20103,20104,20105,20106,20107,
9561620108,20109,20110,20111,20112,20113,20114,20115,20116,20117,20118,20119,
9561720120,20121,20122,20123,20124,20125,20126,20127,20128,20129,20130,20131,
9561820132,20133,20134,20135,20136,20137,20138,20139,20140,20141,20142,20143,
9561920144,20145,20146,20147,20148,20149,20150,20151,20152,20153,20154,20155,
9562020156,20157,20158,20159,20160,20161,20162,20163,20164,20165,20166,20167,
9562120168,20169,20170,20171,20172,20173,20174,20175,20176,20177,20178,20179,
9562220180,20181,20182,20183,20184,20185,20186,20187,20188,20189,20190,20191,
9562320192,20193,20194,20195,20196,20197,20198,20199,20200,20201,20202,20203,
9562420204,20205,20206,20207,20208,20209,20210,20211,20212,20213,20214,20215,
9562520216,20217,20218,20219,20220,20221,20222,20223,20224,20225,20226,20227,
9562620228,20229,20230,20231,20232,20233,20234,20235,20236,20237,20238,20239,
9562720240,20241,20242,20243,20244,20245,20246,20247,20248,20249,20250,20251,
9562820252,20253,20254,20255,20256,20257,20258,20259,20260,20261,20262,20263,
9562920264,20265,20266,20267,20268,20269,20270,20271,20272,20273,20274,20275,
9563020276,20277,20278,20279,20280,20281,20282,20283,20284,20285,20286,20287,
9563120288,20289,20290,20291,20292,20293,20294,20295,20296,20297,20298,20299,
9563220300,20301,20302,20303,20304,20305,20306,20307,20308,20309,20310,20311,
9563320312,20313,20314,20315,20316,20317,20318,20319,20320,20321,20322,20323,
9563420324,20325,20326,20327,20328,20329,20330,20331,20332,20333,20334,20335,
9563520336,20337,20338,20339,20340,20341,20342,20343,20344,20345,20346,20347,
9563620348,20349,20350,20351,20352,20353,20354,20355,20356,20357,20358,20359,
9563720360,20361,20362,20363,20364,20365,20366,20367,20368,20369,20370,20371,
9563820372,20373,20374,20375,20376,20377,20378,20379,20380,20381,20382,20383,
9563920384,20385,20386,20387,20388,20389,20390,20391,20392,20393,20394,20395,
9564020396,20397,20398,20399,20400,20401,20402,20403,20404,20405,20406,20407,
9564120408,20409,20410,20411,20412,20413,20414,20415,20416,20417,20418,20419,
9564220420,20421,20422,20423,20424,20425,20426,20427,20428,20429,20430,20431,
9564320432,20433,20434,20435,20436,20437,20438,20439,20440,20441,20442,20443,
9564420444,20445,20446,20447,20448,20449,20450,20451,20452,20453,20454,20455,
9564520456,20457,20458,20459,20460,20461,20462,20463,20464,20465,20466,20467,
9564620468,20469,20470,20471,20472,20473,20474,20475,20476,20477,20478,20479,
9564720480,20481,20482,20483,20484,20485,20486,20487,20488,20489,20490,20491,
9564820492,20493,20494,20495,20496,20497,20498,20499,20500,20501,20502,20503,
9564920504,20505,20506,20507,20508,20509,20510,20511,20512,20513,20514,20515,
9565020516,20517,20518,20519,20520,20521,20522,20523,20524,20525,20526,20527,
9565120528,20529,20530,20531,20532,20533,20534,20535,20536,20537,20538,20539,
9565220540,20541,20542,20543,20544,20545,20546,20547,20548,20549,20550,20551,
9565320552,20553,20554,20555,20556,20557,20558,20559,20560,20561,20562,20563,
9565420564,20565,20566,20567,20568,20569,20570,20571,20572,20573,20574,20575,
9565520576,20577,20578,20579,20580,20581,20582,20583,20584,20585,20586,20587,
9565620588,20589,20590,20591,20592,20593,20594,20595,20596,20597,20598,20599,
9565720600,20601,20602,20603,20604,20605,20606,20607,20608,20609,20610,20611,
9565820612,20613,20614,20615,20616,20617,20618,20619,20620,20621,20622,20623,
9565920624,20625,20626,20627,20628,20629,20630,20631,20632,20633,20634,20635,
9566020636,20637,20638,20639,20640,20641,20642,20643,20644,20645,20646,20647,
9566120648,20649,20650,20651,20652,20653,20654,20655,20656,20657,20658,20659,
9566220660,20661,20662,20663,20664,20665,20666,20667,20668,20669,20670,20671,
9566320672,20673,20674,20675,20676,20677,20678,20679,20680,20681,20682,20683,
9566420684,20685,20686,20687,20688,20689,20690,20691,20692,20693,20694,20695,
9566520696,20697,20698,20699,20700,20701,20702,20703,20704,20705,20706,20707,
9566620708,20709,20710,20711,20712,20713,20714,20715,20716,20717,20718,20719,
9566720720,20721,20722,20723,20724,20725,20726,20727,20728,20729,20730,20731,
9566820732,20733,20734,20735,20736,20737,20738,20739,20740,20741,20742,20743,
9566920744,20745,20746,20747,20748,20749,20750,20751,20752,20753,20754,20755,
9567020756,20757,20758,20759,20760,20761,20762,20763,20764,20765,20766,20767,
9567120768,20769,20770,20771,20772,20773,20774,20775,20776,20777,20778,20779,
9567220780,20781,20782,20783,20784,20785,20786,20787,20788,20789,20790,20791,
9567320792,20793,20794,20795,20796,20797,20798,20799,20800,20801,20802,20803,
9567420804,20805,20806,20807,20808,20809,20810,20811,20812,20813,20814,20815,
9567520816,20817,20818,20819,20820,20821,20822,20823,20824,20825,20826,20827,
9567620828,20829,20830,20831,20832,20833,20834,20835,20836,20837,20838,20839,
9567720840,20841,20842,20843,20844,20845,20846,20847,20848,20849,20850,20851,
9567820852,20853,20854,20855,20856,20857,20858,20859,20860,20861,20862,20863,
9567920864,20865,20866,20867,20868,20869,20870,20871,20872,20873,20874,20875,
9568020876,20877,20878,20879,20880,20881,20882,20883,20884,20885,20886,20887,
9568120888,20889,20890,20891,20892,20893,20894,20895,20896,20897,20898,20899,
9568220900,20901,20902,20903,20904,20905,20906,20907,20908,20909,20910,20911,
9568320912,20913,20914,20915,20916,20917,20918,20919,20920,20921,20922,20923,
9568420924,20925,20926,20927,20928,20929,20930,20931,20932,20933,20934,20935,
9568520936,20937,20938,20939,20940,20941,20942,20943,20944,20945,20946,20947,
9568620948,20949,20950,20951,20952,20953,20954,20955,20956,20957,20958,20959,
9568720960,20961,20962,20963,20964,20965,20966,20967,20968,20969,20970,20971,
9568820972,20973,20974,20975,20976,20977,20978,20979,20980,20981,20982,20983,
9568920984,20985,20986,20987,20988,20989,20990,20991,20992,20993,20994,20995,
9569020996,20997,20998,20999,21000,21001,21002,21003,21004,21005,21006,21007,
9569121008,21009,21010,21011,21012,21013,21014,21015,21016,21017,21018,21019,
9569221020,21021,21022,21023,21024,21025,21026,21027,21028,21029,21030,21031,
9569321032,21033,21034,21035,21036,21037,21038,21039,21040,21041,21042,21043,
9569421044,21045,21046,21047,21048,21049,21050,21051,21052,21053,21054,21055,
9569521056,21057,21058,21059,21060,21061,21062,21063,21064,21065,21066,21067,
9569621068,21069,21070,21071,21072,21073,21074,21075,21076,21077,21078,21079,
9569721080,21081,21082,21083,21084,21085,21086,21087,21088,21089,21090,21091,
9569821092,21093,21094,21095,21096,21097,21098,21099,21100,21101,21102,21103,
9569921104,21105,21106,21107,21108,21109,21110,21111,21112,21113,21114,21115,
9570021116,21117,21118,21119,21120,21121,21122,21123,21124,21125,21126,21127,
9570121128,21129,21130,21131,21132,21133,21134,21135,21136,21137,21138,21139,
9570221140,21141,21142,21143,21144,21145,21146,21147,21148,21149,21150,21151,
9570321152,21153,21154,21155,21156,21157,21158,21159,21160,21161,21162,21163,
9570421164,21165,21166,21167,21168,21169,21170,21171,21172,21173,21174,21175,
9570521176,21177,21178,21179,21180,21181,21182,21183,21184,21185,21186,21187,
9570621188,21189,21190,21191,21192,21193,21194,21195,21196,21197,21198,21199,
9570721200,21201,21202,21203,21204,21205,21206,21207,21208,21209,21210,21211,
9570821212,21213,21214,21215,21216,21217,21218,21219,21220,21221,21222,21223,
9570921224,21225,21226,21227,21228,21229,21230,21231,21232,21233,21234,21235,
9571021236,21237,21238,21239,21240,21241,21242,21243,21244,21245,21246,21247,
9571121248,21249,21250,21251,21252,21253,21254,21255,21256,21257,21258,21259,
9571221260,21261,21262,21263,21264,21265,21266,21267,21268,21269,21270,21271,
9571321272,21273,21274,21275,21276,21277,21278,21279,21280,21281,21282,21283,
9571421284,21285,21286,21287,21288,21289,21290,21291,21292,21293,21294,21295,
9571521296,21297,21298,21299,21300,21301,21302,21303,21304,21305,21306,21307,
9571621308,21309,21310,21311,21312,21313,21314,21315,21316,21317,21318,21319,
9571721320,21321,21322,21323,21324,21325,21326,21327,21328,21329,21330,21331,
9571821332,21333,21334,21335,21336,21337,21338,21339,21340,21341,21342,21343,
9571921344,21345,21346,21347,21348,21349,21350,21351,21352,21353,21354,21355,
9572021356,21357,21358,21359,21360,21361,21362,21363,21364,21365,21366,21367,
9572121368,21369,21370,21371,21372,21373,21374,21375,21376,21377,21378,21379,
9572221380,21381,21382,21383,21384,21385,21386,21387,21388,21389,21390,21391,
9572321392,21393,21394,21395,21396,21397,21398,21399,21400,21401,21402,21403,
9572421404,21405,21406,21407,21408,21409,21410,21411,21412,21413,21414,21415,
9572521416,21417,21418,21419,21420,21421,21422,21423,21424,21425,21426,21427,
9572621428,21429,21430,21431,21432,21433,21434,21435,21436,21437,21438,21439,
9572721440,21441,21442,21443,21444,21445,21446,21447,21448,21449,21450,21451,
9572821452,21453,21454,21455,21456,21457,21458,21459,21460,21461,21462,21463,
9572921464,21465,21466,21467,21468,21469,21470,21471,21472,21473,21474,21475,
9573021476,21477,21478,21479,21480,21481,21482,21483,21484,21485,21486,21487,
9573121488,21489,21490,21491,21492,21493,21494,21495,21496,21497,21498,21499,
9573221500,21501,21502,21503,21504,21505,21506,21507,21508,21509,21510,21511,
9573321512,21513,21514,21515,21516,21517,21518,21519,21520,21521,21522,21523,
9573421524,21525,21526,21527,21528,21529,21530,21531,21532,21533,21534,21535,
9573521536,21537,21538,21539,21540,21541,21542,21543,21544,21545,21546,21547,
9573621548,21549,21550,21551,21552,21553,21554,21555,21556,21557,21558,21559,
9573721560,21561,21562,21563,21564,21565,21566,21567,21568,21569,21570,21571,
9573821572,21573,21574,21575,21576,21577,21578,21579,21580,21581,21582,21583,
9573921584,21585,21586,21587,21588,21589,21590,21591,21592,21593,21594,21595,
9574021596,21597,21598,21599,21600,21601,21602,21603,21604,21605,21606,21607,
9574121608,21609,21610,21611,21612,21613,21614,21615,21616,21617,21618,21619,
9574221620,21621,21622,21623,21624,21625,21626,21627,21628,21629,21630,21631,
9574321632,21633,21634,21635,21636,21637,21638,21639,21640,21641,21642,21643,
9574421644,21645,21646,21647,21648,21649,21650,21651,21652,21653,21654,21655,
9574521656,21657,21658,21659,21660,21661,21662,21663,21664,21665,21666,21667,
9574621668,21669,21670,21671,21672,21673,21674,21675,21676,21677,21678,21679,
9574721680,21681,21682,21683,21684,21685,21686,21687,21688,21689,21690,21691,
9574821692,21693,21694,21695,21696,21697,21698,21699,21700,21701,21702,21703,
9574921704,21705,21706,21707,21708,21709,21710,21711,21712,21713,21714,21715,
9575021716,21717,21718,21719,21720,21721,21722,21723,21724,21725,21726,21727,
9575121728,21729,21730,21731,21732,21733,21734,21735,21736,21737,21738,21739,
9575221740,21741,21742,21743,21744,21745,21746,21747,21748,21749,21750,21751,
9575321752,21753,21754,21755,21756,21757,21758,21759,21760,21761,21762,21763,
9575421764,21765,21766,21767,21768,21769,21770,21771,21772,21773,21774,21775,
9575521776,21777,21778,21779,21780,21781,21782,21783,21784,21785,21786,21787,
9575621788,21789,21790,21791,21792,21793,21794,21795,21796,21797,21798,21799,
9575721800,21801,21802,21803,21804,21805,21806,21807,21808,21809,21810,21811,
9575821812,21813,21814,21815,21816,21817,21818,21819,21820,21821,21822,21823,
9575921824,21825,21826,21827,21828,21829,21830,21831,21832,21833,21834,21835,
9576021836,21837,21838,21839,21840,21841,21842,21843,21844,21845,21846,21847,
9576121848,21849,21850,21851,21852,21853,21854,21855,21856,21857,21858,21859,
9576221860,21861,21862,21863,21864,21865,21866,21867,21868,21869,21870,21871,
9576321872,21873,21874,21875,21876,21877,21878,21879,21880,21881,21882,21883,
9576421884,21885,21886,21887,21888,21889,21890,21891,21892,21893,21894,21895,
9576521896,21897,21898,21899,21900,21901,21902,21903,21904,21905,21906,21907,
9576621908,21909,21910,21911,21912,21913,21914,21915,21916,21917,21918,21919,
9576721920,21921,21922,21923,21924,21925,21926,21927,21928,21929,21930,21931,
9576821932,21933,21934,21935,21936,21937,21938,21939,21940,21941,21942,21943,
9576921944,21945,21946,21947,21948,21949,21950,21951,21952,21953,21954,21955,
9577021956,21957,21958,21959,21960,21961,21962,21963,21964,21965,21966,21967,
9577121968,21969,21970,21971,21972,21973,21974,21975,21976,21977,21978,21979,
9577221980,21981,21982,21983,21984,21985,21986,21987,21988,21989,21990,21991,
9577321992,21993,21994,21995,21996,21997,21998,21999,22000,22001,22002,22003,
9577422004,22005,22006,22007,22008,22009,22010,22011,22012,22013,22014,22015,
9577522016,22017,22018,22019,22020,22021,22022,22023,22024,22025,22026,22027,
9577622028,22029,22030,22031,22032,22033,22034,22035,22036,22037,22038,22039,
9577722040,22041,22042,22043,22044,22045,22046,22047,22048,22049,22050,22051,
9577822052,22053,22054,22055,22056,22057,22058,22059,22060,22061,22062,22063,
9577922064,22065,22066,22067,22068,22069,22070,22071,22072,22073,22074,22075,
9578022076,22077,22078,22079,22080,22081,22082,22083,22084,22085,22086,22087,
9578122088,22089,22090,22091,22092,22093,22094,22095,22096,22097,22098,22099,
9578222100,22101,22102,22103,22104,22105,22106,22107,22108,22109,22110,22111,
9578322112,22113,22114,22115,22116,22117,22118,22119,22120,22121,22122,22123,
9578422124,22125,22126,22127,22128,22129,22130,22131,22132,22133,22134,22135,
9578522136,22137,22138,22139,22140,22141,22142,22143,22144,22145,22146,22147,
9578622148,22149,22150,22151,22152,22153,22154,22155,22156,22157,22158,22159,
9578722160,22161,22162,22163,22164,22165,22166,22167,22168,22169,22170,22171,
9578822172,22173,22174,22175,22176,22177,22178,22179,22180,22181,22182,22183,
9578922184,22185,22186,22187,22188,22189,22190,22191,22192,22193,22194,22195,
9579022196,22197,22198,22199,22200,22201,22202,22203,22204,22205,22206,22207,
9579122208,22209,22210,22211,22212,22213,22214,22215,22216,22217,22218,22219,
9579222220,22221,22222,22223,22224,22225,22226,22227,22228,22229,22230,22231,
9579322232,22233,22234,22235,22236,22237,22238,22239,22240,22241,22242,22243,
9579422244,22245,22246,22247,22248,22249,22250,22251,22252,22253,22254,22255,
9579522256,22257,22258,22259,22260,22261,22262,22263,22264,22265,22266,22267,
9579622268,22269,22270,22271,22272,22273,22274,22275,22276,22277,22278,22279,
9579722280,22281,22282,22283,22284,22285,22286,22287,22288,22289,22290,22291,
9579822292,22293,22294,22295,22296,22297,22298,22299,22300,22301,22302,22303,
9579922304,22305,22306,22307,22308,22309,22310,22311,22312,22313,22314,22315,
9580022316,22317,22318,22319,22320,22321,22322,22323,22324,22325,22326,22327,
9580122328,22329,22330,22331,22332,22333,22334,22335,22336,22337,22338,22339,
9580222340,22341,22342,22343,22344,22345,22346,22347,22348,22349,22350,22351,
9580322352,22353,22354,22355,22356,22357,22358,22359,22360,22361,22362,22363,
9580422364,22365,22366,22367,22368,22369,22370,22371,22372,22373,22374,22375,
9580522376,22377,22378,22379,22380,22381,22382,22383,22384,22385,22386,22387,
9580622388,22389,22390,22391,22392,22393,22394,22395,22396,22397,22398,22399,
9580722400,22401,22402,22403,22404,22405,22406,22407,22408,22409,22410,22411,
9580822412,22413,22414,22415,22416,22417,22418,22419,22420,22421,22422,22423,
9580922424,22425,22426,22427,22428,22429,22430,22431,22432,22433,22434,22435,
9581022436,22437,22438,22439,22440,22441,22442,22443,22444,22445,22446,22447,
9581122448,22449,22450,22451,22452,22453,22454,22455,22456,22457,22458,22459,
9581222460,22461,22462,22463,22464,22465,22466,22467,22468,22469,22470,22471,
9581322472,22473,22474,22475,22476,22477,22478,22479,22480,22481,22482,22483,
9581422484,22485,22486,22487,22488,22489,22490,22491,22492,22493,22494,22495,
9581522496,22497,22498,22499,22500,22501,22502,22503,22504,22505,22506,22507,
9581622508,22509,22510,22511,22512,22513,22514,22515,22516,22517,22518,22519,
9581722520,22521,22522,22523,22524,22525,22526,22527,22528,22529,22530,22531,
9581822532,22533,22534,22535,22536,22537,22538,22539,22540,22541,22542,22543,
9581922544,22545,22546,22547,22548,22549,22550,22551,22552,22553,22554,22555,
9582022556,22557,22558,22559,22560,22561,22562,22563,22564,22565,22566,22567,
9582122568,22569,22570,22571,22572,22573,22574,22575,22576,22577,22578,22579,
9582222580,22581,22582,22583,22584,22585,22586,22587,22588,22589,22590,22591,
9582322592,22593,22594,22595,22596,22597,22598,22599,22600,22601,22602,22603,
9582422604,22605,22606,22607,22608,22609,22610,22611,22612,22613,22614,22615,
9582522616,22617,22618,22619,22620,22621,22622,22623,22624,22625,22626,22627,
9582622628,22629,22630,22631,22632,22633,22634,22635,22636,22637,22638,22639,
9582722640,22641,22642,22643,22644,22645,22646,22647,22648,22649,22650,22651,
9582822652,22653,22654,22655,22656,22657,22658,22659,22660,22661,22662,22663,
9582922664,22665,22666,22667,22668,22669,22670,22671,22672,22673,22674,22675,
9583022676,22677,22678,22679,22680,22681,22682,22683,22684,22685,22686,22687,
9583122688,22689,22690,22691,22692,22693,22694,22695,22696,22697,22698,22699,
9583222700,22701,22702,22703,22704,22705,22706,22707,22708,22709,22710,22711,
9583322712,22713,22714,22715,22716,22717,22718,22719,22720,22721,22722,22723,
9583422724,22725,22726,22727,22728,22729,22730,22731,22732,22733,22734,22735,
9583522736,22737,22738,22739,22740,22741,22742,22743,22744,22745,22746,22747,
9583622748,22749,22750,22751,22752,22753,22754,22755,22756,22757,22758,22759,
9583722760,22761,22762,22763,22764,22765,22766,22767,22768,22769,22770,22771,
9583822772,22773,22774,22775,22776,22777,22778,22779,22780,22781,22782,22783,
9583922784,22785,22786,22787,22788,22789,22790,22791,22792,22793,22794,22795,
9584022796,22797,22798,22799,22800,22801,22802,22803,22804,22805,22806,22807,
9584122808,22809,22810,22811,22812,22813,22814,22815,22816,22817,22818,22819,
9584222820,22821,22822,22823,22824,22825,22826,22827,22828,22829,22830,22831,
9584322832,22833,22834,22835,22836,22837,22838,22839,22840,22841,22842,22843,
9584422844,22845,22846,22847,22848,22849,22850,22851,22852,22853,22854,22855,
9584522856,22857,22858,22859,22860,22861,22862,22863,22864,22865,22866,22867,
9584622868,22869,22870,22871,22872,22873,22874,22875,22876,22877,22878,22879,
9584722880,22881,22882,22883,22884,22885,22886,22887,22888,22889,22890,22891,
9584822892,22893,22894,22895,22896,22897,22898,22899,22900,22901,22902,22903,
9584922904,22905,22906,22907,22908,22909,22910,22911,22912,22913,22914,22915,
9585022916,22917,22918,22919,22920,22921,22922,22923,22924,22925,22926,22927,
9585122928,22929,22930,22931,22932,22933,22934,22935,22936,22937,22938,22939,
9585222940,22941,22942,22943,22944,22945,22946,22947,22948,22949,22950,22951,
9585322952,22953,22954,22955,22956,22957,22958,22959,22960,22961,22962,22963,
9585422964,22965,22966,22967,22968,22969,22970,22971,22972,22973,22974,22975,
9585522976,22977,22978,22979,22980,22981,22982,22983,22984,22985,22986,22987,
9585622988,22989,22990,22991,22992,22993,22994,22995,22996,22997,22998,22999,
9585723000,23001,23002,23003,23004,23005,23006,23007,23008,23009,23010,23011,
9585823012,23013,23014,23015,23016,23017,23018,23019,23020,23021,23022,23023,
9585923024,23025,23026,23027,23028,23029,23030,23031,23032,23033,23034,23035,
9586023036,23037,23038,23039,23040,23041,23042,23043,23044,23045,23046,23047,
9586123048,23049,23050,23051,23052,23053,23054,23055,23056,23057,23058,23059,
9586223060,23061,23062,23063,23064,23065,23066,23067,23068,23069,23070,23071,
9586323072,23073,23074,23075,23076,23077,23078,23079,23080,23081,23082,23083,
9586423084,23085,23086,23087,23088,23089,23090,23091,23092,23093,23094,23095,
9586523096,23097,23098,23099,23100,23101,23102,23103,23104,23105,23106,23107,
9586623108,23109,23110,23111,23112,23113,23114,23115,23116,23117,23118,23119,
9586723120,23121,23122,23123,23124,23125,23126,23127,23128,23129,23130,23131,
9586823132,23133,23134,23135,23136,23137,23138,23139,23140,23141,23142,23143,
9586923144,23145,23146,23147,23148,23149,23150,23151,23152,23153,23154,23155,
9587023156,23157,23158,23159,23160,23161,23162,23163,23164,23165,23166,23167,
9587123168,23169,23170,23171,23172,23173,23174,23175,23176,23177,23178,23179,
9587223180,23181,23182,23183,23184,23185,23186,23187,23188,23189,23190,23191,
9587323192,23193,23194,23195,23196,23197,23198,23199,23200,23201,23202,23203,
9587423204,23205,23206,23207,23208,23209,23210,23211,23212,23213,23214,23215,
9587523216,23217,23218,23219,23220,23221,23222,23223,23224,23225,23226,23227,
9587623228,23229,23230,23231,23232,23233,23234,23235,23236,23237,23238,23239,
9587723240,23241,23242,23243,23244,23245,23246,23247,23248,23249,23250,23251,
9587823252,23253,23254,23255,23256,23257,23258,23259,23260,23261,23262,23263,
9587923264,23265,23266,23267,23268,23269,23270,23271,23272,23273,23274,23275,
9588023276,23277,23278,23279,23280,23281,23282,23283,23284,23285,23286,23287,
9588123288,23289,23290,23291,23292,23293,23294,23295,23296,23297,23298,23299,
9588223300,23301,23302,23303,23304,23305,23306,23307,23308,23309,23310,23311,
9588323312,23313,23314,23315,23316,23317,23318,23319,23320,23321,23322,23323,
9588423324,23325,23326,23327,23328,23329,23330,23331,23332,23333,23334,23335,
9588523336,23337,23338,23339,23340,23341,23342,23343,23344,23345,23346,23347,
9588623348,23349,23350,23351,23352,23353,23354,23355,23356,23357,23358,23359,
9588723360,23361,23362,23363,23364,23365,23366,23367,23368,23369,23370,23371,
9588823372,23373,23374,23375,23376,23377,23378,23379,23380,23381,23382,23383,
9588923384,23385,23386,23387,23388,23389,23390,23391,23392,23393,23394,23395,
9589023396,23397,23398,23399,23400,23401,23402,23403,23404,23405,23406,23407,
9589123408,23409,23410,23411,23412,23413,23414,23415,23416,23417,23418,23419,
9589223420,23421,23422,23423,23424,23425,23426,23427,23428,23429,23430,23431,
9589323432,23433,23434,23435,23436,23437,23438,23439,23440,23441,23442,23443,
9589423444,23445,23446,23447,23448,23449,23450,23451,23452,23453,23454,23455,
9589523456,23457,23458,23459,23460,23461,23462,23463,23464,23465,23466,23467,
9589623468,23469,23470,23471,23472,23473,23474,23475,23476,23477,23478,23479,
9589723480,23481,23482,23483,23484,23485,23486,23487,23488,23489,23490,23491,
9589823492,23493,23494,23495,23496,23497,23498,23499,23500,23501,23502,23503,
9589923504,23505,23506,23507,23508,23509,23510,23511,23512,23513,23514,23515,
9590023516,23517,23518,23519,23520,23521,23522,23523,23524,23525,23526,23527,
9590123528,23529,23530,23531,23532,23533,23534,23535,23536,23537,23538,23539,
9590223540,23541,23542,23543,23544,23545,23546,23547,23548,23549,23550,23551,
9590323552,23553,23554,23555,23556,23557,23558,23559,23560,23561,23562,23563,
9590423564,23565,23566,23567,23568,23569,23570,23571,23572,23573,23574,23575,
9590523576,23577,23578,23579,23580,23581,23582,23583,23584,23585,23586,23587,
9590623588,23589,23590,23591,23592,23593,23594,23595,23596,23597,23598,23599,
9590723600,23601,23602,23603,23604,23605,23606,23607,23608,23609,23610,23611,
9590823612,23613,23614,23615,23616,23617,23618,23619,23620,23621,23622,23623,
9590923624,23625,23626,23627,23628,23629,23630,23631,23632,23633,23634,23635,
9591023636,23637,23638,23639,23640,23641,23642,23643,23644,23645,23646,23647,
9591123648,23649,23650,23651,23652,23653,23654,23655,23656,23657,23658,23659,
9591223660,23661,23662,23663,23664,23665,23666,23667,23668,23669,23670,23671,
9591323672,23673,23674,23675,23676,23677,23678,23679,23680,23681,23682,23683,
9591423684,23685,23686,23687,23688,23689,23690,23691,23692,23693,23694,23695,
9591523696,23697,23698,23699,23700,23701,23702,23703,23704,23705,23706,23707,
9591623708,23709,23710,23711,23712,23713,23714,23715,23716,23717,23718,23719,
9591723720,23721,23722,23723,23724,23725,23726,23727,23728,23729,23730,23731,
9591823732,23733,23734,23735,23736,23737,23738,23739,23740,23741,23742,23743,
9591923744,23745,23746,23747,23748,23749,23750,23751,23752,23753,23754,23755,
9592023756,23757,23758,23759,23760,23761,23762,23763,23764,23765,23766,23767,
9592123768,23769,23770,23771,23772,23773,23774,23775,23776,23777,23778,23779,
9592223780,23781,23782,23783,23784,23785,23786,23787,23788,23789,23790,23791,
9592323792,23793,23794,23795,23796,23797,23798,23799,23800,23801,23802,23803,
9592423804,23805,23806,23807,23808,23809,23810,23811,23812,23813,23814,23815,
9592523816,23817,23818,23819,23820,23821,23822,23823,23824,23825,23826,23827,
9592623828,23829,23830,23831,23832,23833,23834,23835,23836,23837,23838,23839,
9592723840,23841,23842,23843,23844,23845,23846,23847,23848,23849,23850,23851,
9592823852,23853,23854,23855,23856,23857,23858,23859,23860,23861,23862,23863,
9592923864,23865,23866,23867,23868,23869,23870,23871,23872,23873,23874,23875,
9593023876,23877,23878,23879,23880,23881,23882,23883,23884,23885,23886,23887,
9593123888,23889,23890,23891,23892,23893,23894,23895,23896,23897,23898,23899,
9593223900,23901,23902,23903,23904,23905,23906,23907,23908,23909,23910,23911,
9593323912,23913,23914,23915,23916,23917,23918,23919,23920,23921,23922,23923,
9593423924,23925,23926,23927,23928,23929,23930,23931,23932,23933,23934,23935,
9593523936,23937,23938,23939,23940,23941,23942,23943,23944,23945,23946,23947,
9593623948,23949,23950,23951,23952,23953,23954,23955,23956,23957,23958,23959,
9593723960,23961,23962,23963,23964,23965,23966,23967,23968,23969,23970,23971,
9593823972,23973,23974,23975,23976,23977,23978,23979,23980,23981,23982,23983,
9593923984,23985,23986,23987,23988,23989,23990,23991,23992,23993,23994,23995,
9594023996,23997,23998,23999,24000,24001,24002,24003,24004,24005,24006,24007,
9594124008,24009,24010,24011,24012,24013,24014,24015,24016,24017,24018,24019,
9594224020,24021,24022,24023,24024,24025,24026,24027,24028,24029,24030,24031,
9594324032,24033,24034,24035,24036,24037,24038,24039,24040,24041,24042,24043,
9594424044,24045,24046,24047,24048,24049,24050,24051,24052,24053,24054,24055,
9594524056,24057,24058,24059,24060,24061,24062,24063,24064,24065,24066,24067,
9594624068,24069,24070,24071,24072,24073,24074,24075,24076,24077,24078,24079,
9594724080,24081,24082,24083,24084,24085,24086,24087,24088,24089,24090,24091,
9594824092,24093,24094,24095,24096,24097,24098,24099,24100,24101,24102,24103,
9594924104,24105,24106,24107,24108,24109,24110,24111,24112,24113,24114,24115,
9595024116,24117,24118,24119,24120,24121,24122,24123,24124,24125,24126,24127,
9595124128,24129,24130,24131,24132,24133,24134,24135,24136,24137,24138,24139,
9595224140,24141,24142,24143,24144,24145,24146,24147,24148,24149,24150,24151,
9595324152,24153,24154,24155,24156,24157,24158,24159,24160,24161,24162,24163,
9595424164,24165,24166,24167,24168,24169,24170,24171,24172,24173,24174,24175,
9595524176,24177,24178,24179,24180,24181,24182,24183,24184,24185,24186,24187,
9595624188,24189,24190,24191,24192,24193,24194,24195,24196,24197,24198,24199,
9595724200,24201,24202,24203,24204,24205,24206,24207,24208,24209,24210,24211,
9595824212,24213,24214,24215,24216,24217,24218,24219,24220,24221,24222,24223,
9595924224,24225,24226,24227,24228,24229,24230,24231,24232,24233,24234,24235,
9596024236,24237,24238,24239,24240,24241,24242,24243,24244,24245,24246,24247,
9596124248,24249,24250,24251,24252,24253,24254,24255,24256,24257,24258,24259,
9596224260,24261,24262,24263,24264,24265,24266,24267,24268,24269,24270,24271,
9596324272,24273,24274,24275,24276,24277,24278,24279,24280,24281,24282,24283,
9596424284,24285,24286,24287,24288,24289,24290,24291,24292,24293,24294,24295,
9596524296,24297,24298,24299,24300,24301,24302,24303,24304,24305,24306,24307,
9596624308,24309,24310,24311,24312,24313,24314,24315,24316,24317,24318,24319,
9596724320,24321,24322,24323,24324,24325,24326,24327,24328,24329,24330,24331,
9596824332,24333,24334,24335,24336,24337,24338,24339,24340,24341,24342,24343,
9596924344,24345,24346,24347,24348,24349,24350,24351,24352,24353,24354,24355,
9597024356,24357,24358,24359,24360,24361,24362,24363,24364,24365,24366,24367,
9597124368,24369,24370,24371,24372,24373,24374,24375,24376,24377,24378,24379,
9597224380,24381,24382,24383,24384,24385,24386,24387,24388,24389,24390,24391,
9597324392,24393,24394,24395,24396,24397,24398,24399,24400,24401,24402,24403,
9597424404,24405,24406,24407,24408,24409,24410,24411,24412,24413,24414,24415,
9597524416,24417,24418,24419,24420,24421,24422,24423,24424,24425,24426,24427,
9597624428,24429,24430,24431,24432,24433,24434,24435,24436,24437,24438,24439,
9597724440,24441,24442,24443,24444,24445,24446,24447,24448,24449,24450,24451,
9597824452,24453,24454,24455,24456,24457,24458,24459,24460,24461,24462,24463,
9597924464,24465,24466,24467,24468,24469,24470,24471,24472,24473,24474,24475,
9598024476,24477,24478,24479,24480,24481,24482,24483,24484,24485,24486,24487,
9598124488,24489,24490,24491,24492,24493,24494,24495,24496,24497,24498,24499,
9598224500,24501,24502,24503,24504,24505,24506,24507,24508,24509,24510,24511,
9598324512,24513,24514,24515,24516,24517,24518,24519,24520,24521,24522,24523,
9598424524,24525,24526,24527,24528,24529,24530,24531,24532,24533,24534,24535,
9598524536,24537,24538,24539,24540,24541,24542,24543,24544,24545,24546,24547,
9598624548,24549,24550,24551,24552,24553,24554,24555,24556,24557,24558,24559,
9598724560,24561,24562,24563,24564,24565,24566,24567,24568,24569,24570,24571,
9598824572,24573,24574,24575,24576,24577,24578,24579,24580,24581,24582,24583,
9598924584,24585,24586,24587,24588,24589,24590,24591,24592,24593,24594,24595,
9599024596,24597,24598,24599,24600,24601,24602,24603,24604,24605,24606,24607,
9599124608,24609,24610,24611,24612,24613,24614,24615,24616,24617,24618,24619,
9599224620,24621,24622,24623,24624,24625,24626,24627,24628,24629,24630,24631,
9599324632,24633,24634,24635,24636,24637,24638,24639,24640,24641,24642,24643,
9599424644,24645,24646,24647,24648,24649,24650,24651,24652,24653,24654,24655,
9599524656,24657,24658,24659,24660,24661,24662,24663,24664,24665,24666,24667,
9599624668,24669,24670,24671,24672,24673,24674,24675,24676,24677,24678,24679,
9599724680,24681,24682,24683,24684,24685,24686,24687,24688,24689,24690,24691,
9599824692,24693,24694,24695,24696,24697,24698,24699,24700,24701,24702,24703,
9599924704,24705,24706,24707,24708,24709,24710,24711,24712,24713,24714,24715,
9600024716,24717,24718,24719,24720,24721,24722,24723,24724,24725,24726,24727,
9600124728,24729,24730,24731,24732,24733,24734,24735,24736,24737,24738,24739,
9600224740,24741,24742,24743,24744,24745,24746,24747,24748,24749,24750,24751,
9600324752,24753,24754,24755,24756,24757,24758,24759,24760,24761,24762,24763,
9600424764,24765,24766,24767,24768,24769,24770,24771,24772,24773,24774,24775,
9600524776,24777,24778,24779,24780,24781,24782,24783,24784,24785,24786,24787,
9600624788,24789,24790,24791,24792,24793,24794,24795,24796,24797,24798,24799,
9600724800,24801,24802,24803,24804,24805,24806,24807,24808,24809,24810,24811,
9600824812,24813,24814,24815,24816,24817,24818,24819,24820,24821,24822,24823,
9600924824,24825,24826,24827,24828,24829,24830,24831,24832,24833,24834,24835,
9601024836,24837,24838,24839,24840,24841,24842,24843,24844,24845,24846,24847,
9601124848,24849,24850,24851,24852,24853,24854,24855,24856,24857,24858,24859,
9601224860,24861,24862,24863,24864,24865,24866,24867,24868,24869,24870,24871,
9601324872,24873,24874,24875,24876,24877,24878,24879,24880,24881,24882,24883,
9601424884,24885,24886,24887,24888,24889,24890,24891,24892,24893,24894,24895,
9601524896,24897,24898,24899,24900,24901,24902,24903,24904,24905,24906,24907,
9601624908,24909,24910,24911,24912,24913,24914,24915,24916,24917,24918,24919,
9601724920,24921,24922,24923,24924,24925,24926,24927,24928,24929,24930,24931,
9601824932,24933,24934,24935,24936,24937,24938,24939,24940,24941,24942,24943,
9601924944,24945,24946,24947,24948,24949,24950,24951,24952,24953,24954,24955,
9602024956,24957,24958,24959,24960,24961,24962,24963,24964,24965,24966,24967,
9602124968,24969,24970,24971,24972,24973,24974,24975,24976,24977,24978,24979,
9602224980,24981,24982,24983,24984,24985,24986,24987,24988,24989,24990,24991,
9602324992,24993,24994,24995,24996,24997,24998,24999,25000,25001,25002,25003,
9602425004,25005,25006,25007,25008,25009,25010,25011,25012,25013,25014,25015,
9602525016,25017,25018,25019,25020,25021,25022,25023,25024,25025,25026,25027,
9602625028,25029,25030,25031,25032,25033,25034,25035,25036,25037,25038,25039,
9602725040,25041,25042,25043,25044,25045,25046,25047,25048,25049,25050,25051,
9602825052,25053,25054,25055,25056,25057,25058,25059,25060,25061,25062,25063,
9602925064,25065,25066,25067,25068,25069,25070,25071,25072,25073,25074,25075,
9603025076,25077,25078,25079,25080,25081,25082,25083,25084,25085,25086,25087,
9603125088,25089,25090,25091,25092,25093,25094,25095,25096,25097,25098,25099,
9603225100,25101,25102,25103,25104,25105,25106,25107,25108,25109,25110,25111,
9603325112,25113,25114,25115,25116,25117,25118,25119,25120,25121,25122,25123,
9603425124,25125,25126,25127,25128,25129,25130,25131,25132,25133,25134,25135,
9603525136,25137,25138,25139,25140,25141,25142,25143,25144,25145,25146,25147,
9603625148,25149,25150,25151,25152,25153,25154,25155,25156,25157,25158,25159,
9603725160,25161,25162,25163,25164,25165,25166,25167,25168,25169,25170,25171,
9603825172,25173,25174,25175,25176,25177,25178,25179,25180,25181,25182,25183,
9603925184,25185,25186,25187,25188,25189,25190,25191,25192,25193,25194,25195,
9604025196,25197,25198,25199,25200,25201,25202,25203,25204,25205,25206,25207,
9604125208,25209,25210,25211,25212,25213,25214,25215,25216,25217,25218,25219,
9604225220,25221,25222,25223,25224,25225,25226,25227,25228,25229,25230,25231,
9604325232,25233,25234,25235,25236,25237,25238,25239,25240,25241,25242,25243,
9604425244,25245,25246,25247,25248,25249,25250,25251,25252,25253,25254,25255,
9604525256,25257,25258,25259,25260,25261,25262,25263,25264,25265,25266,25267,
9604625268,25269,25270,25271,25272,25273,25274,25275,25276,25277,25278,25279,
9604725280,25281,25282,25283,25284,25285,25286,25287,25288,25289,25290,25291,
9604825292,25293,25294,25295,25296,25297,25298,25299,25300,25301,25302,25303,
9604925304,25305,25306,25307,25308,25309,25310,25311,25312,25313,25314,25315,
9605025316,25317,25318,25319,25320,25321,25322,25323,25324,25325,25326,25327,
9605125328,25329,25330,25331,25332,25333,25334,25335,25336,25337,25338,25339,
9605225340,25341,25342,25343,25344,25345,25346,25347,25348,25349,25350,25351,
9605325352,25353,25354,25355,25356,25357,25358,25359,25360,25361,25362,25363,
9605425364,25365,25366,25367,25368,25369,25370,25371,25372,25373,25374,25375,
9605525376,25377,25378,25379,25380,25381,25382,25383,25384,25385,25386,25387,
9605625388,25389,25390,25391,25392,25393,25394,25395,25396,25397,25398,25399,
9605725400,25401,25402,25403,25404,25405,25406,25407,25408,25409,25410,25411,
9605825412,25413,25414,25415,25416,25417,25418,25419,25420,25421,25422,25423,
9605925424,25425,25426,25427,25428,25429,25430,25431,25432,25433,25434,25435,
9606025436,25437,25438,25439,25440,25441,25442,25443,25444,25445,25446,25447,
9606125448,25449,25450,25451,25452,25453,25454,25455,25456,25457,25458,25459,
9606225460,25461,25462,25463,25464,25465,25466,25467,25468,25469,25470,25471,
9606325472,25473,25474,25475,25476,25477,25478,25479,25480,25481,25482,25483,
9606425484,25485,25486,25487,25488,25489,25490,25491,25492,25493,25494,25495,
9606525496,25497,25498,25499,25500,25501,25502,25503,25504,25505,25506,25507,
9606625508,25509,25510,25511,25512,25513,25514,25515,25516,25517,25518,25519,
9606725520,25521,25522,25523,25524,25525,25526,25527,25528,25529,25530,25531,
9606825532,25533,25534,25535,25536,25537,25538,25539,25540,25541,25542,25543,
9606925544,25545,25546,25547,25548,25549,25550,25551,25552,25553,25554,25555,
9607025556,25557,25558,25559,25560,25561,25562,25563,25564,25565,25566,25567,
9607125568,25569,25570,25571,25572,25573,25574,25575,25576,25577,25578,25579,
9607225580,25581,25582,25583,25584,25585,25586,25587,25588,25589,25590,25591,
9607325592,25593,25594,25595,25596,25597,25598,25599,25600,25601,25602,25603,
9607425604,25605,25606,25607,25608,25609,25610,25611,25612,25613,25614,25615,
9607525616,25617,25618,25619,25620,25621,25622,25623,25624,25625,25626,25627,
9607625628,25629,25630,25631,25632,25633,25634,25635,25636,25637,25638,25639,
9607725640,25641,25642,25643,25644,25645,25646,25647,25648,25649,25650,25651,
9607825652,25653,25654,25655,25656,25657,25658,25659,25660,25661,25662,25663,
9607925664,25665,25666,25667,25668,25669,25670,25671,25672,25673,25674,25675,
9608025676,25677,25678,25679,25680,25681,25682,25683,25684,25685,25686,25687,
9608125688,25689,25690,25691,25692,25693,25694,25695,25696,25697,25698,25699,
9608225700,25701,25702,25703,25704,25705,25706,25707,25708,25709,25710,25711,
9608325712,25713,25714,25715,25716,25717,25718,25719,25720,25721,25722,25723,
9608425724,25725,25726,25727,25728,25729,25730,25731,25732,25733,25734,25735,
9608525736,25737,25738,25739,25740,25741,25742,25743,25744,25745,25746,25747,
9608625748,25749,25750,25751,25752,25753,25754,25755,25756,25757,25758,25759,
9608725760,25761,25762,25763,25764,25765,25766,25767,25768,25769,25770,25771,
9608825772,25773,25774,25775,25776,25777,25778,25779,25780,25781,25782,25783,
9608925784,25785,25786,25787,25788,25789,25790,25791,25792,25793,25794,25795,
9609025796,25797,25798,25799,25800,25801,25802,25803,25804,25805,25806,25807,
9609125808,25809,25810,25811,25812,25813,25814,25815,25816,25817,25818,25819,
9609225820,25821,25822,25823,25824,25825,25826,25827,25828,25829,25830,25831,
9609325832,25833,25834,25835,25836,25837,25838,25839,25840,25841,25842,25843,
9609425844,25845,25846,25847,25848,25849,25850,25851,25852,25853,25854,25855,
9609525856,25857,25858,25859,25860,25861,25862,25863,25864,25865,25866,25867,
9609625868,25869,25870,25871,25872,25873,25874,25875,25876,25877,25878,25879,
9609725880,25881,25882,25883,25884,25885,25886,25887,25888,25889,25890,25891,
9609825892,25893,25894,25895,25896,25897,25898,25899,25900,25901,25902,25903,
9609925904,25905,25906,25907,25908,25909,25910,25911,25912,25913,25914,25915,
9610025916,25917,25918,25919,25920,25921,25922,25923,25924,25925,25926,25927,
9610125928,25929,25930,25931,25932,25933,25934,25935,25936,25937,25938,25939,
9610225940,25941,25942,25943,25944,25945,25946,25947,25948,25949,25950,25951,
9610325952,25953,25954,25955,25956,25957,25958,25959,25960,25961,25962,25963,
9610425964,25965,25966,25967,25968,25969,25970,25971,25972,25973,25974,25975,
9610525976,25977,25978,25979,25980,25981,25982,25983,25984,25985,25986,25987,
9610625988,25989,25990,25991,25992,25993,25994,25995,25996,25997,25998,25999,
9610726000,26001,26002,26003,26004,26005,26006,26007,26008,26009,26010,26011,
9610826012,26013,26014,26015,26016,26017,26018,26019,26020,26021,26022,26023,
9610926024,26025,26026,26027,26028,26029,26030,26031,26032,26033,26034,26035,
9611026036,26037,26038,26039,26040,26041,26042,26043,26044,26045,26046,26047,
9611126048,26049,26050,26051,26052,26053,26054,26055,26056,26057,26058,26059,
9611226060,26061,26062,26063,26064,26065,26066,26067,26068,26069,26070,26071,
9611326072,26073,26074,26075,26076,26077,26078,26079,26080,26081,26082,26083,
9611426084,26085,26086,26087,26088,26089,26090,26091,26092,26093,26094,26095,
9611526096,26097,26098,26099,26100,26101,26102,26103,26104,26105,26106,26107,
9611626108,26109,26110,26111,26112,26113,26114,26115,26116,26117,26118,26119,
9611726120,26121,26122,26123,26124,26125,26126,26127,26128,26129,26130,26131,
9611826132,26133,26134,26135,26136,26137,26138,26139,26140,26141,26142,26143,
9611926144,26145,26146,26147,26148,26149,26150,26151,26152,26153,26154,26155,
9612026156,26157,26158,26159,26160,26161,26162,26163,26164,26165,26166,26167,
9612126168,26169,26170,26171,26172,26173,26174,26175,26176,26177,26178,26179,
9612226180,26181,26182,26183,26184,26185,26186,26187,26188,26189,26190,26191,
9612326192,26193,26194,26195,26196,26197,26198,26199,26200,26201,26202,26203,
9612426204,26205,26206,26207,26208,26209,26210,26211,26212,26213,26214,26215,
9612526216,26217,26218,26219,26220,26221,26222,26223,26224,26225,26226,26227,
9612626228,26229,26230,26231,26232,26233,26234,26235,26236,26237,26238,26239,
9612726240,26241,26242,26243,26244,26245,26246,26247,26248,26249,26250,26251,
9612826252,26253,26254,26255,26256,26257,26258,26259,26260,26261,26262,26263,
9612926264,26265,26266,26267,26268,26269,26270,26271,26272,26273,26274,26275,
9613026276,26277,26278,26279,26280,26281,26282,26283,26284,26285,26286,26287,
9613126288,26289,26290,26291,26292,26293,26294,26295,26296,26297,26298,26299,
9613226300,26301,26302,26303,26304,26305,26306,26307,26308,26309,26310,26311,
9613326312,26313,26314,26315,26316,26317,26318,26319,26320,26321,26322,26323,
9613426324,26325,26326,26327,26328,26329,26330,26331,26332,26333,26334,26335,
9613526336,26337,26338,26339,26340,26341,26342,26343,26344,26345,26346,26347,
9613626348,26349,26350,26351,26352,26353,26354,26355,26356,26357,26358,26359,
9613726360,26361,26362,26363,26364,26365,26366,26367,26368,26369,26370,26371,
9613826372,26373,26374,26375,26376,26377,26378,26379,26380,26381,26382,26383,
9613926384,26385,26386,26387,26388,26389,26390,26391,26392,26393,26394,26395,
9614026396,26397,26398,26399,26400,26401,26402,26403,26404,26405,26406,26407,
9614126408,26409,26410,26411,26412,26413,26414,26415,26416,26417,26418,26419,
9614226420,26421,26422,26423,26424,26425,26426,26427,26428,26429,26430,26431,
9614326432,26433,26434,26435,26436,26437,26438,26439,26440,26441,26442,26443,
9614426444,26445,26446,26447,26448,26449,26450,26451,26452,26453,26454,26455,
9614526456,26457,26458,26459,26460,26461,26462,26463,26464,26465,26466,26467,
9614626468,26469,26470,26471,26472,26473,26474,26475,26476,26477,26478,26479,
9614726480,26481,26482,26483,26484,26485,26486,26487,26488,26489,26490,26491,
9614826492,26493,26494,26495,26496,26497,26498,26499,26500,26501,26502,26503,
9614926504,26505,26506,26507,26508,26509,26510,26511,26512,26513,26514,26515,
9615026516,26517,26518,26519,26520,26521,26522,26523,26524,26525,26526,26527,
9615126528,26529,26530,26531,26532,26533,26534,26535,26536,26537,26538,26539,
9615226540,26541,26542,26543,26544,26545,26546,26547,26548,26549,26550,26551,
9615326552,26553,26554,26555,26556,26557,26558,26559,26560,26561,26562,26563,
9615426564,26565,26566,26567,26568,26569,26570,26571,26572,26573,26574,26575,
9615526576,26577,26578,26579,26580,26581,26582,26583,26584,26585,26586,26587,
9615626588,26589,26590,26591,26592,26593,26594,26595,26596,26597,26598,26599,
9615726600,26601,26602,26603,26604,26605,26606,26607,26608,26609,26610,26611,
9615826612,26613,26614,26615,26616,26617,26618,26619,26620,26621,26622,26623,
9615926624,26625,26626,26627,26628,26629,26630,26631,26632,26633,26634,26635,
9616026636,26637,26638,26639,26640,26641,26642,26643,26644,26645,26646,26647,
9616126648,26649,26650,26651,26652,26653,26654,26655,26656,26657,26658,26659,
9616226660,26661,26662,26663,26664,26665,26666,26667,26668,26669,26670,26671,
9616326672,26673,26674,26675,26676,26677,26678,26679,26680,26681,26682,26683,
9616426684,26685,26686,26687,26688,26689,26690,26691,26692,26693,26694,26695,
9616526696,26697,26698,26699,26700,26701,26702,26703,26704,26705,26706,26707,
9616626708,26709,26710,26711,26712,26713,26714,26715,26716,26717,26718,26719,
9616726720,26721,26722,26723,26724,26725,26726,26727,26728,26729,26730,26731,
9616826732,26733,26734,26735,26736,26737,26738,26739,26740,26741,26742,26743,
9616926744,26745,26746,26747,26748,26749,26750,26751,26752,26753,26754,26755,
9617026756,26757,26758,26759,26760,26761,26762,26763,26764,26765,26766,26767,
9617126768,26769,26770,26771,26772,26773,26774,26775,26776,26777,26778,26779,
9617226780,26781,26782,26783,26784,26785,26786,26787,26788,26789,26790,26791,
9617326792,26793,26794,26795,26796,26797,26798,26799,26800,26801,26802,26803,
9617426804,26805,26806,26807,26808,26809,26810,26811,26812,26813,26814,26815,
9617526816,26817,26818,26819,26820,26821,26822,26823,26824,26825,26826,26827,
9617626828,26829,26830,26831,26832,26833,26834,26835,26836,26837,26838,26839,
9617726840,26841,26842,26843,26844,26845,26846,26847,26848,26849,26850,26851,
9617826852,26853,26854,26855,26856,26857,26858,26859,26860,26861,26862,26863,
9617926864,26865,26866,26867,26868,26869,26870,26871,26872,26873,26874,26875,
9618026876,26877,26878,26879,26880,26881,26882,26883,26884,26885,26886,26887,
9618126888,26889,26890,26891,26892,26893,26894,26895,26896,26897,26898,26899,
9618226900,26901,26902,26903,26904,26905,26906,26907,26908,26909,26910,26911,
9618326912,26913,26914,26915,26916,26917,26918,26919,26920,26921,26922,26923,
9618426924,26925,26926,26927,26928,26929,26930,26931,26932,26933,26934,26935,
9618526936,26937,26938,26939,26940,26941,26942,26943,26944,26945,26946,26947,
9618626948,26949,26950,26951,26952,26953,26954,26955,26956,26957,26958,26959,
9618726960,26961,26962,26963,26964,26965,26966,26967,26968,26969,26970,26971,
9618826972,26973,26974,26975,26976,26977,26978,26979,26980,26981,26982,26983,
9618926984,26985,26986,26987,26988,26989,26990,26991,26992,26993,26994,26995,
9619026996,26997,26998,26999,27000,27001,27002,27003,27004,27005,27006,27007,
9619127008,27009,27010,27011,27012,27013,27014,27015,27016,27017,27018,27019,
9619227020,27021,27022,27023,27024,27025,27026,27027,27028,27029,27030,27031,
9619327032,27033,27034,27035,27036,27037,27038,27039,27040,27041,27042,27043,
9619427044,27045,27046,27047,27048,27049,27050,27051,27052,27053,27054,27055,
9619527056,27057,27058,27059,27060,27061,27062,27063,27064,27065,27066,27067,
9619627068,27069,27070,27071,27072,27073,27074,27075,27076,27077,27078,27079,
9619727080,27081,27082,27083,27084,27085,27086,27087,27088,27089,27090,27091,
9619827092,27093,27094,27095,27096,27097,27098,27099,27100,27101,27102,27103,
9619927104,27105,27106,27107,27108,27109,27110,27111,27112,27113,27114,27115,
9620027116,27117,27118,27119,27120,27121,27122,27123,27124,27125,27126,27127,
9620127128,27129,27130,27131,27132,27133,27134,27135,27136,27137,27138,27139,
9620227140,27141,27142,27143,27144,27145,27146,27147,27148,27149,27150,27151,
9620327152,27153,27154,27155,27156,27157,27158,27159,27160,27161,27162,27163,
9620427164,27165,27166,27167,27168,27169,27170,27171,27172,27173,27174,27175,
9620527176,27177,27178,27179,27180,27181,27182,27183,27184,27185,27186,27187,
9620627188,27189,27190,27191,27192,27193,27194,27195,27196,27197,27198,27199,
9620727200,27201,27202,27203,27204,27205,27206,27207,27208,27209,27210,27211,
9620827212,27213,27214,27215,27216,27217,27218,27219,27220,27221,27222,27223,
9620927224,27225,27226,27227,27228,27229,27230,27231,27232,27233,27234,27235,
9621027236,27237,27238,27239,27240,27241,27242,27243,27244,27245,27246,27247,
9621127248,27249,27250,27251,27252,27253,27254,27255,27256,27257,27258,27259,
9621227260,27261,27262,27263,27264,27265,27266,27267,27268,27269,27270,27271,
9621327272,27273,27274,27275,27276,27277,27278,27279,27280,27281,27282,27283,
9621427284,27285,27286,27287,27288,27289,27290,27291,27292,27293,27294,27295,
9621527296,27297,27298,27299,27300,27301,27302,27303,27304,27305,27306,27307,
9621627308,27309,27310,27311,27312,27313,27314,27315,27316,27317,27318,27319,
9621727320,27321,27322,27323,27324,27325,27326,27327,27328,27329,27330,27331,
9621827332,27333,27334,27335,27336,27337,27338,27339,27340,27341,27342,27343,
9621927344,27345,27346,27347,27348,27349,27350,27351,27352,27353,27354,27355,
9622027356,27357,27358,27359,27360,27361,27362,27363,27364,27365,27366,27367,
9622127368,27369,27370,27371,27372,27373,27374,27375,27376,27377,27378,27379,
9622227380,27381,27382,27383,27384,27385,27386,27387,27388,27389,27390,27391,
9622327392,27393,27394,27395,27396,27397,27398,27399,27400,27401,27402,27403,
9622427404,27405,27406,27407,27408,27409,27410,27411,27412,27413,27414,27415,
9622527416,27417,27418,27419,27420,27421,27422,27423,27424,27425,27426,27427,
9622627428,27429,27430,27431,27432,27433,27434,27435,27436,27437,27438,27439,
9622727440,27441,27442,27443,27444,27445,27446,27447,27448,27449,27450,27451,
9622827452,27453,27454,27455,27456,27457,27458,27459,27460,27461,27462,27463,
9622927464,27465,27466,27467,27468,27469,27470,27471,27472,27473,27474,27475,
9623027476,27477,27478,27479,27480,27481,27482,27483,27484,27485,27486,27487,
9623127488,27489,27490,27491,27492,27493,27494,27495,27496,27497,27498,27499,
9623227500,27501,27502,27503,27504,27505,27506,27507,27508,27509,27510,27511,
9623327512,27513,27514,27515,27516,27517,27518,27519,27520,27521,27522,27523,
9623427524,27525,27526,27527,27528,27529,27530,27531,27532,27533,27534,27535,
9623527536,27537,27538,27539,27540,27541,27542,27543,27544,27545,27546,27547,
9623627548,27549,27550,27551,27552,27553,27554,27555,27556,27557,27558,27559,
9623727560,27561,27562,27563,27564,27565,27566,27567,27568,27569,27570,27571,
9623827572,27573,27574,27575,27576,27577,27578,27579,27580,27581,27582,27583,
9623927584,27585,27586,27587,27588,27589,27590,27591,27592,27593,27594,27595,
9624027596,27597,27598,27599,27600,27601,27602,27603,27604,27605,27606,27607,
9624127608,27609,27610,27611,27612,27613,27614,27615,27616,27617,27618,27619,
9624227620,27621,27622,27623,27624,27625,27626,27627,27628,27629,27630,27631,
9624327632,27633,27634,27635,27636,27637,27638,27639,27640,27641,27642,27643,
9624427644,27645,27646,27647,27648,27649,27650,27651,27652,27653,27654,27655,
9624527656,27657,27658,27659,27660,27661,27662,27663,27664,27665,27666,27667,
9624627668,27669,27670,27671,27672,27673,27674,27675,27676,27677,27678,27679,
9624727680,27681,27682,27683,27684,27685,27686,27687,27688,27689,27690,27691,
9624827692,27693,27694,27695,27696,27697,27698,27699,27700,27701,27702,27703,
9624927704,27705,27706,27707,27708,27709,27710,27711,27712,27713,27714,27715,
9625027716,27717,27718,27719,27720,27721,27722,27723,27724,27725,27726,27727,
9625127728,27729,27730,27731,27732,27733,27734,27735,27736,27737,27738,27739,
9625227740,27741,27742,27743,27744,27745,27746,27747,27748,27749,27750,27751,
9625327752,27753,27754,27755,27756,27757,27758,27759,27760,27761,27762,27763,
9625427764,27765,27766,27767,27768,27769,27770,27771,27772,27773,27774,27775,
9625527776,27777,27778,27779,27780,27781,27782,27783,27784,27785,27786,27787,
9625627788,27789,27790,27791,27792,27793,27794,27795,27796,27797,27798,27799,
9625727800,27801,27802,27803,27804,27805,27806,27807,27808,27809,27810,27811,
9625827812,27813,27814,27815,27816,27817,27818,27819,27820,27821,27822,27823,
9625927824,27825,27826,27827,27828,27829,27830,27831,27832,27833,27834,27835,
9626027836,27837,27838,27839,27840,27841,27842,27843,27844,27845,27846,27847,
9626127848,27849,27850,27851,27852,27853,27854,27855,27856,27857,27858,27859,
9626227860,27861,27862,27863,27864,27865,27866,27867,27868,27869,27870,27871,
9626327872,27873,27874,27875,27876,27877,27878,27879,27880,27881,27882,27883,
9626427884,27885,27886,27887,27888,27889,27890,27891,27892,27893,27894,27895,
9626527896,27897,27898,27899,27900,27901,27902,27903,27904,27905,27906,27907,
9626627908,27909,27910,27911,27912,27913,27914,27915,27916,27917,27918,27919,
9626727920,27921,27922,27923,27924,27925,27926,27927,27928,27929,27930,27931,
9626827932,27933,27934,27935,27936,27937,27938,27939,27940,27941,27942,27943,
9626927944,27945,27946,27947,27948,27949,27950,27951,27952,27953,27954,27955,
9627027956,27957,27958,27959,27960,27961,27962,27963,27964,27965,27966,27967,
9627127968,27969,27970,27971,27972,27973,27974,27975,27976,27977,27978,27979,
9627227980,27981,27982,27983,27984,27985,27986,27987,27988,27989,27990,27991,
9627327992,27993,27994,27995,27996,27997,27998,27999,28000,28001,28002,28003,
9627428004,28005,28006,28007,28008,28009,28010,28011,28012,28013,28014,28015,
9627528016,28017,28018,28019,28020,28021,28022,28023,28024,28025,28026,28027,
9627628028,28029,28030,28031,28032,28033,28034,28035,28036,28037,28038,28039,
9627728040,28041,28042,28043,28044,28045,28046,28047,28048,28049,28050,28051,
9627828052,28053,28054,28055,28056,28057,28058,28059,28060,28061,28062,28063,
9627928064,28065,28066,28067,28068,28069,28070,28071,28072,28073,28074,28075,
9628028076,28077,28078,28079,28080,28081,28082,28083,28084,28085,28086,28087,
9628128088,28089,28090,28091,28092,28093,28094,28095,28096,28097,28098,28099,
9628228100,28101,28102,28103,28104,28105,28106,28107,28108,28109,28110,28111,
9628328112,28113,28114,28115,28116,28117,28118,28119,28120,28121,28122,28123,
9628428124,28125,28126,28127,28128,28129,28130,28131,28132,28133,28134,28135,
9628528136,28137,28138,28139,28140,28141,28142,28143,28144,28145,28146,28147,
9628628148,28149,28150,28151,28152,28153,28154,28155,28156,28157,28158,28159,
9628728160,28161,28162,28163,28164,28165,28166,28167,28168,28169,28170,28171,
9628828172,28173,28174,28175,28176,28177,28178,28179,28180,28181,28182,28183,
9628928184,28185,28186,28187,28188,28189,28190,28191,28192,28193,28194,28195,
9629028196,28197,28198,28199,28200,28201,28202,28203,28204,28205,28206,28207,
9629128208,28209,28210,28211,28212,28213,28214,28215,28216,28217,28218,28219,
9629228220,28221,28222,28223,28224,28225,28226,28227,28228,28229,28230,28231,
9629328232,28233,28234,28235,28236,28237,28238,28239,28240,28241,28242,28243,
9629428244,28245,28246,28247,28248,28249,28250,28251,28252,28253,28254,28255,
9629528256,28257,28258,28259,28260,28261,28262,28263,28264,28265,28266,28267,
9629628268,28269,28270,28271,28272,28273,28274,28275,28276,28277,28278,28279,
9629728280,28281,28282,28283,28284,28285,28286,28287,28288,28289,28290,28291,
9629828292,28293,28294,28295,28296,28297,28298,28299,28300,28301,28302,28303,
9629928304,28305,28306,28307,28308,28309,28310,28311,28312,28313,28314,28315,
9630028316,28317,28318,28319,28320,28321,28322,28323,28324,28325,28326,28327,
9630128328,28329,28330,28331,28332,28333,28334,28335,28336,28337,28338,28339,
9630228340,28341,28342,28343,28344,28345,28346,28347,28348,28349,28350,28351,
9630328352,28353,28354,28355,28356,28357,28358,28359,28360,28361,28362,28363,
9630428364,28365,28366,28367,28368,28369,28370,28371,28372,28373,28374,28375,
9630528376,28377,28378,28379,28380,28381,28382,28383,28384,28385,28386,28387,
9630628388,28389,28390,28391,28392,28393,28394,28395,28396,28397,28398,28399,
9630728400,28401,28402,28403,28404,28405,28406,28407,28408,28409,28410,28411,
9630828412,28413,28414,28415,28416,28417,28418,28419,28420,28421,28422,28423,
9630928424,28425,28426,28427,28428,28429,28430,28431,28432,28433,28434,28435,
9631028436,28437,28438,28439,28440,28441,28442,28443,28444,28445,28446,28447,
9631128448,28449,28450,28451,28452,28453,28454,28455,28456,28457,28458,28459,
9631228460,28461,28462,28463,28464,28465,28466,28467,28468,28469,28470,28471,
9631328472,28473,28474,28475,28476,28477,28478,28479,28480,28481,28482,28483,
9631428484,28485,28486,28487,28488,28489,28490,28491,28492,28493,28494,28495,
9631528496,28497,28498,28499,28500,28501,28502,28503,28504,28505,28506,28507,
9631628508,28509,28510,28511,28512,28513,28514,28515,28516,28517,28518,28519,
9631728520,28521,28522,28523,28524,28525,28526,28527,28528,28529,28530,28531,
9631828532,28533,28534,28535,28536,28537,28538,28539,28540,28541,28542,28543,
9631928544,28545,28546,28547,28548,28549,28550,28551,28552,28553,28554,28555,
9632028556,28557,28558,28559,28560,28561,28562,28563,28564,28565,28566,28567,
9632128568,28569,28570,28571,28572,28573,28574,28575,28576,28577,28578,28579,
9632228580,28581,28582,28583,28584,28585,28586,28587,28588,28589,28590,28591,
9632328592,28593,28594,28595,28596,28597,28598,28599,28600,28601,28602,28603,
9632428604,28605,28606,28607,28608,28609,28610,28611,28612,28613,28614,28615,
9632528616,28617,28618,28619,28620,28621,28622,28623,28624,28625,28626,28627,
9632628628,28629,28630,28631,28632,28633,28634,28635,28636,28637,28638,28639,
9632728640,28641,28642,28643,28644,28645,28646,28647,28648,28649,28650,28651,
9632828652,28653,28654,28655,28656,28657,28658,28659,28660,28661,28662,28663,
9632928664,28665,28666,28667,28668,28669,28670,28671,28672,28673,28674,28675,
9633028676,28677,28678,28679,28680,28681,28682,28683,28684,28685,28686,28687,
9633128688,28689,28690,28691,28692,28693,28694,28695,28696,28697,28698,28699,
9633228700,28701,28702,28703,28704,28705,28706,28707,28708,28709,28710,28711,
9633328712,28713,28714,28715,28716,28717,28718,28719,28720,28721,28722,28723,
9633428724,28725,28726,28727,28728,28729,28730,28731,28732,28733,28734,28735,
9633528736,28737,28738,28739,28740,28741,28742,28743,28744,28745,28746,28747,
9633628748,28749,28750,28751,28752,28753,28754,28755,28756,28757,28758,28759,
9633728760,28761,28762,28763,28764,28765,28766,28767,28768,28769,28770,28771,
9633828772,28773,28774,28775,28776,28777,28778,28779,28780,28781,28782,28783,
9633928784,28785,28786,28787,28788,28789,28790,28791,28792,28793,28794,28795,
9634028796,28797,28798,28799,28800,28801,28802,28803,28804,28805,28806,28807,
9634128808,28809,28810,28811,28812,28813,28814,28815,28816,28817,28818,28819,
9634228820,28821,28822,28823,28824,28825,28826,28827,28828,28829,28830,28831,
9634328832,28833,28834,28835,28836,28837,28838,28839,28840,28841,28842,28843,
9634428844,28845,28846,28847,28848,28849,28850,28851,28852,28853,28854,28855,
9634528856,28857,28858,28859,28860,28861,28862,28863,28864,28865,28866,28867,
9634628868,28869,28870,28871,28872,28873,28874,28875,28876,28877,28878,28879,
9634728880,28881,28882,28883,28884,28885,28886,28887,28888,28889,28890,28891,
9634828892,28893,28894,28895,28896,28897,28898,28899,28900,28901,28902,28903,
9634928904,28905,28906,28907,28908,28909,28910,28911,28912,28913,28914,28915,
9635028916,28917,28918,28919,28920,28921,28922,28923,28924,28925,28926,28927,
9635128928,28929,28930,28931,28932,28933,28934,28935,28936,28937,28938,28939,
9635228940,28941,28942,28943,28944,28945,28946,28947,28948,28949,28950,28951,
9635328952,28953,28954,28955,28956,28957,28958,28959,28960,28961,28962,28963,
9635428964,28965,28966,28967,28968,28969,28970,28971,28972,28973,28974,28975,
9635528976,28977,28978,28979,28980,28981,28982,28983,28984,28985,28986,28987,
9635628988,28989,28990,28991,28992,28993,28994,28995,28996,28997,28998,28999,
9635729000,29001,29002,29003,29004,29005,29006,29007,29008,29009,29010,29011,
9635829012,29013,29014,29015,29016,29017,29018,29019,29020,29021,29022,29023,
9635929024,29025,29026,29027,29028,29029,29030,29031,29032,29033,29034,29035,
9636029036,29037,29038,29039,29040,29041,29042,29043,29044,29045,29046,29047,
9636129048,29049,29050,29051,29052,29053,29054,29055,29056,29057,29058,29059,
9636229060,29061,29062,29063,29064,29065,29066,29067,29068,29069,29070,29071,
9636329072,29073,29074,29075,29076,29077,29078,29079,29080,29081,29082,29083,
9636429084,29085,29086,29087,29088,29089,29090,29091,29092,29093,29094,29095,
9636529096,29097,29098,29099,29100,29101,29102,29103,29104,29105,29106,29107,
9636629108,29109,29110,29111,29112,29113,29114,29115,29116,29117,29118,29119,
9636729120,29121,29122,29123,29124,29125,29126,29127,29128,29129,29130,29131,
9636829132,29133,29134,29135,29136,29137,29138,29139,29140,29141,29142,29143,
9636929144,29145,29146,29147,29148,29149,29150,29151,29152,29153,29154,29155,
9637029156,29157,29158,29159,29160,29161,29162,29163,29164,29165,29166,29167,
9637129168,29169,29170,29171,29172,29173,29174,29175,29176,29177,29178,29179,
9637229180,29181,29182,29183,29184,29185,29186,29187,29188,29189,29190,29191,
9637329192,29193,29194,29195,29196,29197,29198,29199,29200,29201,29202,29203,
9637429204,29205,29206,29207,29208,29209,29210,29211,29212,29213,29214,29215,
9637529216,29217,29218,29219,29220,29221,29222,29223,29224,29225,29226,29227,
9637629228,29229,29230,29231,29232,29233,29234,29235,29236,29237,29238,29239,
9637729240,29241,29242,29243,29244,29245,29246,29247,29248,29249,29250,29251,
9637829252,29253,29254,29255,29256,29257,29258,29259,29260,29261,29262,29263,
9637929264,29265,29266,29267,29268,29269,29270,29271,29272,29273,29274,29275,
9638029276,29277,29278,29279,29280,29281,29282,29283,29284,29285,29286,29287,
9638129288,29289,29290,29291,29292,29293,29294,29295,29296,29297,29298,29299,
9638229300,29301,29302,29303,29304,29305,29306,29307,29308,29309,29310,29311,
9638329312,29313,29314,29315,29316,29317,29318,29319,29320,29321,29322,29323,
9638429324,29325,29326,29327,29328,29329,29330,29331,29332,29333,29334,29335,
9638529336,29337,29338,29339,29340,29341,29342,29343,29344,29345,29346,29347,
9638629348,29349,29350,29351,29352,29353,29354,29355,29356,29357,29358,29359,
9638729360,29361,29362,29363,29364,29365,29366,29367,29368,29369,29370,29371,
9638829372,29373,29374,29375,29376,29377,29378,29379,29380,29381,29382,29383,
9638929384,29385,29386,29387,29388,29389,29390,29391,29392,29393,29394,29395,
9639029396,29397,29398,29399,29400,29401,29402,29403,29404,29405,29406,29407,
9639129408,29409,29410,29411,29412,29413,29414,29415,29416,29417,29418,29419,
9639229420,29421,29422,29423,29424,29425,29426,29427,29428,29429,29430,29431,
9639329432,29433,29434,29435,29436,29437,29438,29439,29440,29441,29442,29443,
9639429444,29445,29446,29447,29448,29449,29450,29451,29452,29453,29454,29455,
9639529456,29457,29458,29459,29460,29461,29462,29463,29464,29465,29466,29467,
9639629468,29469,29470,29471,29472,29473,29474,29475,29476,29477,29478,29479,
9639729480,29481,29482,29483,29484,29485,29486,29487,29488,29489,29490,29491,
9639829492,29493,29494,29495,29496,29497,29498,29499,29500,29501,29502,29503,
9639929504,29505,29506,29507,29508,29509,29510,29511,29512,29513,29514,29515,
9640029516,29517,29518,29519,29520,29521,29522,29523,29524,29525,29526,29527,
9640129528,29529,29530,29531,29532,29533,29534,29535,29536,29537,29538,29539,
9640229540,29541,29542,29543,29544,29545,29546,29547,29548,29549,29550,29551,
9640329552,29553,29554,29555,29556,29557,29558,29559,29560,29561,29562,29563,
9640429564,29565,29566,29567,29568,29569,29570,29571,29572,29573,29574,29575,
9640529576,29577,29578,29579,29580,29581,29582,29583,29584,29585,29586,29587,
9640629588,29589,29590,29591,29592,29593,29594,29595,29596,29597,29598,29599,
9640729600,29601,29602,29603,29604,29605,29606,29607,29608,29609,29610,29611,
9640829612,29613,29614,29615,29616,29617,29618,29619,29620,29621,29622,29623,
9640929624,29625,29626,29627,29628,29629,29630,29631,29632,29633,29634,29635,
9641029636,29637,29638,29639,29640,29641,29642,29643,29644,29645,29646,29647,
9641129648,29649,29650,29651,29652,29653,29654,29655,29656,29657,29658,29659,
9641229660,29661,29662,29663,29664,29665,29666,29667,29668,29669,29670,29671,
9641329672,29673,29674,29675,29676,29677,29678,29679,29680,29681,29682,29683,
9641429684,29685,29686,29687,29688,29689,29690,29691,29692,29693,29694,29695,
9641529696,29697,29698,29699,29700,29701,29702,29703,29704,29705,29706,29707,
9641629708,29709,29710,29711,29712,29713,29714,29715,29716,29717,29718,29719,
9641729720,29721,29722,29723,29724,29725,29726,29727,29728,29729,29730,29731,
9641829732,29733,29734,29735,29736,29737,29738,29739,29740,29741,29742,29743,
9641929744,29745,29746,29747,29748,29749,29750,29751,29752,29753,29754,29755,
9642029756,29757,29758,29759,29760,29761,29762,29763,29764,29765,29766,29767,
9642129768,29769,29770,29771,29772,29773,29774,29775,29776,29777,29778,29779,
9642229780,29781,29782,29783,29784,29785,29786,29787,29788,29789,29790,29791,
9642329792,29793,29794,29795,29796,29797,29798,29799,29800,29801,29802,29803,
9642429804,29805,29806,29807,29808,29809,29810,29811,29812,29813,29814,29815,
9642529816,29817,29818,29819,29820,29821,29822,29823,29824,29825,29826,29827,
9642629828,29829,29830,29831,29832,29833,29834,29835,29836,29837,29838,29839,
9642729840,29841,29842,29843,29844,29845,29846,29847,29848,29849,29850,29851,
9642829852,29853,29854,29855,29856,29857,29858,29859,29860,29861,29862,29863,
9642929864,29865,29866,29867,29868,29869,29870,29871,29872,29873,29874,29875,
9643029876,29877,29878,29879,29880,29881,29882,29883,29884,29885,29886,29887,
9643129888,29889,29890,29891,29892,29893,29894,29895,29896,29897,29898,29899,
9643229900,29901,29902,29903,29904,29905,29906,29907,29908,29909,29910,29911,
9643329912,29913,29914,29915,29916,29917,29918,29919,29920,29921,29922,29923,
9643429924,29925,29926,29927,29928,29929,29930,29931,29932,29933,29934,29935,
9643529936,29937,29938,29939,29940,29941,29942,29943,29944,29945,29946,29947,
9643629948,29949,29950,29951,29952,29953,29954,29955,29956,29957,29958,29959,
9643729960,29961,29962,29963,29964,29965,29966,29967,29968,29969,29970,29971,
9643829972,29973,29974,29975,29976,29977,29978,29979,29980,29981,29982,29983,
9643929984,29985,29986,29987,29988,29989,29990,29991,29992,29993,29994,29995,
9644029996,29997,29998,29999,30000,30001,30002,30003,30004,30005,30006,30007,
9644130008,30009,30010,30011,30012,30013,30014,30015,30016,30017,30018,30019,
9644230020,30021,30022,30023,30024,30025,30026,30027,30028,30029,30030,30031,
9644330032,30033,30034,30035,30036,30037,30038,30039,30040,30041,30042,30043,
9644430044,30045,30046,30047,30048,30049,30050,30051,30052,30053,30054,30055,
9644530056,30057,30058,30059,30060,30061,30062,30063,30064,30065,30066,30067,
9644630068,30069,30070,30071,30072,30073,30074,30075,30076,30077,30078,30079,
9644730080,30081,30082,30083,30084,30085,30086,30087,30088,30089,30090,30091,
9644830092,30093,30094,30095,30096,30097,30098,30099,30100,30101,30102,30103,
9644930104,30105,30106,30107,30108,30109,30110,30111,30112,30113,30114,30115,
9645030116,30117,30118,30119,30120,30121,30122,30123,30124,30125,30126,30127,
9645130128,30129,30130,30131,30132,30133,30134,30135,30136,30137,30138,30139,
9645230140,30141,30142,30143,30144,30145,30146,30147,30148,30149,30150,30151,
9645330152,30153,30154,30155,30156,30157,30158,30159,30160,30161,30162,30163,
9645430164,30165,30166,30167,30168,30169,30170,30171,30172,30173,30174,30175,
9645530176,30177,30178,30179,30180,30181,30182,30183,30184,30185,30186,30187,
9645630188,30189,30190,30191,30192,30193,30194,30195,30196,30197,30198,30199,
9645730200,30201,30202,30203,30204,30205,30206,30207,30208,30209,30210,30211,
9645830212,30213,30214,30215,30216,30217,30218,30219,30220,30221,30222,30223,
9645930224,30225,30226,30227,30228,30229,30230,30231,30232,30233,30234,30235,
9646030236,30237,30238,30239,30240,30241,30242,30243,30244,30245,30246,30247,
9646130248,30249,30250,30251,30252,30253,30254,30255,30256,30257,30258,30259,
9646230260,30261,30262,30263,30264,30265,30266,30267,30268,30269,30270,30271,
9646330272,30273,30274,30275,30276,30277,30278,30279,30280,30281,30282,30283,
9646430284,30285,30286,30287,30288,30289,30290,30291,30292,30293,30294,30295,
9646530296,30297,30298,30299,30300,30301,30302,30303,30304,30305,30306,30307,
9646630308,30309,30310,30311,30312,30313,30314,30315,30316,30317,30318,30319,
9646730320,30321,30322,30323,30324,30325,30326,30327,30328,30329,30330,30331,
9646830332,30333,30334,30335,30336,30337,30338,30339,30340,30341,30342,30343,
9646930344,30345,30346,30347,30348,30349,30350,30351,30352,30353,30354,30355,
9647030356,30357,30358,30359,30360,30361,30362,30363,30364,30365,30366,30367,
9647130368,30369,30370,30371,30372,30373,30374,30375,30376,30377,30378,30379,
9647230380,30381,30382,30383,30384,30385,30386,30387,30388,30389,30390,30391,
9647330392,30393,30394,30395,30396,30397,30398,30399,30400,30401,30402,30403,
9647430404,30405,30406,30407,30408,30409,30410,30411,30412,30413,30414,30415,
9647530416,30417,30418,30419,30420,30421,30422,30423,30424,30425,30426,30427,
9647630428,30429,30430,30431,30432,30433,30434,30435,30436,30437,30438,30439,
9647730440,30441,30442,30443,30444,30445,30446,30447,30448,30449,30450,30451,
9647830452,30453,30454,30455,30456,30457,30458,30459,30460,30461,30462,30463,
9647930464,30465,30466,30467,30468,30469,30470,30471,30472,30473,30474,30475,
9648030476,30477,30478,30479,30480,30481,30482,30483,30484,30485,30486,30487,
9648130488,30489,30490,30491,30492,30493,30494,30495,30496,30497,30498,30499,
9648230500,30501,30502,30503,30504,30505,30506,30507,30508,30509,30510,30511,
9648330512,30513,30514,30515,30516,30517,30518,30519,30520,30521,30522,30523,
9648430524,30525,30526,30527,30528,30529,30530,30531,30532,30533,30534,30535,
9648530536,30537,30538,30539,30540,30541,30542,30543,30544,30545,30546,30547,
9648630548,30549,30550,30551,30552,30553,30554,30555,30556,30557,30558,30559,
9648730560,30561,30562,30563,30564,30565,30566,30567,30568,30569,30570,30571,
9648830572,30573,30574,30575,30576,30577,30578,30579,30580,30581,30582,30583,
9648930584,30585,30586,30587,30588,30589,30590,30591,30592,30593,30594,30595,
9649030596,30597,30598,30599,30600,30601,30602,30603,30604,30605,30606,30607,
9649130608,30609,30610,30611,30612,30613,30614,30615,30616,30617,30618,30619,
9649230620,30621,30622,30623,30624,30625,30626,30627,30628,30629,30630,30631,
9649330632,30633,30634,30635,30636,30637,30638,30639,30640,30641,30642,30643,
9649430644,30645,30646,30647,30648,30649,30650,30651,30652,30653,30654,30655,
9649530656,30657,30658,30659,30660,30661,30662,30663,30664,30665,30666,30667,
9649630668,30669,30670,30671,30672,30673,30674,30675,30676,30677,30678,30679,
9649730680,30681,30682,30683,30684,30685,30686,30687,30688,30689,30690,30691,
9649830692,30693,30694,30695,30696,30697,30698,30699,30700,30701,30702,30703,
9649930704,30705,30706,30707,30708,30709,30710,30711,30712,30713,30714,30715,
9650030716,30717,30718,30719,30720,30721,30722,30723,30724,30725,30726,30727,
9650130728,30729,30730,30731,30732,30733,30734,30735,30736,30737,30738,30739,
9650230740,30741,30742,30743,30744,30745,30746,30747,30748,30749,30750,30751,
9650330752,30753,30754,30755,30756,30757,30758,30759,30760,30761,30762,30763,
9650430764,30765,30766,30767,30768,30769,30770,30771,30772,30773,30774,30775,
9650530776,30777,30778,30779,30780,30781,30782,30783,30784,30785,30786,30787,
9650630788,30789,30790,30791,30792,30793,30794,30795,30796,30797,30798,30799,
9650730800,30801,30802,30803,30804,30805,30806,30807,30808,30809,30810,30811,
9650830812,30813,30814,30815,30816,30817,30818,30819,30820,30821,30822,30823,
9650930824,30825,30826,30827,30828,30829,30830,30831,30832,30833,30834,30835,
9651030836,30837,30838,30839,30840,30841,30842,30843,30844,30845,30846,30847,
9651130848,30849,30850,30851,30852,30853,30854,30855,30856,30857,30858,30859,
9651230860,30861,30862,30863,30864,30865,30866,30867,30868,30869,30870,30871,
9651330872,30873,30874,30875,30876,30877,30878,30879,30880,30881,30882,30883,
9651430884,30885,30886,30887,30888,30889,30890,30891,30892,30893,30894,30895,
9651530896,30897,30898,30899,30900,30901,30902,30903,30904,30905,30906,30907,
9651630908,30909,30910,30911,30912,30913,30914,30915,30916,30917,30918,30919,
9651730920,30921,30922,30923,30924,30925,30926,30927,30928,30929,30930,30931,
9651830932,30933,30934,30935,30936,30937,30938,30939,30940,30941,30942,30943,
9651930944,30945,30946,30947,30948,30949,30950,30951,30952,30953,30954,30955,
9652030956,30957,30958,30959,30960,30961,30962,30963,30964,30965,30966,30967,
9652130968,30969,30970,30971,30972,30973,30974,30975,30976,30977,30978,30979,
9652230980,30981,30982,30983,30984,30985,30986,30987,30988,30989,30990,30991,
9652330992,30993,30994,30995,30996,30997,30998,30999,31000,31001,31002,31003,
9652431004,31005,31006,31007,31008,31009,31010,31011,31012,31013,31014,31015,
9652531016,31017,31018,31019,31020,31021,31022,31023,31024,31025,31026,31027,
9652631028,31029,31030,31031,31032,31033,31034,31035,31036,31037,31038,31039,
9652731040,31041,31042,31043,31044,31045,31046,31047,31048,31049,31050,31051,
9652831052,31053,31054,31055,31056,31057,31058,31059,31060,31061,31062,31063,
9652931064,31065,31066,31067,31068,31069,31070,31071,31072,31073,31074,31075,
9653031076,31077,31078,31079,31080,31081,31082,31083,31084,31085,31086,31087,
9653131088,31089,31090,31091,31092,31093,31094,31095,31096,31097,31098,31099,
9653231100,31101,31102,31103,31104,31105,31106,31107,31108,31109,31110,31111,
9653331112,31113,31114,31115,31116,31117,31118,31119,31120,31121,31122,31123,
9653431124,31125,31126,31127,31128,31129,31130,31131,31132,31133,31134,31135,
9653531136,31137,31138,31139,31140,31141,31142,31143,31144,31145,31146,31147,
9653631148,31149,31150,31151,31152,31153,31154,31155,31156,31157,31158,31159,
9653731160,31161,31162,31163,31164,31165,31166,31167,31168,31169,31170,31171,
9653831172,31173,31174,31175,31176,31177,31178,31179,31180,31181,31182,31183,
9653931184,31185,31186,31187,31188,31189,31190,31191,31192,31193,31194,31195,
9654031196,31197,31198,31199,31200,31201,31202,31203,31204,31205,31206,31207,
9654131208,31209,31210,31211,31212,31213,31214,31215,31216,31217,31218,31219,
9654231220,31221,31222,31223,31224,31225,31226,31227,31228,31229,31230,31231,
9654331232,31233,31234,31235,31236,31237,31238,31239,31240,31241,31242,31243,
9654431244,31245,31246,31247,31248,31249,31250,31251,31252,31253,31254,31255,
9654531256,31257,31258,31259,31260,31261,31262,31263,31264,31265,31266,31267,
9654631268,31269,31270,31271,31272,31273,31274,31275,31276,31277,31278,31279,
9654731280,31281,31282,31283,31284,31285,31286,31287,31288,31289,31290,31291,
9654831292,31293,31294,31295,31296,31297,31298,31299,31300,31301,31302,31303,
9654931304,31305,31306,31307,31308,31309,31310,31311,31312,31313,31314,31315,
9655031316,31317,31318,31319,31320,31321,31322,31323,31324,31325,31326,31327,
9655131328,31329,31330,31331,31332,31333,31334,31335,31336,31337,31338,31339,
9655231340,31341,31342,31343,31344,31345,31346,31347,31348,31349,31350,31351,
9655331352,31353,31354,31355,31356,31357,31358,31359,31360,31361,31362,31363,
9655431364,31365,31366,31367,31368,31369,31370,31371,31372,31373,31374,31375,
9655531376,31377,31378,31379,31380,31381,31382,31383,31384,31385,31386,31387,
9655631388,31389,31390,31391,31392,31393,31394,31395,31396,31397,31398,31399,
9655731400,31401,31402,31403,31404,31405,31406,31407,31408,31409,31410,31411,
9655831412,31413,31414,31415,31416,31417,31418,31419,31420,31421,31422,31423,
9655931424,31425,31426,31427,31428,31429,31430,31431,31432,31433,31434,31435,
9656031436,31437,31438,31439,31440,31441,31442,31443,31444,31445,31446,31447,
9656131448,31449,31450,31451,31452,31453,31454,31455,31456,31457,31458,31459,
9656231460,31461,31462,31463,31464,31465,31466,31467,31468,31469,31470,31471,
9656331472,31473,31474,31475,31476,31477,31478,31479,31480,31481,31482,31483,
9656431484,31485,31486,31487,31488,31489,31490,31491,31492,31493,31494,31495,
9656531496,31497,31498,31499,31500,31501,31502,31503,31504,31505,31506,31507,
9656631508,31509,31510,31511,31512,31513,31514,31515,31516,31517,31518,31519,
9656731520,31521,31522,31523,31524,31525,31526,31527,31528,31529,31530,31531,
9656831532,31533,31534,31535,31536,31537,31538,31539,31540,31541,31542,31543,
9656931544,31545,31546,31547,31548,31549,31550,31551,31552,31553,31554,31555,
9657031556,31557,31558,31559,31560,31561,31562,31563,31564,31565,31566,31567,
9657131568,31569,31570,31571,31572,31573,31574,31575,31576,31577,31578,31579,
9657231580,31581,31582,31583,31584,31585,31586,31587,31588,31589,31590,31591,
9657331592,31593,31594,31595,31596,31597,31598,31599,31600,31601,31602,31603,
9657431604,31605,31606,31607,31608,31609,31610,31611,31612,31613,31614,31615,
9657531616,31617,31618,31619,31620,31621,31622,31623,31624,31625,31626,31627,
9657631628,31629,31630,31631,31632,31633,31634,31635,31636,31637,31638,31639,
9657731640,31641,31642,31643,31644,31645,31646,31647,31648,31649,31650,31651,
9657831652,31653,31654,31655,31656,31657,31658,31659,31660,31661,31662,31663,
9657931664,31665,31666,31667,31668,31669,31670,31671,31672,31673,31674,31675,
9658031676,31677,31678,31679,31680,31681,31682,31683,31684,31685,31686,31687,
9658131688,31689,31690,31691,31692,31693,31694,31695,31696,31697,31698,31699,
9658231700,31701,31702,31703,31704,31705,31706,31707,31708,31709,31710,31711,
9658331712,31713,31714,31715,31716,31717,31718,31719,31720,31721,31722,31723,
9658431724,31725,31726,31727,31728,31729,31730,31731,31732,31733,31734,31735,
9658531736,31737,31738,31739,31740,31741,31742,31743,31744,31745,31746,31747,
9658631748,31749,31750,31751,31752,31753,31754,31755,31756,31757,31758,31759,
9658731760,31761,31762,31763,31764,31765,31766,31767,31768,31769,31770,31771,
9658831772,31773,31774,31775,31776,31777,31778,31779,31780,31781,31782,31783,
9658931784,31785,31786,31787,31788,31789,31790,31791,31792,31793,31794,31795,
9659031796,31797,31798,31799,31800,31801,31802,31803,31804,31805,31806,31807,
9659131808,31809,31810,31811,31812,31813,31814,31815,31816,31817,31818,31819,
9659231820,31821,31822,31823,31824,31825,31826,31827,31828,31829,31830,31831,
9659331832,31833,31834,31835,31836,31837,31838,31839,31840,31841,31842,31843,
9659431844,31845,31846,31847,31848,31849,31850,31851,31852,31853,31854,31855,
9659531856,31857,31858,31859,31860,31861,31862,31863,31864,31865,31866,31867,
9659631868,31869,31870,31871,31872,31873,31874,31875,31876,31877,31878,31879,
9659731880,31881,31882,31883,31884,31885,31886,31887,31888,31889,31890,31891,
9659831892,31893,31894,31895,31896,31897,31898,31899,31900,31901,31902,31903,
9659931904,31905,31906,31907,31908,31909,31910,31911,31912,31913,31914,31915,
9660031916,31917,31918,31919,31920,31921,31922,31923,31924,31925,31926,31927,
9660131928,31929,31930,31931,31932,31933,31934,31935,31936,31937,31938,31939,
9660231940,31941,31942,31943,31944,31945,31946,31947,31948,31949,31950,31951,
9660331952,31953,31954,31955,31956,31957,31958,31959,31960,31961,31962,31963,
9660431964,31965,31966,31967,31968,31969,31970,31971,31972,31973,31974,31975,
9660531976,31977,31978,31979,31980,31981,31982,31983,31984,31985,31986,31987,
9660631988,31989,31990,31991,31992,31993,31994,31995,31996,31997,31998,31999,
9660732000,32001,32002,32003,32004,32005,32006,32007,32008,32009,32010,32011,
9660832012,32013,32014,32015,32016,32017,32018,32019,32020,32021,32022,32023,
9660932024,32025,32026,32027,32028,32029,32030,32031,32032,32033,32034,32035,
9661032036,32037,32038,32039,32040,32041,32042,32043,32044,32045,32046,32047,
9661132048,32049,32050,32051,32052,32053,32054,32055,32056,32057,32058,32059,
9661232060,32061,32062,32063,32064,32065,32066,32067,32068,32069,32070,32071,
9661332072,32073,32074,32075,32076,32077,32078,32079,32080,32081,32082,32083,
9661432084,32085,32086,32087,32088,32089,32090,32091,32092,32093,32094,32095,
9661532096,32097,32098,32099,32100,32101,32102,32103,32104,32105,32106,32107,
9661632108,32109,32110,32111,32112,32113,32114,32115,32116,32117,32118,32119,
9661732120,32121,32122,32123,32124,32125,32126,32127,32128,32129,32130,32131,
9661832132,32133,32134,32135,32136,32137,32138,32139,32140,32141,32142,32143,
9661932144,32145,32146,32147,32148,32149,32150,32151,32152,32153,32154,32155,
9662032156,32157,32158,32159,32160,32161,32162,32163,32164,32165,32166,32167,
9662132168,32169,32170,32171,32172,32173,32174,32175,32176,32177,32178,32179,
9662232180,32181,32182,32183,32184,32185,32186,32187,32188,32189,32190,32191,
9662332192,32193,32194,32195,32196,32197,32198,32199,32200,32201,32202,32203,
9662432204,32205,32206,32207,32208,32209,32210,32211,32212,32213,32214,32215,
9662532216,32217,32218,32219,32220,32221,32222,32223,32224,32225,32226,32227,
9662632228,32229,32230,32231,32232,32233,32234,32235,32236,32237,32238,32239,
9662732240,32241,32242,32243,32244,32245,32246,32247,32248,32249,32250,32251,
9662832252,32253,32254,32255,32256,32257,32258,32259,32260,32261,32262,32263,
9662932264,32265,32266,32267,32268,32269,32270,32271,32272,32273,32274,32275,
9663032276,32277,32278,32279,32280,32281,32282,32283,32284,32285,32286,32287,
9663132288,32289,32290,32291,32292,32293,32294,32295,32296,32297,32298,32299,
9663232300,32301,32302,32303,32304,32305,32306,32307,32308,32309,32310,32311,
9663332312,32313,32314,32315,32316,32317,32318,32319,32320,32321,32322,32323,
9663432324,32325,32326,32327,32328,32329,32330,32331,32332,32333,32334,32335,
9663532336,32337,32338,32339,32340,32341,32342,32343,32344,32345,32346,32347,
9663632348,32349,32350,32351,32352,32353,32354,32355,32356,32357,32358,32359,
9663732360,32361,32362,32363,32364,32365,32366,32367,32368,32369,32370,32371,
9663832372,32373,32374,32375,32376,32377,32378,32379,32380,32381,32382,32383,
9663932384,32385,32386,32387,32388,32389,32390,32391,32392,32393,32394,32395,
9664032396,32397,32398,32399,32400,32401,32402,32403,32404,32405,32406,32407,
9664132408,32409,32410,32411,32412,32413,32414,32415,32416,32417,32418,32419,
9664232420,32421,32422,32423,32424,32425,32426,32427,32428,32429,32430,32431,
9664332432,32433,32434,32435,32436,32437,32438,32439,32440,32441,32442,32443,
9664432444,32445,32446,32447,32448,32449,32450,32451,32452,32453,32454,32455,
9664532456,32457,32458,32459,32460,32461,32462,32463,32464,32465,32466,32467,
9664632468,32469,32470,32471,32472,32473,32474,32475,32476,32477,32478,32479,
9664732480,32481,32482,32483,32484,32485,32486,32487,32488,32489,32490,32491,
9664832492,32493,32494,32495,32496,32497,32498,32499,32500,32501,32502,32503,
9664932504,32505,32506,32507,32508,32509,32510,32511,32512,32513,32514,32515,
9665032516,32517,32518,32519,32520,32521,32522,32523,32524,32525,32526,32527,
9665132528,32529,32530,32531,32532,32533,32534,32535,32536,32537,32538,32539,
9665232540,32541,32542,32543,32544,32545,32546,32547,32548,32549,32550,32551,
9665332552,32553,32554,32555,32556,32557,32558,32559,32560,32561,32562,32563,
9665432564,32565,32566,32567,32568,32569,32570,32571,32572,32573,32574,32575,
9665532576,32577,32578,32579,32580,32581,32582,32583,32584,32585,32586,32587,
9665632588,32589,32590,32591,32592,32593,32594,32595,32596,32597,32598,32599,
9665732600,32601,32602,32603,32604,32605,32606,32607,32608,32609,32610,32611,
9665832612,32613,32614,32615,32616,32617,32618,32619,32620,32621,32622,32623,
9665932624,32625,32626,32627,32628,32629,32630,32631,32632,32633,32634,32635,
9666032636,32637,32638,32639,32640,32641,32642,32643,32644,32645,32646,32647,
9666132648,32649,32650,32651,32652,32653,32654,32655,32656,32657,32658,32659,
9666232660,32661,32662,32663,32664,32665,32666,32667,32668,32669,32670,32671,
9666332672,32673,32674,32675,32676,32677,32678,32679,32680,32681,32682,32683,
9666432684,32685,32686,32687,32688,32689,32690,32691,32692,32693,32694,32695,
9666532696,32697,32698,32699,32700,32701,32702,32703,32704,32705,32706,32707,
9666632708,32709,32710,32711,32712,32713,32714,32715,32716,32717,32718,32719,
9666732720,32721,32722,32723,32724,32725,32726,32727,32728,32729,32730,32731,
9666832732,32733,32734,32735,32736,32737,32738,32739,32740,32741,32742,32743,
9666932744,32745,32746,32747,32748,32749,32750,32751,32752,32753,32754,32755,
9667032756,32757,32758,32759,32760,32761,32762,32763,32764,32765,32766,32767,
9667132768L,32769L,32770L,32771L,32772L,32773L,32774L,32775L,32776L,32777L,
9667232778L,32779L,32780L,32781L,32782L,32783L,32784L,32785L,32786L,32787L,
9667332788L,32789L,32790L,32791L,32792L,32793L,32794L,32795L,32796L,32797L,
9667432798L,32799L,32800L,32801L,32802L,32803L,32804L,32805L,32806L,32807L,
9667532808L,32809L,32810L,32811L,32812L,32813L,32814L,32815L,32816L,32817L,
9667632818L,32819L,32820L,32821L,32822L,32823L,32824L,32825L,32826L,32827L,
9667732828L,32829L,32830L,32831L,32832L,32833L,32834L,32835L,32836L,32837L,
9667832838L,32839L,32840L,32841L,32842L,32843L,32844L,32845L,32846L,32847L,
9667932848L,32849L,32850L,32851L,32852L,32853L,32854L,32855L,32856L,32857L,
9668032858L,32859L,32860L,32861L,32862L,32863L,32864L,32865L,32866L,32867L,
9668132868L,32869L,32870L,32871L,32872L,32873L,32874L,32875L,32876L,32877L,
9668232878L,32879L,32880L,32881L,32882L,32883L,32884L,32885L,32886L,32887L,
9668332888L,32889L,32890L,32891L,32892L,32893L,32894L,32895L,32896L,32897L,
9668432898L,32899L,32900L,32901L,32902L,32903L,32904L,32905L,32906L,32907L,
9668532908L,32909L,32910L,32911L,32912L,32913L,32914L,32915L,32916L,32917L,
9668632918L,32919L,32920L,32921L,32922L,32923L,32924L,32925L,32926L,32927L,
9668732928L,32929L,32930L,32931L,32932L,32933L,32934L,32935L,32936L,32937L,
9668832938L,32939L,32940L,32941L,32942L,32943L,32944L,32945L,32946L,32947L,
9668932948L,32949L,32950L,32951L,32952L,32953L,32954L,32955L,32956L,32957L,
9669032958L,32959L,32960L,32961L,32962L,32963L,32964L,32965L,32966L,32967L,
9669132968L,32969L,32970L,32971L,32972L,32973L,32974L,32975L,32976L,32977L,
9669232978L,32979L,32980L,32981L,32982L,32983L,32984L,32985L,32986L,32987L,
9669332988L,32989L,32990L,32991L,32992L,32993L,32994L,32995L,32996L,32997L,
9669432998L,32999L,33000L,33001L,33002L,33003L,33004L,33005L,33006L,33007L,
9669533008L,33009L,33010L,33011L,33012L,33013L,33014L,33015L,33016L,33017L,
9669633018L,33019L,33020L,33021L,33022L,33023L,33024L,33025L,33026L,33027L,
9669733028L,33029L,33030L,33031L,33032L,33033L,33034L,33035L,33036L,33037L,
9669833038L,33039L,33040L,33041L,33042L,33043L,33044L,33045L,33046L,33047L,
9669933048L,33049L,33050L,33051L,33052L,33053L,33054L,33055L,33056L,33057L,
9670033058L,33059L,33060L,33061L,33062L,33063L,33064L,33065L,33066L,33067L,
9670133068L,33069L,33070L,33071L,33072L,33073L,33074L,33075L,33076L,33077L,
9670233078L,33079L,33080L,33081L,33082L,33083L,33084L,33085L,33086L,33087L,
9670333088L,33089L,33090L,33091L,33092L,33093L,33094L,33095L,33096L,33097L,
9670433098L,33099L,33100L,33101L,33102L,33103L,33104L,33105L,33106L,33107L,
9670533108L,33109L,33110L,33111L,33112L,33113L,33114L,33115L,33116L,33117L,
9670633118L,33119L,33120L,33121L,33122L,33123L,33124L,33125L,33126L,33127L,
9670733128L,33129L,33130L,33131L,33132L,33133L,33134L,33135L,33136L,33137L,
9670833138L,33139L,33140L,33141L,33142L,33143L,33144L,33145L,33146L,33147L,
9670933148L,33149L,33150L,33151L,33152L,33153L,33154L,33155L,33156L,33157L,
9671033158L,33159L,33160L,33161L,33162L,33163L,33164L,33165L,33166L,33167L,
9671133168L,33169L,33170L,33171L,33172L,33173L,33174L,33175L,33176L,33177L,
9671233178L,33179L,33180L,33181L,33182L,33183L,33184L,33185L,33186L,33187L,
9671333188L,33189L,33190L,33191L,33192L,33193L,33194L,33195L,33196L,33197L,
9671433198L,33199L,33200L,33201L,33202L,33203L,33204L,33205L,33206L,33207L,
9671533208L,33209L,33210L,33211L,33212L,33213L,33214L,33215L,33216L,33217L,
9671633218L,33219L,33220L,33221L,33222L,33223L,33224L,33225L,33226L,33227L,
9671733228L,33229L,33230L,33231L,33232L,33233L,33234L,33235L,33236L,33237L,
9671833238L,33239L,33240L,33241L,33242L,33243L,33244L,33245L,33246L,33247L,
9671933248L,33249L,33250L,33251L,33252L,33253L,33254L,33255L,33256L,33257L,
9672033258L,33259L,33260L,33261L,33262L,33263L,33264L,33265L,33266L,33267L,
9672133268L,33269L,33270L,33271L,33272L,33273L,33274L,33275L,33276L,33277L,
9672233278L,33279L,33280L,33281L,33282L,33283L,33284L,33285L,33286L,33287L,
9672333288L,33289L,33290L,33291L,33292L,33293L,33294L,33295L,33296L,33297L,
9672433298L,33299L,33300L,33301L,33302L,33303L,33304L,33305L,33306L,33307L,
9672533308L,33309L,33310L,33311L,33312L,33313L,33314L,33315L,33316L,33317L,
9672633318L,33319L,33320L,33321L,33322L,33323L,33324L,33325L,33326L,33327L,
9672733328L,33329L,33330L,33331L,33332L,33333L,33334L,33335L,33336L,33337L,
9672833338L,33339L,33340L,33341L,33342L,33343L,33344L,33345L,33346L,33347L,
9672933348L,33349L,33350L,33351L,33352L,33353L,33354L,33355L,33356L,33357L,
9673033358L,33359L,33360L,33361L,33362L,33363L,33364L,33365L,33366L,33367L,
9673133368L,33369L,33370L,33371L,33372L,33373L,33374L,33375L,33376L,33377L,
9673233378L,33379L,33380L,33381L,33382L,33383L,33384L,33385L,33386L,33387L,
9673333388L,33389L,33390L,33391L,33392L,33393L,33394L,33395L,33396L,33397L,
9673433398L,33399L,33400L,33401L,33402L,33403L,33404L,33405L,33406L,33407L,
9673533408L,33409L,33410L,33411L,33412L,33413L,33414L,33415L,33416L,33417L,
9673633418L,33419L,33420L,33421L,33422L,33423L,33424L,33425L,33426L,33427L,
9673733428L,33429L,33430L,33431L,33432L,33433L,33434L,33435L,33436L,33437L,
9673833438L,33439L,33440L,33441L,33442L,33443L,33444L,33445L,33446L,33447L,
9673933448L,33449L,33450L,33451L,33452L,33453L,33454L,33455L,33456L,33457L,
9674033458L,33459L,33460L,33461L,33462L,33463L,33464L,33465L,33466L,33467L,
9674133468L,33469L,33470L,33471L,33472L,33473L,33474L,33475L,33476L,33477L,
9674233478L,33479L,33480L,33481L,33482L,33483L,33484L,33485L,33486L,33487L,
9674333488L,33489L,33490L,33491L,33492L,33493L,33494L,33495L,33496L,33497L,
9674433498L,33499L,33500L,33501L,33502L,33503L,33504L,33505L,33506L,33507L,
9674533508L,33509L,33510L,33511L,33512L,33513L,33514L,33515L,33516L,33517L,
9674633518L,33519L,33520L,33521L,33522L,33523L,33524L,33525L,33526L,33527L,
9674733528L,33529L,33530L,33531L,33532L,33533L,33534L,33535L,33536L,33537L,
9674833538L,33539L,33540L,33541L,33542L,33543L,33544L,33545L,33546L,33547L,
9674933548L,33549L,33550L,33551L,33552L,33553L,33554L,33555L,33556L,33557L,
9675033558L,33559L,33560L,33561L,33562L,33563L,33564L,33565L,33566L,33567L,
9675133568L,33569L,33570L,33571L,33572L,33573L,33574L,33575L,33576L,33577L,
9675233578L,33579L,33580L,33581L,33582L,33583L,33584L,33585L,33586L,33587L,
9675333588L,33589L,33590L,33591L,33592L,33593L,33594L,33595L,33596L,33597L,
9675433598L,33599L,33600L,33601L,33602L,33603L,33604L,33605L,33606L,33607L,
9675533608L,33609L,33610L,33611L,33612L,33613L,33614L,33615L,33616L,33617L,
9675633618L,33619L,33620L,33621L,33622L,33623L,33624L,33625L,33626L,33627L,
9675733628L,33629L,33630L,33631L,33632L,33633L,33634L,33635L,33636L,33637L,
9675833638L,33639L,33640L,33641L,33642L,33643L,33644L,33645L,33646L,33647L,
9675933648L,33649L,33650L,33651L,33652L,33653L,33654L,33655L,33656L,33657L,
9676033658L,33659L,33660L,33661L,33662L,33663L,33664L,33665L,33666L,33667L,
9676133668L,33669L,33670L,33671L,33672L,33673L,33674L,33675L,33676L,33677L,
9676233678L,33679L,33680L,33681L,33682L,33683L,33684L,33685L,33686L,33687L,
9676333688L,33689L,33690L,33691L,33692L,33693L,33694L,33695L,33696L,33697L,
9676433698L,33699L,33700L,33701L,33702L,33703L,33704L,33705L,33706L,33707L,
9676533708L,33709L,33710L,33711L,33712L,33713L,33714L,33715L,33716L,33717L,
9676633718L,33719L,33720L,33721L,33722L,33723L,33724L,33725L,33726L,33727L,
9676733728L,33729L,33730L,33731L,33732L,33733L,33734L,33735L,33736L,33737L,
9676833738L,33739L,33740L,33741L,33742L,33743L,33744L,33745L,33746L,33747L,
9676933748L,33749L,33750L,33751L,33752L,33753L,33754L,33755L,33756L,33757L,
9677033758L,33759L,33760L,33761L,33762L,33763L,33764L,33765L,33766L,33767L,
9677133768L,33769L,33770L,33771L,33772L,33773L,33774L,33775L,33776L,33777L,
9677233778L,33779L,33780L,33781L,33782L,33783L,33784L,33785L,33786L,33787L,
9677333788L,33789L,33790L,33791L,33792L,33793L,33794L,33795L,33796L,33797L,
9677433798L,33799L,33800L,33801L,33802L,33803L,33804L,33805L,33806L,33807L,
9677533808L,33809L,33810L,33811L,33812L,33813L,33814L,33815L,33816L,33817L,
9677633818L,33819L,33820L,33821L,33822L,33823L,33824L,33825L,33826L,33827L,
9677733828L,33829L,33830L,33831L,33832L,33833L,33834L,33835L,33836L,33837L,
9677833838L,33839L,33840L,33841L,33842L,33843L,33844L,33845L,33846L,33847L,
9677933848L,33849L,33850L,33851L,33852L,33853L,33854L,33855L,33856L,33857L,
9678033858L,33859L,33860L,33861L,33862L,33863L,33864L,33865L,33866L,33867L,
9678133868L,33869L,33870L,33871L,33872L,33873L,33874L,33875L,33876L,33877L,
9678233878L,33879L,33880L,33881L,33882L,33883L,33884L,33885L,33886L,33887L,
9678333888L,33889L,33890L,33891L,33892L,33893L,33894L,33895L,33896L,33897L,
9678433898L,33899L,33900L,33901L,33902L,33903L,33904L,33905L,33906L,33907L,
9678533908L,33909L,33910L,33911L,33912L,33913L,33914L,33915L,33916L,33917L,
9678633918L,33919L,33920L,33921L,33922L,33923L,33924L,33925L,33926L,33927L,
9678733928L,33929L,33930L,33931L,33932L,33933L,33934L,33935L,33936L,33937L,
9678833938L,33939L,33940L,33941L,33942L,33943L,33944L,33945L,33946L,33947L,
9678933948L,33949L,33950L,33951L,33952L,33953L,33954L,33955L,33956L,33957L,
9679033958L,33959L,33960L,33961L,33962L,33963L,33964L,33965L,33966L,33967L,
9679133968L,33969L,33970L,33971L,33972L,33973L,33974L,33975L,33976L,33977L,
9679233978L,33979L,33980L,33981L,33982L,33983L,33984L,33985L,33986L,33987L,
9679333988L,33989L,33990L,33991L,33992L,33993L,33994L,33995L,33996L,33997L,
9679433998L,33999L,34000L,34001L,34002L,34003L,34004L,34005L,34006L,34007L,
9679534008L,34009L,34010L,34011L,34012L,34013L,34014L,34015L,34016L,34017L,
9679634018L,34019L,34020L,34021L,34022L,34023L,34024L,34025L,34026L,34027L,
9679734028L,34029L,34030L,34031L,34032L,34033L,34034L,34035L,34036L,34037L,
9679834038L,34039L,34040L,34041L,34042L,34043L,34044L,34045L,34046L,34047L,
9679934048L,34049L,34050L,34051L,34052L,34053L,34054L,34055L,34056L,34057L,
9680034058L,34059L,34060L,34061L,34062L,34063L,34064L,34065L,34066L,34067L,
9680134068L,34069L,34070L,34071L,34072L,34073L,34074L,34075L,34076L,34077L,
9680234078L,34079L,34080L,34081L,34082L,34083L,34084L,34085L,34086L,34087L,
9680334088L,34089L,34090L,34091L,34092L,34093L,34094L,34095L,34096L,34097L,
9680434098L,34099L,34100L,34101L,34102L,34103L,34104L,34105L,34106L,34107L,
9680534108L,34109L,34110L,34111L,34112L,34113L,34114L,34115L,34116L,34117L,
9680634118L,34119L,34120L,34121L,34122L,34123L,34124L,34125L,34126L,34127L,
9680734128L,34129L,34130L,34131L,34132L,34133L,34134L,34135L,34136L,34137L,
9680834138L,34139L,34140L,34141L,34142L,34143L,34144L,34145L,34146L,34147L,
9680934148L,34149L,34150L,34151L,34152L,34153L,34154L,34155L,34156L,34157L,
9681034158L,34159L,34160L,34161L,34162L,34163L,34164L,34165L,34166L,34167L,
9681134168L,34169L,34170L,34171L,34172L,34173L,34174L,34175L,34176L,34177L,
9681234178L,34179L,34180L,34181L,34182L,34183L,34184L,34185L,34186L,34187L,
9681334188L,34189L,34190L,34191L,34192L,34193L,34194L,34195L,34196L,34197L,
9681434198L,34199L,34200L,34201L,34202L,34203L,34204L,34205L,34206L,34207L,
9681534208L,34209L,34210L,34211L,34212L,34213L,34214L,34215L,34216L,34217L,
9681634218L,34219L,34220L,34221L,34222L,34223L,34224L,34225L,34226L,34227L,
9681734228L,34229L,34230L,34231L,34232L,34233L,34234L,34235L,34236L,34237L,
9681834238L,34239L,34240L,34241L,34242L,34243L,34244L,34245L,34246L,34247L,
9681934248L,34249L,34250L,34251L,34252L,34253L,34254L,34255L,34256L,34257L,
9682034258L,34259L,34260L,34261L,34262L,34263L,34264L,34265L,34266L,34267L,
9682134268L,34269L,34270L,34271L,34272L,34273L,34274L,34275L,34276L,34277L,
9682234278L,34279L,34280L,34281L,34282L,34283L,34284L,34285L,34286L,34287L,
9682334288L,34289L,34290L,34291L,34292L,34293L,34294L,34295L,34296L,34297L,
9682434298L,34299L,34300L,34301L,34302L,34303L,34304L,34305L,34306L,34307L,
9682534308L,34309L,34310L,34311L,34312L,34313L,34314L,34315L,34316L,34317L,
9682634318L,34319L,34320L,34321L,34322L,34323L,34324L,34325L,34326L,34327L,
9682734328L,34329L,34330L,34331L,34332L,34333L,34334L,34335L,34336L,34337L,
9682834338L,34339L,34340L,34341L,34342L,34343L,34344L,34345L,34346L,34347L,
9682934348L,34349L,34350L,34351L,34352L,34353L,34354L,34355L,34356L,34357L,
9683034358L,34359L,34360L,34361L,34362L,34363L,34364L,34365L,34366L,34367L,
9683134368L,34369L,34370L,34371L,34372L,34373L,34374L,34375L,34376L,34377L,
9683234378L,34379L,34380L,34381L,34382L,34383L,34384L,34385L,34386L,34387L,
9683334388L,34389L,34390L,34391L,34392L,34393L,34394L,34395L,34396L,34397L,
9683434398L,34399L,34400L,34401L,34402L,34403L,34404L,34405L,34406L,34407L,
9683534408L,34409L,34410L,34411L,34412L,34413L,34414L,34415L,34416L,34417L,
9683634418L,34419L,34420L,34421L,34422L,34423L,34424L,34425L,34426L,34427L,
9683734428L,34429L,34430L,34431L,34432L,34433L,34434L,34435L,34436L,34437L,
9683834438L,34439L,34440L,34441L,34442L,34443L,34444L,34445L,34446L,34447L,
9683934448L,34449L,34450L,34451L,34452L,34453L,34454L,34455L,34456L,34457L,
9684034458L,34459L,34460L,34461L,34462L,34463L,34464L,34465L,34466L,34467L,
9684134468L,34469L,34470L,34471L,34472L,34473L,34474L,34475L,34476L,34477L,
9684234478L,34479L,34480L,34481L,34482L,34483L,34484L,34485L,34486L,34487L,
9684334488L,34489L,34490L,34491L,34492L,34493L,34494L,34495L,34496L,34497L,
9684434498L,34499L,34500L,34501L,34502L,34503L,34504L,34505L,34506L,34507L,
9684534508L,34509L,34510L,34511L,34512L,34513L,34514L,34515L,34516L,34517L,
9684634518L,34519L,34520L,34521L,34522L,34523L,34524L,34525L,34526L,34527L,
9684734528L,34529L,34530L,34531L,34532L,34533L,34534L,34535L,34536L,34537L,
9684834538L,34539L,34540L,34541L,34542L,34543L,34544L,34545L,34546L,34547L,
9684934548L,34549L,34550L,34551L,34552L,34553L,34554L,34555L,34556L,34557L,
9685034558L,34559L,34560L,34561L,34562L,34563L,34564L,34565L,34566L,34567L,
9685134568L,34569L,34570L,34571L,34572L,34573L,34574L,34575L,34576L,34577L,
9685234578L,34579L,34580L,34581L,34582L,34583L,34584L,34585L,34586L,34587L,
9685334588L,34589L,34590L,34591L,34592L,34593L,34594L,34595L,34596L,34597L,
9685434598L,34599L,34600L,34601L,34602L,34603L,34604L,34605L,34606L,34607L,
9685534608L,34609L,34610L,34611L,34612L,34613L,34614L,34615L,34616L,34617L,
9685634618L,34619L,34620L,34621L,34622L,34623L,34624L,34625L,34626L,34627L,
9685734628L,34629L,34630L,34631L,34632L,34633L,34634L,34635L,34636L,34637L,
9685834638L,34639L,34640L,34641L,34642L,34643L,34644L,34645L,34646L,34647L,
9685934648L,34649L,34650L,34651L,34652L,34653L,34654L,34655L,34656L,34657L,
9686034658L,34659L,34660L,34661L,34662L,34663L,34664L,34665L,34666L,34667L,
9686134668L,34669L,34670L,34671L,34672L,34673L,34674L,34675L,34676L,34677L,
9686234678L,34679L,34680L,34681L,34682L,34683L,34684L,34685L,34686L,34687L,
9686334688L,34689L,34690L,34691L,34692L,34693L,34694L,34695L,34696L,34697L,
9686434698L,34699L,34700L,34701L,34702L,34703L,34704L,34705L,34706L,34707L,
9686534708L,34709L,34710L,34711L,34712L,34713L,34714L,34715L,34716L,34717L,
9686634718L,34719L,34720L,34721L,34722L,34723L,34724L,34725L,34726L,34727L,
9686734728L,34729L,34730L,34731L,34732L,34733L,34734L,34735L,34736L,34737L,
9686834738L,34739L,34740L,34741L,34742L,34743L,34744L,34745L,34746L,34747L,
9686934748L,34749L,34750L,34751L,34752L,34753L,34754L,34755L,34756L,34757L,
9687034758L,34759L,34760L,34761L,34762L,34763L,34764L,34765L,34766L,34767L,
9687134768L,34769L,34770L,34771L,34772L,34773L,34774L,34775L,34776L,34777L,
9687234778L,34779L,34780L,34781L,34782L,34783L,34784L,34785L,34786L,34787L,
9687334788L,34789L,34790L,34791L,34792L,34793L,34794L,34795L,34796L,34797L,
9687434798L,34799L,34800L,34801L,34802L,34803L,34804L,34805L,34806L,34807L,
9687534808L,34809L,34810L,34811L,34812L,34813L,34814L,34815L,34816L,34817L,
9687634818L,34819L,34820L,34821L,34822L,34823L,34824L,34825L,34826L,34827L,
9687734828L,34829L,34830L,34831L,34832L,34833L,34834L,34835L,34836L,34837L,
9687834838L,34839L,34840L,34841L,34842L,34843L,34844L,34845L,34846L,34847L,
9687934848L,34849L,34850L,34851L,34852L,34853L,34854L,34855L,34856L,34857L,
9688034858L,34859L,34860L,34861L,34862L,34863L,34864L,34865L,34866L,34867L,
9688134868L,34869L,34870L,34871L,34872L,34873L,34874L,34875L,34876L,34877L,
9688234878L,34879L,34880L,34881L,34882L,34883L,34884L,34885L,34886L,34887L,
9688334888L,34889L,34890L,34891L,34892L,34893L,34894L,34895L,34896L,34897L,
9688434898L,34899L,34900L,34901L,34902L,34903L,34904L,34905L,34906L,34907L,
9688534908L,34909L,34910L,34911L,34912L,34913L,34914L,34915L,34916L,34917L,
9688634918L,34919L,34920L,34921L,34922L,34923L,34924L,34925L,34926L,34927L,
9688734928L,34929L,34930L,34931L,34932L,34933L,34934L,34935L,34936L,34937L,
9688834938L,34939L,34940L,34941L,34942L,34943L,34944L,34945L,34946L,34947L,
9688934948L,34949L,34950L,34951L,34952L,34953L,34954L,34955L,34956L,34957L,
9689034958L,34959L,34960L,34961L,34962L,34963L,34964L,34965L,34966L,34967L,
9689134968L,34969L,34970L,34971L,34972L,34973L,34974L,34975L,34976L,34977L,
9689234978L,34979L,34980L,34981L,34982L,34983L,34984L,34985L,34986L,34987L,
9689334988L,34989L,34990L,34991L,34992L,34993L,34994L,34995L,34996L,34997L,
9689434998L,34999L,35000L,35001L,35002L,35003L,35004L,35005L,35006L,35007L,
9689535008L,35009L,35010L,35011L,35012L,35013L,35014L,35015L,35016L,35017L,
9689635018L,35019L,35020L,35021L,35022L,35023L,35024L,35025L,35026L,35027L,
9689735028L,35029L,35030L,35031L,35032L,35033L,35034L,35035L,35036L,35037L,
9689835038L,35039L,35040L,35041L,35042L,35043L,35044L,35045L,35046L,35047L,
9689935048L,35049L,35050L,35051L,35052L,35053L,35054L,35055L,35056L,35057L,
9690035058L,35059L,35060L,35061L,35062L,35063L,35064L,35065L,35066L,35067L,
9690135068L,35069L,35070L,35071L,35072L,35073L,35074L,35075L,35076L,35077L,
9690235078L,35079L,35080L,35081L,35082L,35083L,35084L,35085L,35086L,35087L,
9690335088L,35089L,35090L,35091L,35092L,35093L,35094L,35095L,35096L,35097L,
9690435098L,35099L,35100L,35101L,35102L,35103L,35104L,35105L,35106L,35107L,
9690535108L,35109L,35110L,35111L,35112L,35113L,35114L,35115L,35116L,35117L,
9690635118L,35119L,35120L,35121L,35122L,35123L,35124L,35125L,35126L,35127L,
9690735128L,35129L,35130L,35131L,35132L,35133L,35134L,35135L,35136L,35137L,
9690835138L,35139L,35140L,35141L,35142L,35143L,35144L,35145L,35146L,35147L,
9690935148L,35149L,35150L,35151L,35152L,35153L,35154L,35155L,35156L,35157L,
9691035158L,35159L,35160L,35161L,35162L,35163L,35164L,35165L,35166L,35167L,
9691135168L,35169L,35170L,35171L,35172L,35173L,35174L,35175L,35176L,35177L,
9691235178L,35179L,35180L,35181L,35182L,35183L,35184L,35185L,35186L,35187L,
9691335188L,35189L,35190L,35191L,35192L,35193L,35194L,35195L,35196L,35197L,
9691435198L,35199L,35200L,35201L,35202L,35203L,35204L,35205L,35206L,35207L,
9691535208L,35209L,35210L,35211L,35212L,35213L,35214L,35215L,35216L,35217L,
9691635218L,35219L,35220L,35221L,35222L,35223L,35224L,35225L,35226L,35227L,
9691735228L,35229L,35230L,35231L,35232L,35233L,35234L,35235L,35236L,35237L,
9691835238L,35239L,35240L,35241L,35242L,35243L,35244L,35245L,35246L,35247L,
9691935248L,35249L,35250L,35251L,35252L,35253L,35254L,35255L,35256L,35257L,
9692035258L,35259L,35260L,35261L,35262L,35263L,35264L,35265L,35266L,35267L,
9692135268L,35269L,35270L,35271L,35272L,35273L,35274L,35275L,35276L,35277L,
9692235278L,35279L,35280L,35281L,35282L,35283L,35284L,35285L,35286L,35287L,
9692335288L,35289L,35290L,35291L,35292L,35293L,35294L,35295L,35296L,35297L,
9692435298L,35299L,35300L,35301L,35302L,35303L,35304L,35305L,35306L,35307L,
9692535308L,35309L,35310L,35311L,35312L,35313L,35314L,35315L,35316L,35317L,
9692635318L,35319L,35320L,35321L,35322L,35323L,35324L,35325L,35326L,35327L,
9692735328L,35329L,35330L,35331L,35332L,35333L,35334L,35335L,35336L,35337L,
9692835338L,35339L,35340L,35341L,35342L,35343L,35344L,35345L,35346L,35347L,
9692935348L,35349L,35350L,35351L,35352L,35353L,35354L,35355L,35356L,35357L,
9693035358L,35359L,35360L,35361L,35362L,35363L,35364L,35365L,35366L,35367L,
9693135368L,35369L,35370L,35371L,35372L,35373L,35374L,35375L,35376L,35377L,
9693235378L,35379L,35380L,35381L,35382L,35383L,35384L,35385L,35386L,35387L,
9693335388L,35389L,35390L,35391L,35392L,35393L,35394L,35395L,35396L,35397L,
9693435398L,35399L,35400L,35401L,35402L,35403L,35404L,35405L,35406L,35407L,
9693535408L,35409L,35410L,35411L,35412L,35413L,35414L,35415L,35416L,35417L,
9693635418L,35419L,35420L,35421L,35422L,35423L,35424L,35425L,35426L,35427L,
9693735428L,35429L,35430L,35431L,35432L,35433L,35434L,35435L,35436L,35437L,
9693835438L,35439L,35440L,35441L,35442L,35443L,35444L,35445L,35446L,35447L,
9693935448L,35449L,35450L,35451L,35452L,35453L,35454L,35455L,35456L,35457L,
9694035458L,35459L,35460L,35461L,35462L,35463L,35464L,35465L,35466L,35467L,
9694135468L,35469L,35470L,35471L,35472L,35473L,35474L,35475L,35476L,35477L,
9694235478L,35479L,35480L,35481L,35482L,35483L,35484L,35485L,35486L,35487L,
9694335488L,35489L,35490L,35491L,35492L,35493L,35494L,35495L,35496L,35497L,
9694435498L,35499L,35500L,35501L,35502L,35503L,35504L,35505L,35506L,35507L,
9694535508L,35509L,35510L,35511L,35512L,35513L,35514L,35515L,35516L,35517L,
9694635518L,35519L,35520L,35521L,35522L,35523L,35524L,35525L,35526L,35527L,
9694735528L,35529L,35530L,35531L,35532L,35533L,35534L,35535L,35536L,35537L,
9694835538L,35539L,35540L,35541L,35542L,35543L,35544L,35545L,35546L,35547L,
9694935548L,35549L,35550L,35551L,35552L,35553L,35554L,35555L,35556L,35557L,
9695035558L,35559L,35560L,35561L,35562L,35563L,35564L,35565L,35566L,35567L,
9695135568L,35569L,35570L,35571L,35572L,35573L,35574L,35575L,35576L,35577L,
9695235578L,35579L,35580L,35581L,35582L,35583L,35584L,35585L,35586L,35587L,
9695335588L,35589L,35590L,35591L,35592L,35593L,35594L,35595L,35596L,35597L,
9695435598L,35599L,35600L,35601L,35602L,35603L,35604L,35605L,35606L,35607L,
9695535608L,35609L,35610L,35611L,35612L,35613L,35614L,35615L,35616L,35617L,
9695635618L,35619L,35620L,35621L,35622L,35623L,35624L,35625L,35626L,35627L,
9695735628L,35629L,35630L,35631L,35632L,35633L,35634L,35635L,35636L,35637L,
9695835638L,35639L,35640L,35641L,35642L,35643L,35644L,35645L,35646L,35647L,
9695935648L,35649L,35650L,35651L,35652L,35653L,35654L,35655L,35656L,35657L,
9696035658L,35659L,35660L,35661L,35662L,35663L,35664L,35665L,35666L,35667L,
9696135668L,35669L,35670L,35671L,35672L,35673L,35674L,35675L,35676L,35677L,
9696235678L,35679L,35680L,35681L,35682L,35683L,35684L,35685L,35686L,35687L,
9696335688L,35689L,35690L,35691L,35692L,35693L,35694L,35695L,35696L,35697L,
9696435698L,35699L,35700L,35701L,35702L,35703L,35704L,35705L,35706L,35707L,
9696535708L,35709L,35710L,35711L,35712L,35713L,35714L,35715L,35716L,35717L,
9696635718L,35719L,35720L,35721L,35722L,35723L,35724L,35725L,35726L,35727L,
9696735728L,35729L,35730L,35731L,35732L,35733L,35734L,35735L,35736L,35737L,
9696835738L,35739L,35740L,35741L,35742L,35743L,35744L,35745L,35746L,35747L,
9696935748L,35749L,35750L,35751L,35752L,35753L,35754L,35755L,35756L,35757L,
9697035758L,35759L,35760L,35761L,35762L,35763L,35764L,35765L,35766L,35767L,
9697135768L,35769L,35770L,35771L,35772L,35773L,35774L,35775L,35776L,35777L,
9697235778L,35779L,35780L,35781L,35782L,35783L,35784L,35785L,35786L,35787L,
9697335788L,35789L,35790L,35791L,35792L,35793L,35794L,35795L,35796L,35797L,
9697435798L,35799L,35800L,35801L,35802L,35803L,35804L,35805L,35806L,35807L,
9697535808L,35809L,35810L,35811L,35812L,35813L,35814L,35815L,35816L,35817L,
9697635818L,35819L,35820L,35821L,35822L,35823L,35824L,35825L,35826L,35827L,
9697735828L,35829L,35830L,35831L,35832L,35833L,35834L,35835L,35836L,35837L,
9697835838L,35839L,35840L,35841L,35842L,35843L,35844L,35845L,35846L,35847L,
9697935848L,35849L,35850L,35851L,35852L,35853L,35854L,35855L,35856L,35857L,
9698035858L,35859L,35860L,35861L,35862L,35863L,35864L,35865L,35866L,35867L,
9698135868L,35869L,35870L,35871L,35872L,35873L,35874L,35875L,35876L,35877L,
9698235878L,35879L,35880L,35881L,35882L,35883L,35884L,35885L,35886L,35887L,
9698335888L,35889L,35890L,35891L,35892L,35893L,35894L,35895L,35896L,35897L,
9698435898L,35899L,35900L,35901L,35902L,35903L,35904L,35905L,35906L,35907L,
9698535908L,35909L,35910L,35911L,35912L,35913L,35914L,35915L,35916L,35917L,
9698635918L,35919L,35920L,35921L,35922L,35923L,35924L,35925L,35926L,35927L,
9698735928L,35929L,35930L,35931L,35932L,35933L,35934L,35935L,35936L,35937L,
9698835938L,35939L,35940L,35941L,35942L,35943L,35944L,35945L,35946L,35947L,
9698935948L,35949L,35950L,35951L,35952L,35953L,35954L,35955L,35956L,35957L,
9699035958L,35959L,35960L,35961L,35962L,35963L,35964L,35965L,35966L,35967L,
9699135968L,35969L,35970L,35971L,35972L,35973L,35974L,35975L,35976L,35977L,
9699235978L,35979L,35980L,35981L,35982L,35983L,35984L,35985L,35986L,35987L,
9699335988L,35989L,35990L,35991L,35992L,35993L,35994L,35995L,35996L,35997L,
9699435998L,35999L,36000L,36001L,36002L,36003L,36004L,36005L,36006L,36007L,
9699536008L,36009L,36010L,36011L,36012L,36013L,36014L,36015L,36016L,36017L,
9699636018L,36019L,36020L,36021L,36022L,36023L,36024L,36025L,36026L,36027L,
9699736028L,36029L,36030L,36031L,36032L,36033L,36034L,36035L,36036L,36037L,
9699836038L,36039L,36040L,36041L,36042L,36043L,36044L,36045L,36046L,36047L,
9699936048L,36049L,36050L,36051L,36052L,36053L,36054L,36055L,36056L,36057L,
9700036058L,36059L,36060L,36061L,36062L,36063L,36064L,36065L,36066L,36067L,
9700136068L,36069L,36070L,36071L,36072L,36073L,36074L,36075L,36076L,36077L,
9700236078L,36079L,36080L,36081L,36082L,36083L,36084L,36085L,36086L,36087L,
9700336088L,36089L,36090L,36091L,36092L,36093L,36094L,36095L,36096L,36097L,
9700436098L,36099L,36100L,36101L,36102L,36103L,36104L,36105L,36106L,36107L,
9700536108L,36109L,36110L,36111L,36112L,36113L,36114L,36115L,36116L,36117L,
9700636118L,36119L,36120L,36121L,36122L,36123L,36124L,36125L,36126L,36127L,
9700736128L,36129L,36130L,36131L,36132L,36133L,36134L,36135L,36136L,36137L,
9700836138L,36139L,36140L,36141L,36142L,36143L,36144L,36145L,36146L,36147L,
9700936148L,36149L,36150L,36151L,36152L,36153L,36154L,36155L,36156L,36157L,
9701036158L,36159L,36160L,36161L,36162L,36163L,36164L,36165L,36166L,36167L,
9701136168L,36169L,36170L,36171L,36172L,36173L,36174L,36175L,36176L,36177L,
9701236178L,36179L,36180L,36181L,36182L,36183L,36184L,36185L,36186L,36187L,
9701336188L,36189L,36190L,36191L,36192L,36193L,36194L,36195L,36196L,36197L,
9701436198L,36199L,36200L,36201L,36202L,36203L,36204L,36205L,36206L,36207L,
9701536208L,36209L,36210L,36211L,36212L,36213L,36214L,36215L,36216L,36217L,
9701636218L,36219L,36220L,36221L,36222L,36223L,36224L,36225L,36226L,36227L,
9701736228L,36229L,36230L,36231L,36232L,36233L,36234L,36235L,36236L,36237L,
9701836238L,36239L,36240L,36241L,36242L,36243L,36244L,36245L,36246L,36247L,
9701936248L,36249L,36250L,36251L,36252L,36253L,36254L,36255L,36256L,36257L,
9702036258L,36259L,36260L,36261L,36262L,36263L,36264L,36265L,36266L,36267L,
9702136268L,36269L,36270L,36271L,36272L,36273L,36274L,36275L,36276L,36277L,
9702236278L,36279L,36280L,36281L,36282L,36283L,36284L,36285L,36286L,36287L,
9702336288L,36289L,36290L,36291L,36292L,36293L,36294L,36295L,36296L,36297L,
9702436298L,36299L,36300L,36301L,36302L,36303L,36304L,36305L,36306L,36307L,
9702536308L,36309L,36310L,36311L,36312L,36313L,36314L,36315L,36316L,36317L,
9702636318L,36319L,36320L,36321L,36322L,36323L,36324L,36325L,36326L,36327L,
9702736328L,36329L,36330L,36331L,36332L,36333L,36334L,36335L,36336L,36337L,
9702836338L,36339L,36340L,36341L,36342L,36343L,36344L,36345L,36346L,36347L,
9702936348L,36349L,36350L,36351L,36352L,36353L,36354L,36355L,36356L,36357L,
9703036358L,36359L,36360L,36361L,36362L,36363L,36364L,36365L,36366L,36367L,
9703136368L,36369L,36370L,36371L,36372L,36373L,36374L,36375L,36376L,36377L,
9703236378L,36379L,36380L,36381L,36382L,36383L,36384L,36385L,36386L,36387L,
9703336388L,36389L,36390L,36391L,36392L,36393L,36394L,36395L,36396L,36397L,
9703436398L,36399L,36400L,36401L,36402L,36403L,36404L,36405L,36406L,36407L,
9703536408L,36409L,36410L,36411L,36412L,36413L,36414L,36415L,36416L,36417L,
9703636418L,36419L,36420L,36421L,36422L,36423L,36424L,36425L,36426L,36427L,
9703736428L,36429L,36430L,36431L,36432L,36433L,36434L,36435L,36436L,36437L,
9703836438L,36439L,36440L,36441L,36442L,36443L,36444L,36445L,36446L,36447L,
9703936448L,36449L,36450L,36451L,36452L,36453L,36454L,36455L,36456L,36457L,
9704036458L,36459L,36460L,36461L,36462L,36463L,36464L,36465L,36466L,36467L,
9704136468L,36469L,36470L,36471L,36472L,36473L,36474L,36475L,36476L,36477L,
9704236478L,36479L,36480L,36481L,36482L,36483L,36484L,36485L,36486L,36487L,
9704336488L,36489L,36490L,36491L,36492L,36493L,36494L,36495L,36496L,36497L,
9704436498L,36499L,36500L,36501L,36502L,36503L,36504L,36505L,36506L,36507L,
9704536508L,36509L,36510L,36511L,36512L,36513L,36514L,36515L,36516L,36517L,
9704636518L,36519L,36520L,36521L,36522L,36523L,36524L,36525L,36526L,36527L,
9704736528L,36529L,36530L,36531L,36532L,36533L,36534L,36535L,36536L,36537L,
9704836538L,36539L,36540L,36541L,36542L,36543L,36544L,36545L,36546L,36547L,
9704936548L,36549L,36550L,36551L,36552L,36553L,36554L,36555L,36556L,36557L,
9705036558L,36559L,36560L,36561L,36562L,36563L,36564L,36565L,36566L,36567L,
9705136568L,36569L,36570L,36571L,36572L,36573L,36574L,36575L,36576L,36577L,
9705236578L,36579L,36580L,36581L,36582L,36583L,36584L,36585L,36586L,36587L,
9705336588L,36589L,36590L,36591L,36592L,36593L,36594L,36595L,36596L,36597L,
9705436598L,36599L,36600L,36601L,36602L,36603L,36604L,36605L,36606L,36607L,
9705536608L,36609L,36610L,36611L,36612L,36613L,36614L,36615L,36616L,36617L,
9705636618L,36619L,36620L,36621L,36622L,36623L,36624L,36625L,36626L,36627L,
9705736628L,36629L,36630L,36631L,36632L,36633L,36634L,36635L,36636L,36637L,
9705836638L,36639L,36640L,36641L,36642L,36643L,36644L,36645L,36646L,36647L,
9705936648L,36649L,36650L,36651L,36652L,36653L,36654L,36655L,36656L,36657L,
9706036658L,36659L,36660L,36661L,36662L,36663L,36664L,36665L,36666L,36667L,
9706136668L,36669L,36670L,36671L,36672L,36673L,36674L,36675L,36676L,36677L,
9706236678L,36679L,36680L,36681L,36682L,36683L,36684L,36685L,36686L,36687L,
9706336688L,36689L,36690L,36691L,36692L,36693L,36694L,36695L,36696L,36697L,
9706436698L,36699L,36700L,36701L,36702L,36703L,36704L,36705L,36706L,36707L,
9706536708L,36709L,36710L,36711L,36712L,36713L,36714L,36715L,36716L,36717L,
9706636718L,36719L,36720L,36721L,36722L,36723L,36724L,36725L,36726L,36727L,
9706736728L,36729L,36730L,36731L,36732L,36733L,36734L,36735L,36736L,36737L,
9706836738L,36739L,36740L,36741L,36742L,36743L,36744L,36745L,36746L,36747L,
9706936748L,36749L,36750L,36751L,36752L,36753L,36754L,36755L,36756L,36757L,
9707036758L,36759L,36760L,36761L,36762L,36763L,36764L,36765L,36766L,36767L,
9707136768L,36769L,36770L,36771L,36772L,36773L,36774L,36775L,36776L,36777L,
9707236778L,36779L,36780L,36781L,36782L,36783L,36784L,36785L,36786L,36787L,
9707336788L,36789L,36790L,36791L,36792L,36793L,36794L,36795L,36796L,36797L,
9707436798L,36799L,36800L,36801L,36802L,36803L,36804L,36805L,36806L,36807L,
9707536808L,36809L,36810L,36811L,36812L,36813L,36814L,36815L,36816L,36817L,
9707636818L,36819L,36820L,36821L,36822L,36823L,36824L,36825L,36826L,36827L,
9707736828L,36829L,36830L,36831L,36832L,36833L,36834L,36835L,36836L,36837L,
9707836838L,36839L,36840L,36841L,36842L,36843L,36844L,36845L,36846L,36847L,
9707936848L,36849L,36850L,36851L,36852L,36853L,36854L,36855L,36856L,36857L,
9708036858L,36859L,36860L,36861L,36862L,36863L,36864L,36865L,36866L,36867L,
9708136868L,36869L,36870L,36871L,36872L,36873L,36874L,36875L,36876L,36877L,
9708236878L,36879L,36880L,36881L,36882L,36883L,36884L,36885L,36886L,36887L,
9708336888L,36889L,36890L,36891L,36892L,36893L,36894L,36895L,36896L,36897L,
9708436898L,36899L,36900L,36901L,36902L,36903L,36904L,36905L,36906L,36907L,
9708536908L,36909L,36910L,36911L,36912L,36913L,36914L,36915L,36916L,36917L,
9708636918L,36919L,36920L,36921L,36922L,36923L,36924L,36925L,36926L,36927L,
9708736928L,36929L,36930L,36931L,36932L,36933L,36934L,36935L,36936L,36937L,
9708836938L,36939L,36940L,36941L,36942L,36943L,36944L,36945L,36946L,36947L,
9708936948L,36949L,36950L,36951L,36952L,36953L,36954L,36955L,36956L,36957L,
9709036958L,36959L,36960L,36961L,36962L,36963L,36964L,36965L,36966L,36967L,
9709136968L,36969L,36970L,36971L,36972L,36973L,36974L,36975L,36976L,36977L,
9709236978L,36979L,36980L,36981L,36982L,36983L,36984L,36985L,36986L,36987L,
9709336988L,36989L,36990L,36991L,36992L,36993L,36994L,36995L,36996L,36997L,
9709436998L,36999L,37000L,37001L,37002L,37003L,37004L,37005L,37006L,37007L,
9709537008L,37009L,37010L,37011L,37012L,37013L,37014L,37015L,37016L,37017L,
9709637018L,37019L,37020L,37021L,37022L,37023L,37024L,37025L,37026L,37027L,
9709737028L,37029L,37030L,37031L,37032L,37033L,37034L,37035L,37036L,37037L,
9709837038L,37039L,37040L,37041L,37042L,37043L,37044L,37045L,37046L,37047L,
9709937048L,37049L,37050L,37051L,37052L,37053L,37054L,37055L,37056L,37057L,
9710037058L,37059L,37060L,37061L,37062L,37063L,37064L,37065L,37066L,37067L,
9710137068L,37069L,37070L,37071L,37072L,37073L,37074L,37075L,37076L,37077L,
9710237078L,37079L,37080L,37081L,37082L,37083L,37084L,37085L,37086L,37087L,
9710337088L,37089L,37090L,37091L,37092L,37093L,37094L,37095L,37096L,37097L,
9710437098L,37099L,37100L,37101L,37102L,37103L,37104L,37105L,37106L,37107L,
9710537108L,37109L,37110L,37111L,37112L,37113L,37114L,37115L,37116L,37117L,
9710637118L,37119L,37120L,37121L,37122L,37123L,37124L,37125L,37126L,37127L,
9710737128L,37129L,37130L,37131L,37132L,37133L,37134L,37135L,37136L,37137L,
9710837138L,37139L,37140L,37141L,37142L,37143L,37144L,37145L,37146L,37147L,
9710937148L,37149L,37150L,37151L,37152L,37153L,37154L,37155L,37156L,37157L,
9711037158L,37159L,37160L,37161L,37162L,37163L,37164L,37165L,37166L,37167L,
9711137168L,37169L,37170L,37171L,37172L,37173L,37174L,37175L,37176L,37177L,
9711237178L,37179L,37180L,37181L,37182L,37183L,37184L,37185L,37186L,37187L,
9711337188L,37189L,37190L,37191L,37192L,37193L,37194L,37195L,37196L,37197L,
9711437198L,37199L,37200L,37201L,37202L,37203L,37204L,37205L,37206L,37207L,
9711537208L,37209L,37210L,37211L,37212L,37213L,37214L,37215L,37216L,37217L,
9711637218L,37219L,37220L,37221L,37222L,37223L,37224L,37225L,37226L,37227L,
9711737228L,37229L,37230L,37231L,37232L,37233L,37234L,37235L,37236L,37237L,
9711837238L,37239L,37240L,37241L,37242L,37243L,37244L,37245L,37246L,37247L,
9711937248L,37249L,37250L,37251L,37252L,37253L,37254L,37255L,37256L,37257L,
9712037258L,37259L,37260L,37261L,37262L,37263L,37264L,37265L,37266L,37267L,
9712137268L,37269L,37270L,37271L,37272L,37273L,37274L,37275L,37276L,37277L,
9712237278L,37279L,37280L,37281L,37282L,37283L,37284L,37285L,37286L,37287L,
9712337288L,37289L,37290L,37291L,37292L,37293L,37294L,37295L,37296L,37297L,
9712437298L,37299L,37300L,37301L,37302L,37303L,37304L,37305L,37306L,37307L,
9712537308L,37309L,37310L,37311L,37312L,37313L,37314L,37315L,37316L,37317L,
9712637318L,37319L,37320L,37321L,37322L,37323L,37324L,37325L,37326L,37327L,
9712737328L,37329L,37330L,37331L,37332L,37333L,37334L,37335L,37336L,37337L,
9712837338L,37339L,37340L,37341L,37342L,37343L,37344L,37345L,37346L,37347L,
9712937348L,37349L,37350L,37351L,37352L,37353L,37354L,37355L,37356L,37357L,
9713037358L,37359L,37360L,37361L,37362L,37363L,37364L,37365L,37366L,37367L,
9713137368L,37369L,37370L,37371L,37372L,37373L,37374L,37375L,37376L,37377L,
9713237378L,37379L,37380L,37381L,37382L,37383L,37384L,37385L,37386L,37387L,
9713337388L,37389L,37390L,37391L,37392L,37393L,37394L,37395L,37396L,37397L,
9713437398L,37399L,37400L,37401L,37402L,37403L,37404L,37405L,37406L,37407L,
9713537408L,37409L,37410L,37411L,37412L,37413L,37414L,37415L,37416L,37417L,
9713637418L,37419L,37420L,37421L,37422L,37423L,37424L,37425L,37426L,37427L,
9713737428L,37429L,37430L,37431L,37432L,37433L,37434L,37435L,37436L,37437L,
9713837438L,37439L,37440L,37441L,37442L,37443L,37444L,37445L,37446L,37447L,
9713937448L,37449L,37450L,37451L,37452L,37453L,37454L,37455L,37456L,37457L,
9714037458L,37459L,37460L,37461L,37462L,37463L,37464L,37465L,37466L,37467L,
9714137468L,37469L,37470L,37471L,37472L,37473L,37474L,37475L,37476L,37477L,
9714237478L,37479L,37480L,37481L,37482L,37483L,37484L,37485L,37486L,37487L,
9714337488L,37489L,37490L,37491L,37492L,37493L,37494L,37495L,37496L,37497L,
9714437498L,37499L,37500L,37501L,37502L,37503L,37504L,37505L,37506L,37507L,
9714537508L,37509L,37510L,37511L,37512L,37513L,37514L,37515L,37516L,37517L,
9714637518L,37519L,37520L,37521L,37522L,37523L,37524L,37525L,37526L,37527L,
9714737528L,37529L,37530L,37531L,37532L,37533L,37534L,37535L,37536L,37537L,
9714837538L,37539L,37540L,37541L,37542L,37543L,37544L,37545L,37546L,37547L,
9714937548L,37549L,37550L,37551L,37552L,37553L,37554L,37555L,37556L,37557L,
9715037558L,37559L,37560L,37561L,37562L,37563L,37564L,37565L,37566L,37567L,
9715137568L,37569L,37570L,37571L,37572L,37573L,37574L,37575L,37576L,37577L,
9715237578L,37579L,37580L,37581L,37582L,37583L,37584L,37585L,37586L,37587L,
9715337588L,37589L,37590L,37591L,37592L,37593L,37594L,37595L,37596L,37597L,
9715437598L,37599L,37600L,37601L,37602L,37603L,37604L,37605L,37606L,37607L,
9715537608L,37609L,37610L,37611L,37612L,37613L,37614L,37615L,37616L,37617L,
9715637618L,37619L,37620L,37621L,37622L,37623L,37624L,37625L,37626L,37627L,
9715737628L,37629L,37630L,37631L,37632L,37633L,37634L,37635L,37636L,37637L,
9715837638L,37639L,37640L,37641L,37642L,37643L,37644L,37645L,37646L,37647L,
9715937648L,37649L,37650L,37651L,37652L,37653L,37654L,37655L,37656L,37657L,
9716037658L,37659L,37660L,37661L,37662L,37663L,37664L,37665L,37666L,37667L,
9716137668L,37669L,37670L,37671L,37672L,37673L,37674L,37675L,37676L,37677L,
9716237678L,37679L,37680L,37681L,37682L,37683L,37684L,37685L,37686L,37687L,
9716337688L,37689L,37690L,37691L,37692L,37693L,37694L,37695L,37696L,37697L,
9716437698L,37699L,37700L,37701L,37702L,37703L,37704L,37705L,37706L,37707L,
9716537708L,37709L,37710L,37711L,37712L,37713L,37714L,37715L,37716L,37717L,
9716637718L,37719L,37720L,37721L,37722L,37723L,37724L,37725L,37726L,37727L,
9716737728L,37729L,37730L,37731L,37732L,37733L,37734L,37735L,37736L,37737L,
9716837738L,37739L,37740L,37741L,37742L,37743L,37744L,37745L,37746L,37747L,
9716937748L,37749L,37750L,37751L,37752L,37753L,37754L,37755L,37756L,37757L,
9717037758L,37759L,37760L,37761L,37762L,37763L,37764L,37765L,37766L,37767L,
9717137768L,37769L,37770L,37771L,37772L,37773L,37774L,37775L,37776L,37777L,
9717237778L,37779L,37780L,37781L,37782L,37783L,37784L,37785L,37786L,37787L,
9717337788L,37789L,37790L,37791L,37792L,37793L,37794L,37795L,37796L,37797L,
9717437798L,37799L,37800L,37801L,37802L,37803L,37804L,37805L,37806L,37807L,
9717537808L,37809L,37810L,37811L,37812L,37813L,37814L,37815L,37816L,37817L,
9717637818L,37819L,37820L,37821L,37822L,37823L,37824L,37825L,37826L,37827L,
9717737828L,37829L,37830L,37831L,37832L,37833L,37834L,37835L,37836L,37837L,
9717837838L,37839L,37840L,37841L,37842L,37843L,37844L,37845L,37846L,37847L,
9717937848L,37849L,37850L,37851L,37852L,37853L,37854L,37855L,37856L,37857L,
9718037858L,37859L,37860L,37861L,37862L,37863L,37864L,37865L,37866L,37867L,
9718137868L,37869L,37870L,37871L,37872L,37873L,37874L,37875L,37876L,37877L,
9718237878L,37879L,37880L,37881L,37882L,37883L,37884L,37885L,37886L,37887L,
9718337888L,37889L,37890L,37891L,37892L,37893L,37894L,37895L,37896L,37897L,
9718437898L,37899L,37900L,37901L,37902L,37903L,37904L,37905L,37906L,37907L,
9718537908L,37909L,37910L,37911L,37912L,37913L,37914L,37915L,37916L,37917L,
9718637918L,37919L,37920L,37921L,37922L,37923L,37924L,37925L,37926L,37927L,
9718737928L,37929L,37930L,37931L,37932L,37933L,37934L,37935L,37936L,37937L,
9718837938L,37939L,37940L,37941L,37942L,37943L,37944L,37945L,37946L,37947L,
9718937948L,37949L,37950L,37951L,37952L,37953L,37954L,37955L,37956L,37957L,
9719037958L,37959L,37960L,37961L,37962L,37963L,37964L,37965L,37966L,37967L,
9719137968L,37969L,37970L,37971L,37972L,37973L,37974L,37975L,37976L,37977L,
9719237978L,37979L,37980L,37981L,37982L,37983L,37984L,37985L,37986L,37987L,
9719337988L,37989L,37990L,37991L,37992L,37993L,37994L,37995L,37996L,37997L,
9719437998L,37999L,38000L,38001L,38002L,38003L,38004L,38005L,38006L,38007L,
9719538008L,38009L,38010L,38011L,38012L,38013L,38014L,38015L,38016L,38017L,
9719638018L,38019L,38020L,38021L,38022L,38023L,38024L,38025L,38026L,38027L,
9719738028L,38029L,38030L,38031L,38032L,38033L,38034L,38035L,38036L,38037L,
9719838038L,38039L,38040L,38041L,38042L,38043L,38044L,38045L,38046L,38047L,
9719938048L,38049L,38050L,38051L,38052L,38053L,38054L,38055L,38056L,38057L,
9720038058L,38059L,38060L,38061L,38062L,38063L,38064L,38065L,38066L,38067L,
9720138068L,38069L,38070L,38071L,38072L,38073L,38074L,38075L,38076L,38077L,
9720238078L,38079L,38080L,38081L,38082L,38083L,38084L,38085L,38086L,38087L,
9720338088L,38089L,38090L,38091L,38092L,38093L,38094L,38095L,38096L,38097L,
9720438098L,38099L,38100L,38101L,38102L,38103L,38104L,38105L,38106L,38107L,
9720538108L,38109L,38110L,38111L,38112L,38113L,38114L,38115L,38116L,38117L,
9720638118L,38119L,38120L,38121L,38122L,38123L,38124L,38125L,38126L,38127L,
9720738128L,38129L,38130L,38131L,38132L,38133L,38134L,38135L,38136L,38137L,
9720838138L,38139L,38140L,38141L,38142L,38143L,38144L,38145L,38146L,38147L,
9720938148L,38149L,38150L,38151L,38152L,38153L,38154L,38155L,38156L,38157L,
9721038158L,38159L,38160L,38161L,38162L,38163L,38164L,38165L,38166L,38167L,
9721138168L,38169L,38170L,38171L,38172L,38173L,38174L,38175L,38176L,38177L,
9721238178L,38179L,38180L,38181L,38182L,38183L,38184L,38185L,38186L,38187L,
9721338188L,38189L,38190L,38191L,38192L,38193L,38194L,38195L,38196L,38197L,
9721438198L,38199L,38200L,38201L,38202L,38203L,38204L,38205L,38206L,38207L,
9721538208L,38209L,38210L,38211L,38212L,38213L,38214L,38215L,38216L,38217L,
9721638218L,38219L,38220L,38221L,38222L,38223L,38224L,38225L,38226L,38227L,
9721738228L,38229L,38230L,38231L,38232L,38233L,38234L,38235L,38236L,38237L,
9721838238L,38239L,38240L,38241L,38242L,38243L,38244L,38245L,38246L,38247L,
9721938248L,38249L,38250L,38251L,38252L,38253L,38254L,38255L,38256L,38257L,
9722038258L,38259L,38260L,38261L,38262L,38263L,38264L,38265L,38266L,38267L,
9722138268L,38269L,38270L,38271L,38272L,38273L,38274L,38275L,38276L,38277L,
9722238278L,38279L,38280L,38281L,38282L,38283L,38284L,38285L,38286L,38287L,
9722338288L,38289L,38290L,38291L,38292L,38293L,38294L,38295L,38296L,38297L,
9722438298L,38299L,38300L,38301L,38302L,38303L,38304L,38305L,38306L,38307L,
9722538308L,38309L,38310L,38311L,38312L,38313L,38314L,38315L,38316L,38317L,
9722638318L,38319L,38320L,38321L,38322L,38323L,38324L,38325L,38326L,38327L,
9722738328L,38329L,38330L,38331L,38332L,38333L,38334L,38335L,38336L,38337L,
9722838338L,38339L,38340L,38341L,38342L,38343L,38344L,38345L,38346L,38347L,
9722938348L,38349L,38350L,38351L,38352L,38353L,38354L,38355L,38356L,38357L,
9723038358L,38359L,38360L,38361L,38362L,38363L,38364L,38365L,38366L,38367L,
9723138368L,38369L,38370L,38371L,38372L,38373L,38374L,38375L,38376L,38377L,
9723238378L,38379L,38380L,38381L,38382L,38383L,38384L,38385L,38386L,38387L,
9723338388L,38389L,38390L,38391L,38392L,38393L,38394L,38395L,38396L,38397L,
9723438398L,38399L,38400L,38401L,38402L,38403L,38404L,38405L,38406L,38407L,
9723538408L,38409L,38410L,38411L,38412L,38413L,38414L,38415L,38416L,38417L,
9723638418L,38419L,38420L,38421L,38422L,38423L,38424L,38425L,38426L,38427L,
9723738428L,38429L,38430L,38431L,38432L,38433L,38434L,38435L,38436L,38437L,
9723838438L,38439L,38440L,38441L,38442L,38443L,38444L,38445L,38446L,38447L,
9723938448L,38449L,38450L,38451L,38452L,38453L,38454L,38455L,38456L,38457L,
9724038458L,38459L,38460L,38461L,38462L,38463L,38464L,38465L,38466L,38467L,
9724138468L,38469L,38470L,38471L,38472L,38473L,38474L,38475L,38476L,38477L,
9724238478L,38479L,38480L,38481L,38482L,38483L,38484L,38485L,38486L,38487L,
9724338488L,38489L,38490L,38491L,38492L,38493L,38494L,38495L,38496L,38497L,
9724438498L,38499L,38500L,38501L,38502L,38503L,38504L,38505L,38506L,38507L,
9724538508L,38509L,38510L,38511L,38512L,38513L,38514L,38515L,38516L,38517L,
9724638518L,38519L,38520L,38521L,38522L,38523L,38524L,38525L,38526L,38527L,
9724738528L,38529L,38530L,38531L,38532L,38533L,38534L,38535L,38536L,38537L,
9724838538L,38539L,38540L,38541L,38542L,38543L,38544L,38545L,38546L,38547L,
9724938548L,38549L,38550L,38551L,38552L,38553L,38554L,38555L,38556L,38557L,
9725038558L,38559L,38560L,38561L,38562L,38563L,38564L,38565L,38566L,38567L,
9725138568L,38569L,38570L,38571L,38572L,38573L,38574L,38575L,38576L,38577L,
9725238578L,38579L,38580L,38581L,38582L,38583L,38584L,38585L,38586L,38587L,
9725338588L,38589L,38590L,38591L,38592L,38593L,38594L,38595L,38596L,38597L,
9725438598L,38599L,38600L,38601L,38602L,38603L,38604L,38605L,38606L,38607L,
9725538608L,38609L,38610L,38611L,38612L,38613L,38614L,38615L,38616L,38617L,
9725638618L,38619L,38620L,38621L,38622L,38623L,38624L,38625L,38626L,38627L,
9725738628L,38629L,38630L,38631L,38632L,38633L,38634L,38635L,38636L,38637L,
9725838638L,38639L,38640L,38641L,38642L,38643L,38644L,38645L,38646L,38647L,
9725938648L,38649L,38650L,38651L,38652L,38653L,38654L,38655L,38656L,38657L,
9726038658L,38659L,38660L,38661L,38662L,38663L,38664L,38665L,38666L,38667L,
9726138668L,38669L,38670L,38671L,38672L,38673L,38674L,38675L,38676L,38677L,
9726238678L,38679L,38680L,38681L,38682L,38683L,38684L,38685L,38686L,38687L,
9726338688L,38689L,38690L,38691L,38692L,38693L,38694L,38695L,38696L,38697L,
9726438698L,38699L,38700L,38701L,38702L,38703L,38704L,38705L,38706L,38707L,
9726538708L,38709L,38710L,38711L,38712L,38713L,38714L,38715L,38716L,38717L,
9726638718L,38719L,38720L,38721L,38722L,38723L,38724L,38725L,38726L,38727L,
9726738728L,38729L,38730L,38731L,38732L,38733L,38734L,38735L,38736L,38737L,
9726838738L,38739L,38740L,38741L,38742L,38743L,38744L,38745L,38746L,38747L,
9726938748L,38749L,38750L,38751L,38752L,38753L,38754L,38755L,38756L,38757L,
9727038758L,38759L,38760L,38761L,38762L,38763L,38764L,38765L,38766L,38767L,
9727138768L,38769L,38770L,38771L,38772L,38773L,38774L,38775L,38776L,38777L,
9727238778L,38779L,38780L,38781L,38782L,38783L,38784L,38785L,38786L,38787L,
9727338788L,38789L,38790L,38791L,38792L,38793L,38794L,38795L,38796L,38797L,
9727438798L,38799L,38800L,38801L,38802L,38803L,38804L,38805L,38806L,38807L,
9727538808L,38809L,38810L,38811L,38812L,38813L,38814L,38815L,38816L,38817L,
9727638818L,38819L,38820L,38821L,38822L,38823L,38824L,38825L,38826L,38827L,
9727738828L,38829L,38830L,38831L,38832L,38833L,38834L,38835L,38836L,38837L,
9727838838L,38839L,38840L,38841L,38842L,38843L,38844L,38845L,38846L,38847L,
9727938848L,38849L,38850L,38851L,38852L,38853L,38854L,38855L,38856L,38857L,
9728038858L,38859L,38860L,38861L,38862L,38863L,38864L,38865L,38866L,38867L,
9728138868L,38869L,38870L,38871L,38872L,38873L,38874L,38875L,38876L,38877L,
9728238878L,38879L,38880L,38881L,38882L,38883L,38884L,38885L,38886L,38887L,
9728338888L,38889L,38890L,38891L,38892L,38893L,38894L,38895L,38896L,38897L,
9728438898L,38899L,38900L,38901L,38902L,38903L,38904L,38905L,38906L,38907L,
9728538908L,38909L,38910L,38911L,38912L,38913L,38914L,38915L,38916L,38917L,
9728638918L,38919L,38920L,38921L,38922L,38923L,38924L,38925L,38926L,38927L,
9728738928L,38929L,38930L,38931L,38932L,38933L,38934L,38935L,38936L,38937L,
9728838938L,38939L,38940L,38941L,38942L,38943L,38944L,38945L,38946L,38947L,
9728938948L,38949L,38950L,38951L,38952L,38953L,38954L,38955L,38956L,38957L,
9729038958L,38959L,38960L,38961L,38962L,38963L,38964L,38965L,38966L,38967L,
9729138968L,38969L,38970L,38971L,38972L,38973L,38974L,38975L,38976L,38977L,
9729238978L,38979L,38980L,38981L,38982L,38983L,38984L,38985L,38986L,38987L,
9729338988L,38989L,38990L,38991L,38992L,38993L,38994L,38995L,38996L,38997L,
9729438998L,38999L,39000L,39001L,39002L,39003L,39004L,39005L,39006L,39007L,
9729539008L,39009L,39010L,39011L,39012L,39013L,39014L,39015L,39016L,39017L,
9729639018L,39019L,39020L,39021L,39022L,39023L,39024L,39025L,39026L,39027L,
9729739028L,39029L,39030L,39031L,39032L,39033L,39034L,39035L,39036L,39037L,
9729839038L,39039L,39040L,39041L,39042L,39043L,39044L,39045L,39046L,39047L,
9729939048L,39049L,39050L,39051L,39052L,39053L,39054L,39055L,39056L,39057L,
9730039058L,39059L,39060L,39061L,39062L,39063L,39064L,39065L,39066L,39067L,
9730139068L,39069L,39070L,39071L,39072L,39073L,39074L,39075L,39076L,39077L,
9730239078L,39079L,39080L,39081L,39082L,39083L,39084L,39085L,39086L,39087L,
9730339088L,39089L,39090L,39091L,39092L,39093L,39094L,39095L,39096L,39097L,
9730439098L,39099L,39100L,39101L,39102L,39103L,39104L,39105L,39106L,39107L,
9730539108L,39109L,39110L,39111L,39112L,39113L,39114L,39115L,39116L,39117L,
9730639118L,39119L,39120L,39121L,39122L,39123L,39124L,39125L,39126L,39127L,
9730739128L,39129L,39130L,39131L,39132L,39133L,39134L,39135L,39136L,39137L,
9730839138L,39139L,39140L,39141L,39142L,39143L,39144L,39145L,39146L,39147L,
9730939148L,39149L,39150L,39151L,39152L,39153L,39154L,39155L,39156L,39157L,
9731039158L,39159L,39160L,39161L,39162L,39163L,39164L,39165L,39166L,39167L,
9731139168L,39169L,39170L,39171L,39172L,39173L,39174L,39175L,39176L,39177L,
9731239178L,39179L,39180L,39181L,39182L,39183L,39184L,39185L,39186L,39187L,
9731339188L,39189L,39190L,39191L,39192L,39193L,39194L,39195L,39196L,39197L,
9731439198L,39199L,39200L,39201L,39202L,39203L,39204L,39205L,39206L,39207L,
9731539208L,39209L,39210L,39211L,39212L,39213L,39214L,39215L,39216L,39217L,
9731639218L,39219L,39220L,39221L,39222L,39223L,39224L,39225L,39226L,39227L,
9731739228L,39229L,39230L,39231L,39232L,39233L,39234L,39235L,39236L,39237L,
9731839238L,39239L,39240L,39241L,39242L,39243L,39244L,39245L,39246L,39247L,
9731939248L,39249L,39250L,39251L,39252L,39253L,39254L,39255L,39256L,39257L,
9732039258L,39259L,39260L,39261L,39262L,39263L,39264L,39265L,39266L,39267L,
9732139268L,39269L,39270L,39271L,39272L,39273L,39274L,39275L,39276L,39277L,
9732239278L,39279L,39280L,39281L,39282L,39283L,39284L,39285L,39286L,39287L,
9732339288L,39289L,39290L,39291L,39292L,39293L,39294L,39295L,39296L,39297L,
9732439298L,39299L,39300L,39301L,39302L,39303L,39304L,39305L,39306L,39307L,
9732539308L,39309L,39310L,39311L,39312L,39313L,39314L,39315L,39316L,39317L,
9732639318L,39319L,39320L,39321L,39322L,39323L,39324L,39325L,39326L,39327L,
9732739328L,39329L,39330L,39331L,39332L,39333L,39334L,39335L,39336L,39337L,
9732839338L,39339L,39340L,39341L,39342L,39343L,39344L,39345L,39346L,39347L,
9732939348L,39349L,39350L,39351L,39352L,39353L,39354L,39355L,39356L,39357L,
9733039358L,39359L,39360L,39361L,39362L,39363L,39364L,39365L,39366L,39367L,
9733139368L,39369L,39370L,39371L,39372L,39373L,39374L,39375L,39376L,39377L,
9733239378L,39379L,39380L,39381L,39382L,39383L,39384L,39385L,39386L,39387L,
9733339388L,39389L,39390L,39391L,39392L,39393L,39394L,39395L,39396L,39397L,
9733439398L,39399L,39400L,39401L,39402L,39403L,39404L,39405L,39406L,39407L,
9733539408L,39409L,39410L,39411L,39412L,39413L,39414L,39415L,39416L,39417L,
9733639418L,39419L,39420L,39421L,39422L,39423L,39424L,39425L,39426L,39427L,
9733739428L,39429L,39430L,39431L,39432L,39433L,39434L,39435L,39436L,39437L,
9733839438L,39439L,39440L,39441L,39442L,39443L,39444L,39445L,39446L,39447L,
9733939448L,39449L,39450L,39451L,39452L,39453L,39454L,39455L,39456L,39457L,
9734039458L,39459L,39460L,39461L,39462L,39463L,39464L,39465L,39466L,39467L,
9734139468L,39469L,39470L,39471L,39472L,39473L,39474L,39475L,39476L,39477L,
9734239478L,39479L,39480L,39481L,39482L,39483L,39484L,39485L,39486L,39487L,
9734339488L,39489L,39490L,39491L,39492L,39493L,39494L,39495L,39496L,39497L,
9734439498L,39499L,39500L,39501L,39502L,39503L,39504L,39505L,39506L,39507L,
9734539508L,39509L,39510L,39511L,39512L,39513L,39514L,39515L,39516L,39517L,
9734639518L,39519L,39520L,39521L,39522L,39523L,39524L,39525L,39526L,39527L,
9734739528L,39529L,39530L,39531L,39532L,39533L,39534L,39535L,39536L,39537L,
9734839538L,39539L,39540L,39541L,39542L,39543L,39544L,39545L,39546L,39547L,
9734939548L,39549L,39550L,39551L,39552L,39553L,39554L,39555L,39556L,39557L,
9735039558L,39559L,39560L,39561L,39562L,39563L,39564L,39565L,39566L,39567L,
9735139568L,39569L,39570L,39571L,39572L,39573L,39574L,39575L,39576L,39577L,
9735239578L,39579L,39580L,39581L,39582L,39583L,39584L,39585L,39586L,39587L,
9735339588L,39589L,39590L,39591L,39592L,39593L,39594L,39595L,39596L,39597L,
9735439598L,39599L,39600L,39601L,39602L,39603L,39604L,39605L,39606L,39607L,
9735539608L,39609L,39610L,39611L,39612L,39613L,39614L,39615L,39616L,39617L,
9735639618L,39619L,39620L,39621L,39622L,39623L,39624L,39625L,39626L,39627L,
9735739628L,39629L,39630L,39631L,39632L,39633L,39634L,39635L,39636L,39637L,
9735839638L,39639L,39640L,39641L,39642L,39643L,39644L,39645L,39646L,39647L,
9735939648L,39649L,39650L,39651L,39652L,39653L,39654L,39655L,39656L,39657L,
9736039658L,39659L,39660L,39661L,39662L,39663L,39664L,39665L,39666L,39667L,
9736139668L,39669L,39670L,39671L,39672L,39673L,39674L,39675L,39676L,39677L,
9736239678L,39679L,39680L,39681L,39682L,39683L,39684L,39685L,39686L,39687L,
9736339688L,39689L,39690L,39691L,39692L,39693L,39694L,39695L,39696L,39697L,
9736439698L,39699L,39700L,39701L,39702L,39703L,39704L,39705L,39706L,39707L,
9736539708L,39709L,39710L,39711L,39712L,39713L,39714L,39715L,39716L,39717L,
9736639718L,39719L,39720L,39721L,39722L,39723L,39724L,39725L,39726L,39727L,
9736739728L,39729L,39730L,39731L,39732L,39733L,39734L,39735L,39736L,39737L,
9736839738L,39739L,39740L,39741L,39742L,39743L,39744L,39745L,39746L,39747L,
9736939748L,39749L,39750L,39751L,39752L,39753L,39754L,39755L,39756L,39757L,
9737039758L,39759L,39760L,39761L,39762L,39763L,39764L,39765L,39766L,39767L,
9737139768L,39769L,39770L,39771L,39772L,39773L,39774L,39775L,39776L,39777L,
9737239778L,39779L,39780L,39781L,39782L,39783L,39784L,39785L,39786L,39787L,
9737339788L,39789L,39790L,39791L,39792L,39793L,39794L,39795L,39796L,39797L,
9737439798L,39799L,39800L,39801L,39802L,39803L,39804L,39805L,39806L,39807L,
9737539808L,39809L,39810L,39811L,39812L,39813L,39814L,39815L,39816L,39817L,
9737639818L,39819L,39820L,39821L,39822L,39823L,39824L,39825L,39826L,39827L,
9737739828L,39829L,39830L,39831L,39832L,39833L,39834L,39835L,39836L,39837L,
9737839838L,39839L,39840L,39841L,39842L,39843L,39844L,39845L,39846L,39847L,
9737939848L,39849L,39850L,39851L,39852L,39853L,39854L,39855L,39856L,39857L,
9738039858L,39859L,39860L,39861L,39862L,39863L,39864L,39865L,39866L,39867L,
9738139868L,39869L,39870L,39871L,39872L,39873L,39874L,39875L,39876L,39877L,
9738239878L,39879L,39880L,39881L,39882L,39883L,39884L,39885L,39886L,39887L,
9738339888L,39889L,39890L,39891L,39892L,39893L,39894L,39895L,39896L,39897L,
9738439898L,39899L,39900L,39901L,39902L,39903L,39904L,39905L,39906L,39907L,
9738539908L,39909L,39910L,39911L,39912L,39913L,39914L,39915L,39916L,39917L,
9738639918L,39919L,39920L,39921L,39922L,39923L,39924L,39925L,39926L,39927L,
9738739928L,39929L,39930L,39931L,39932L,39933L,39934L,39935L,39936L,39937L,
9738839938L,39939L,39940L,39941L,39942L,39943L,39944L,39945L,39946L,39947L,
9738939948L,39949L,39950L,39951L,39952L,39953L,39954L,39955L,39956L,39957L,
9739039958L,39959L,39960L,39961L,39962L,39963L,39964L,39965L,39966L,39967L,
9739139968L,39969L,39970L,39971L,39972L,39973L,39974L,39975L,39976L,39977L,
9739239978L,39979L,39980L,39981L,39982L,39983L,39984L,39985L,39986L,39987L,
9739339988L,39989L,39990L,39991L,39992L,39993L,39994L,39995L,39996L,39997L,
9739439998L,39999L,40000L,40001L,40002L,40003L,40004L,40005L,40006L,40007L,
9739540008L,40009L,40010L,40011L,40012L,40013L,40014L,40015L,40016L,40017L,
9739640018L,40019L,40020L,40021L,40022L,40023L,40024L,40025L,40026L,40027L,
9739740028L,40029L,40030L,40031L,40032L,40033L,40034L,40035L,40036L,40037L,
9739840038L,40039L,40040L,40041L,40042L,40043L,40044L,40045L,40046L,40047L,
9739940048L,40049L,40050L,40051L,40052L,40053L,40054L,40055L,40056L,40057L,
9740040058L,40059L,40060L,40061L,40062L,40063L,40064L,40065L,40066L,40067L,
9740140068L,40069L,40070L,40071L,40072L,40073L,40074L,40075L,40076L,40077L,
9740240078L,40079L,40080L,40081L,40082L,40083L,40084L,40085L,40086L,40087L,
9740340088L,40089L,40090L,40091L,40092L,40093L,40094L,40095L,40096L,40097L,
9740440098L,40099L,40100L,40101L,40102L,40103L,40104L,40105L,40106L,40107L,
9740540108L,40109L,40110L,40111L,40112L,40113L,40114L,40115L,40116L,40117L,
9740640118L,40119L,40120L,40121L,40122L,40123L,40124L,40125L,40126L,40127L,
9740740128L,40129L,40130L,40131L,40132L,40133L,40134L,40135L,40136L,40137L,
9740840138L,40139L,40140L,40141L,40142L,40143L,40144L,40145L,40146L,40147L,
9740940148L,40149L,40150L,40151L,40152L,40153L,40154L,40155L,40156L,40157L,
9741040158L,40159L,40160L,40161L,40162L,40163L,40164L,40165L,40166L,40167L,
9741140168L,40169L,40170L,40171L,40172L,40173L,40174L,40175L,40176L,40177L,
9741240178L,40179L,40180L,40181L,40182L,40183L,40184L,40185L,40186L,40187L,
9741340188L,40189L,40190L,40191L,40192L,40193L,40194L,40195L,40196L,40197L,
9741440198L,40199L,40200L,40201L,40202L,40203L,40204L,40205L,40206L,40207L,
9741540208L,40209L,40210L,40211L,40212L,40213L,40214L,40215L,40216L,40217L,
9741640218L,40219L,40220L,40221L,40222L,40223L,40224L,40225L,40226L,40227L,
9741740228L,40229L,40230L,40231L,40232L,40233L,40234L,40235L,40236L,40237L,
9741840238L,40239L,40240L,40241L,40242L,40243L,40244L,40245L,40246L,40247L,
9741940248L,40249L,40250L,40251L,40252L,40253L,40254L,40255L,40256L,40257L,
9742040258L,40259L,40260L,40261L,40262L,40263L,40264L,40265L,40266L,40267L,
9742140268L,40269L,40270L,40271L,40272L,40273L,40274L,40275L,40276L,40277L,
9742240278L,40279L,40280L,40281L,40282L,40283L,40284L,40285L,40286L,40287L,
9742340288L,40289L,40290L,40291L,40292L,40293L,40294L,40295L,40296L,40297L,
9742440298L,40299L,40300L,40301L,40302L,40303L,40304L,40305L,40306L,40307L,
9742540308L,40309L,40310L,40311L,40312L,40313L,40314L,40315L,40316L,40317L,
9742640318L,40319L,40320L,40321L,40322L,40323L,40324L,40325L,40326L,40327L,
9742740328L,40329L,40330L,40331L,40332L,40333L,40334L,40335L,40336L,40337L,
9742840338L,40339L,40340L,40341L,40342L,40343L,40344L,40345L,40346L,40347L,
9742940348L,40349L,40350L,40351L,40352L,40353L,40354L,40355L,40356L,40357L,
9743040358L,40359L,40360L,40361L,40362L,40363L,40364L,40365L,40366L,40367L,
9743140368L,40369L,40370L,40371L,40372L,40373L,40374L,40375L,40376L,40377L,
9743240378L,40379L,40380L,40381L,40382L,40383L,40384L,40385L,40386L,40387L,
9743340388L,40389L,40390L,40391L,40392L,40393L,40394L,40395L,40396L,40397L,
9743440398L,40399L,40400L,40401L,40402L,40403L,40404L,40405L,40406L,40407L,
9743540408L,40409L,40410L,40411L,40412L,40413L,40414L,40415L,40416L,40417L,
9743640418L,40419L,40420L,40421L,40422L,40423L,40424L,40425L,40426L,40427L,
9743740428L,40429L,40430L,40431L,40432L,40433L,40434L,40435L,40436L,40437L,
9743840438L,40439L,40440L,40441L,40442L,40443L,40444L,40445L,40446L,40447L,
9743940448L,40449L,40450L,40451L,40452L,40453L,40454L,40455L,40456L,40457L,
9744040458L,40459L,40460L,40461L,40462L,40463L,40464L,40465L,40466L,40467L,
9744140468L,40469L,40470L,40471L,40472L,40473L,40474L,40475L,40476L,40477L,
9744240478L,40479L,40480L,40481L,40482L,40483L,40484L,40485L,40486L,40487L,
9744340488L,40489L,40490L,40491L,40492L,40493L,40494L,40495L,40496L,40497L,
9744440498L,40499L,40500L,40501L,40502L,40503L,40504L,40505L,40506L,40507L,
9744540508L,40509L,40510L,40511L,40512L,40513L,40514L,40515L,40516L,40517L,
9744640518L,40519L,40520L,40521L,40522L,40523L,40524L,40525L,40526L,40527L,
9744740528L,40529L,40530L,40531L,40532L,40533L,40534L,40535L,40536L,40537L,
9744840538L,40539L,40540L,40541L,40542L,40543L,40544L,40545L,40546L,40547L,
9744940548L,40549L,40550L,40551L,40552L,40553L,40554L,40555L,40556L,40557L,
9745040558L,40559L,40560L,40561L,40562L,40563L,40564L,40565L,40566L,40567L,
9745140568L,40569L,40570L,40571L,40572L,40573L,40574L,40575L,40576L,40577L,
9745240578L,40579L,40580L,40581L,40582L,40583L,40584L,40585L,40586L,40587L,
9745340588L,40589L,40590L,40591L,40592L,40593L,40594L,40595L,40596L,40597L,
9745440598L,40599L,40600L,40601L,40602L,40603L,40604L,40605L,40606L,40607L,
9745540608L,40609L,40610L,40611L,40612L,40613L,40614L,40615L,40616L,40617L,
9745640618L,40619L,40620L,40621L,40622L,40623L,40624L,40625L,40626L,40627L,
9745740628L,40629L,40630L,40631L,40632L,40633L,40634L,40635L,40636L,40637L,
9745840638L,40639L,40640L,40641L,40642L,40643L,40644L,40645L,40646L,40647L,
9745940648L,40649L,40650L,40651L,40652L,40653L,40654L,40655L,40656L,40657L,
9746040658L,40659L,40660L,40661L,40662L,40663L,40664L,40665L,40666L,40667L,
9746140668L,40669L,40670L,40671L,40672L,40673L,40674L,40675L,40676L,40677L,
9746240678L,40679L,40680L,40681L,40682L,40683L,40684L,40685L,40686L,40687L,
9746340688L,40689L,40690L,40691L,40692L,40693L,40694L,40695L,40696L,40697L,
9746440698L,40699L,40700L,40701L,40702L,40703L,40704L,40705L,40706L,40707L,
9746540708L,40709L,40710L,40711L,40712L,40713L,40714L,40715L,40716L,40717L,
9746640718L,40719L,40720L,40721L,40722L,40723L,40724L,40725L,40726L,40727L,
9746740728L,40729L,40730L,40731L,40732L,40733L,40734L,40735L,40736L,40737L,
9746840738L,40739L,40740L,40741L,40742L,40743L,40744L,40745L,40746L,40747L,
9746940748L,40749L,40750L,40751L,40752L,40753L,40754L,40755L,40756L,40757L,
9747040758L,40759L,40760L,40761L,40762L,40763L,40764L,40765L,40766L,40767L,
9747140768L,40769L,40770L,40771L,40772L,40773L,40774L,40775L,40776L,40777L,
9747240778L,40779L,40780L,40781L,40782L,40783L,40784L,40785L,40786L,40787L,
9747340788L,40789L,40790L,40791L,40792L,40793L,40794L,40795L,40796L,40797L,
9747440798L,40799L,40800L,40801L,40802L,40803L,40804L,40805L,40806L,40807L,
9747540808L,40809L,40810L,40811L,40812L,40813L,40814L,40815L,40816L,40817L,
9747640818L,40819L,40820L,40821L,40822L,40823L,40824L,40825L,40826L,40827L,
9747740828L,40829L,40830L,40831L,40832L,40833L,40834L,40835L,40836L,40837L,
9747840838L,40839L,40840L,40841L,40842L,40843L,40844L,40845L,40846L,40847L,
9747940848L,40849L,40850L,40851L,40852L,40853L,40854L,40855L,40856L,40857L,
9748040858L,40859L,40860L,40861L,40862L,40863L,40864L,40865L,40866L,40867L,
9748140868L,40869L,40870L,40871L,40872L,40873L,40874L,40875L,40876L,40877L,
9748240878L,40879L,40880L,40881L,40882L,40883L,40884L,40885L,40886L,40887L,
9748340888L,40889L,40890L,40891L,40892L,40893L,40894L,40895L,40896L,40897L,
9748440898L,40899L,40900L,40901L,40902L,40903L,40904L,40905L,40906L,40907L,
9748540908L,40909L,40910L,40911L,40912L,40913L,40914L,40915L,40916L,40917L,
9748640918L,40919L,40920L,40921L,40922L,40923L,40924L,40925L,40926L,40927L,
9748740928L,40929L,40930L,40931L,40932L,40933L,40934L,40935L,40936L,40937L,
9748840938L,40939L,40940L,40941L,40942L,40943L,40944L,40945L,40946L,40947L,
9748940948L,40949L,40950L,40951L,40952L,40953L,40954L,40955L,40956L,40957L,
9749040958L,40959L,40960L,40961L,40962L,40963L,40964L,40965L,40966L,40967L,
9749140968L,40969L,40970L,40971L,40972L,40973L,40974L,40975L,40976L,40977L,
9749240978L,40979L,40980L,40981L,40982L,40983L,40984L,40985L,40986L,40987L,
9749340988L,40989L,40990L,40991L,40992L,40993L,40994L,40995L,40996L,40997L,
9749440998L,40999L,41000L,41001L,41002L,41003L,41004L,41005L,41006L,41007L,
9749541008L,41009L,41010L,41011L,41012L,41013L,41014L,41015L,41016L,41017L,
9749641018L,41019L,41020L,41021L,41022L,41023L,41024L,41025L,41026L,41027L,
9749741028L,41029L,41030L,41031L,41032L,41033L,41034L,41035L,41036L,41037L,
9749841038L,41039L,41040L,41041L,41042L,41043L,41044L,41045L,41046L,41047L,
9749941048L,41049L,41050L,41051L,41052L,41053L,41054L,41055L,41056L,41057L,
9750041058L,41059L,41060L,41061L,41062L,41063L,41064L,41065L,41066L,41067L,
9750141068L,41069L,41070L,41071L,41072L,41073L,41074L,41075L,41076L,41077L,
9750241078L,41079L,41080L,41081L,41082L,41083L,41084L,41085L,41086L,41087L,
9750341088L,41089L,41090L,41091L,41092L,41093L,41094L,41095L,41096L,41097L,
9750441098L,41099L,41100L,41101L,41102L,41103L,41104L,41105L,41106L,41107L,
9750541108L,41109L,41110L,41111L,41112L,41113L,41114L,41115L,41116L,41117L,
9750641118L,41119L,41120L,41121L,41122L,41123L,41124L,41125L,41126L,41127L,
9750741128L,41129L,41130L,41131L,41132L,41133L,41134L,41135L,41136L,41137L,
9750841138L,41139L,41140L,41141L,41142L,41143L,41144L,41145L,41146L,41147L,
9750941148L,41149L,41150L,41151L,41152L,41153L,41154L,41155L,41156L,41157L,
9751041158L,41159L,41160L,41161L,41162L,41163L,41164L,41165L,41166L,41167L,
9751141168L,41169L,41170L,41171L,41172L,41173L,41174L,41175L,41176L,41177L,
9751241178L,41179L,41180L,41181L,41182L,41183L,41184L,41185L,41186L,41187L,
9751341188L,41189L,41190L,41191L,41192L,41193L,41194L,41195L,41196L,41197L,
9751441198L,41199L,41200L,41201L,41202L,41203L,41204L,41205L,41206L,41207L,
9751541208L,41209L,41210L,41211L,41212L,41213L,41214L,41215L,41216L,41217L,
9751641218L,41219L,41220L,41221L,41222L,41223L,41224L,41225L,41226L,41227L,
9751741228L,41229L,41230L,41231L,41232L,41233L,41234L,41235L,41236L,41237L,
9751841238L,41239L,41240L,41241L,41242L,41243L,41244L,41245L,41246L,41247L,
9751941248L,41249L,41250L,41251L,41252L,41253L,41254L,41255L,41256L,41257L,
9752041258L,41259L,41260L,41261L,41262L,41263L,41264L,41265L,41266L,41267L,
9752141268L,41269L,41270L,41271L,41272L,41273L,41274L,41275L,41276L,41277L,
9752241278L,41279L,41280L,41281L,41282L,41283L,41284L,41285L,41286L,41287L,
9752341288L,41289L,41290L,41291L,41292L,41293L,41294L,41295L,41296L,41297L,
9752441298L,41299L,41300L,41301L,41302L,41303L,41304L,41305L,41306L,41307L,
9752541308L,41309L,41310L,41311L,41312L,41313L,41314L,41315L,41316L,41317L,
9752641318L,41319L,41320L,41321L,41322L,41323L,41324L,41325L,41326L,41327L,
9752741328L,41329L,41330L,41331L,41332L,41333L,41334L,41335L,41336L,41337L,
9752841338L,41339L,41340L,41341L,41342L,41343L,41344L,41345L,41346L,41347L,
9752941348L,41349L,41350L,41351L,41352L,41353L,41354L,41355L,41356L,41357L,
9753041358L,41359L,41360L,41361L,41362L,41363L,41364L,41365L,41366L,41367L,
9753141368L,41369L,41370L,41371L,41372L,41373L,41374L,41375L,41376L,41377L,
9753241378L,41379L,41380L,41381L,41382L,41383L,41384L,41385L,41386L,41387L,
9753341388L,41389L,41390L,41391L,41392L,41393L,41394L,41395L,41396L,41397L,
9753441398L,41399L,41400L,41401L,41402L,41403L,41404L,41405L,41406L,41407L,
9753541408L,41409L,41410L,41411L,41412L,41413L,41414L,41415L,41416L,41417L,
9753641418L,41419L,41420L,41421L,41422L,41423L,41424L,41425L,41426L,41427L,
9753741428L,41429L,41430L,41431L,41432L,41433L,41434L,41435L,41436L,41437L,
9753841438L,41439L,41440L,41441L,41442L,41443L,41444L,41445L,41446L,41447L,
9753941448L,41449L,41450L,41451L,41452L,41453L,41454L,41455L,41456L,41457L,
9754041458L,41459L,41460L,41461L,41462L,41463L,41464L,41465L,41466L,41467L,
9754141468L,41469L,41470L,41471L,41472L,41473L,41474L,41475L,41476L,41477L,
9754241478L,41479L,41480L,41481L,41482L,41483L,41484L,41485L,41486L,41487L,
9754341488L,41489L,41490L,41491L,41492L,41493L,41494L,41495L,41496L,41497L,
9754441498L,41499L,41500L,41501L,41502L,41503L,41504L,41505L,41506L,41507L,
9754541508L,41509L,41510L,41511L,41512L,41513L,41514L,41515L,41516L,41517L,
9754641518L,41519L,41520L,41521L,41522L,41523L,41524L,41525L,41526L,41527L,
9754741528L,41529L,41530L,41531L,41532L,41533L,41534L,41535L,41536L,41537L,
9754841538L,41539L,41540L,41541L,41542L,41543L,41544L,41545L,41546L,41547L,
9754941548L,41549L,41550L,41551L,41552L,41553L,41554L,41555L,41556L,41557L,
9755041558L,41559L,41560L,41561L,41562L,41563L,41564L,41565L,41566L,41567L,
9755141568L,41569L,41570L,41571L,41572L,41573L,41574L,41575L,41576L,41577L,
9755241578L,41579L,41580L,41581L,41582L,41583L,41584L,41585L,41586L,41587L,
9755341588L,41589L,41590L,41591L,41592L,41593L,41594L,41595L,41596L,41597L,
9755441598L,41599L,41600L,41601L,41602L,41603L,41604L,41605L,41606L,41607L,
9755541608L,41609L,41610L,41611L,41612L,41613L,41614L,41615L,41616L,41617L,
9755641618L,41619L,41620L,41621L,41622L,41623L,41624L,41625L,41626L,41627L,
9755741628L,41629L,41630L,41631L,41632L,41633L,41634L,41635L,41636L,41637L,
9755841638L,41639L,41640L,41641L,41642L,41643L,41644L,41645L,41646L,41647L,
9755941648L,41649L,41650L,41651L,41652L,41653L,41654L,41655L,41656L,41657L,
9756041658L,41659L,41660L,41661L,41662L,41663L,41664L,41665L,41666L,41667L,
9756141668L,41669L,41670L,41671L,41672L,41673L,41674L,41675L,41676L,41677L,
9756241678L,41679L,41680L,41681L,41682L,41683L,41684L,41685L,41686L,41687L,
9756341688L,41689L,41690L,41691L,41692L,41693L,41694L,41695L,41696L,41697L,
9756441698L,41699L,41700L,41701L,41702L,41703L,41704L,41705L,41706L,41707L,
9756541708L,41709L,41710L,41711L,41712L,41713L,41714L,41715L,41716L,41717L,
9756641718L,41719L,41720L,41721L,41722L,41723L,41724L,41725L,41726L,41727L,
9756741728L,41729L,41730L,41731L,41732L,41733L,41734L,41735L,41736L,41737L,
9756841738L,41739L,41740L,41741L,41742L,41743L,41744L,41745L,41746L,41747L,
9756941748L,41749L,41750L,41751L,41752L,41753L,41754L,41755L,41756L,41757L,
9757041758L,41759L,41760L,41761L,41762L,41763L,41764L,41765L,41766L,41767L,
9757141768L,41769L,41770L,41771L,41772L,41773L,41774L,41775L,41776L,41777L,
9757241778L,41779L,41780L,41781L,41782L,41783L,41784L,41785L,41786L,41787L,
9757341788L,41789L,41790L,41791L,41792L,41793L,41794L,41795L,41796L,41797L,
9757441798L,41799L,41800L,41801L,41802L,41803L,41804L,41805L,41806L,41807L,
9757541808L,41809L,41810L,41811L,41812L,41813L,41814L,41815L,41816L,41817L,
9757641818L,41819L,41820L,41821L,41822L,41823L,41824L,41825L,41826L,41827L,
9757741828L,41829L,41830L,41831L,41832L,41833L,41834L,41835L,41836L,41837L,
9757841838L,41839L,41840L,41841L,41842L,41843L,41844L,41845L,41846L,41847L,
9757941848L,41849L,41850L,41851L,41852L,41853L,41854L,41855L,41856L,41857L,
9758041858L,41859L,41860L,41861L,41862L,41863L,41864L,41865L,41866L,41867L,
9758141868L,41869L,41870L,41871L,41872L,41873L,41874L,41875L,41876L,41877L,
9758241878L,41879L,41880L,41881L,41882L,41883L,41884L,41885L,41886L,41887L,
9758341888L,41889L,41890L,41891L,41892L,41893L,41894L,41895L,41896L,41897L,
9758441898L,41899L,41900L,41901L,41902L,41903L,41904L,41905L,41906L,41907L,
9758541908L,41909L,41910L,41911L,41912L,41913L,41914L,41915L,41916L,41917L,
9758641918L,41919L,41920L,41921L,41922L,41923L,41924L,41925L,41926L,41927L,
9758741928L,41929L,41930L,41931L,41932L,41933L,41934L,41935L,41936L,41937L,
9758841938L,41939L,41940L,41941L,41942L,41943L,41944L,41945L,41946L,41947L,
9758941948L,41949L,41950L,41951L,41952L,41953L,41954L,41955L,41956L,41957L,
9759041958L,41959L,41960L,41961L,41962L,41963L,41964L,41965L,41966L,41967L,
9759141968L,41969L,41970L,41971L,41972L,41973L,41974L,41975L,41976L,41977L,
9759241978L,41979L,41980L,41981L,41982L,41983L,41984L,41985L,41986L,41987L,
9759341988L,41989L,41990L,41991L,41992L,41993L,41994L,41995L,41996L,41997L,
9759441998L,41999L,42000L,42001L,42002L,42003L,42004L,42005L,42006L,42007L,
9759542008L,42009L,42010L,42011L,42012L,42013L,42014L,42015L,42016L,42017L,
9759642018L,42019L,42020L,42021L,42022L,42023L,42024L,42025L,42026L,42027L,
9759742028L,42029L,42030L,42031L,42032L,42033L,42034L,42035L,42036L,42037L,
9759842038L,42039L,42040L,42041L,42042L,42043L,42044L,42045L,42046L,42047L,
9759942048L,42049L,42050L,42051L,42052L,42053L,42054L,42055L,42056L,42057L,
9760042058L,42059L,42060L,42061L,42062L,42063L,42064L,42065L,42066L,42067L,
9760142068L,42069L,42070L,42071L,42072L,42073L,42074L,42075L,42076L,42077L,
9760242078L,42079L,42080L,42081L,42082L,42083L,42084L,42085L,42086L,42087L,
9760342088L,42089L,42090L,42091L,42092L,42093L,42094L,42095L,42096L,42097L,
9760442098L,42099L,42100L,42101L,42102L,42103L,42104L,42105L,42106L,42107L,
9760542108L,42109L,42110L,42111L,42112L,42113L,42114L,42115L,42116L,42117L,
9760642118L,42119L,42120L,42121L,42122L,42123L,42124L,42125L,42126L,42127L,
9760742128L,42129L,42130L,42131L,42132L,42133L,42134L,42135L,42136L,42137L,
9760842138L,42139L,42140L,42141L,42142L,42143L,42144L,42145L,42146L,42147L,
9760942148L,42149L,42150L,42151L,42152L,42153L,42154L,42155L,42156L,42157L,
9761042158L,42159L,42160L,42161L,42162L,42163L,42164L,42165L,42166L,42167L,
9761142168L,42169L,42170L,42171L,42172L,42173L,42174L,42175L,42176L,42177L,
9761242178L,42179L,42180L,42181L,42182L,42183L,42184L,42185L,42186L,42187L,
9761342188L,42189L,42190L,42191L,42192L,42193L,42194L,42195L,42196L,42197L,
9761442198L,42199L,42200L,42201L,42202L,42203L,42204L,42205L,42206L,42207L,
9761542208L,42209L,42210L,42211L,42212L,42213L,42214L,42215L,42216L,42217L,
9761642218L,42219L,42220L,42221L,42222L,42223L,42224L,42225L,42226L,42227L,
9761742228L,42229L,42230L,42231L,42232L,42233L,42234L,42235L,42236L,42237L,
9761842238L,42239L,42240L,42241L,42242L,42243L,42244L,42245L,42246L,42247L,
9761942248L,42249L,42250L,42251L,42252L,42253L,42254L,42255L,42256L,42257L,
9762042258L,42259L,42260L,42261L,42262L,42263L,42264L,42265L,42266L,42267L,
9762142268L,42269L,42270L,42271L,42272L,42273L,42274L,42275L,42276L,42277L,
9762242278L,42279L,42280L,42281L,42282L,42283L,42284L,42285L,42286L,42287L,
9762342288L,42289L,42290L,42291L,42292L,42293L,42294L,42295L,42296L,42297L,
9762442298L,42299L,42300L,42301L,42302L,42303L,42304L,42305L,42306L,42307L,
9762542308L,42309L,42310L,42311L,42312L,42313L,42314L,42315L,42316L,42317L,
9762642318L,42319L,42320L,42321L,42322L,42323L,42324L,42325L,42326L,42327L,
9762742328L,42329L,42330L,42331L,42332L,42333L,42334L,42335L,42336L,42337L,
9762842338L,42339L,42340L,42341L,42342L,42343L,42344L,42345L,42346L,42347L,
9762942348L,42349L,42350L,42351L,42352L,42353L,42354L,42355L,42356L,42357L,
9763042358L,42359L,42360L,42361L,42362L,42363L,42364L,42365L,42366L,42367L,
9763142368L,42369L,42370L,42371L,42372L,42373L,42374L,42375L,42376L,42377L,
9763242378L,42379L,42380L,42381L,42382L,42383L,42384L,42385L,42386L,42387L,
9763342388L,42389L,42390L,42391L,42392L,42393L,42394L,42395L,42396L,42397L,
9763442398L,42399L,42400L,42401L,42402L,42403L,42404L,42405L,42406L,42407L,
9763542408L,42409L,42410L,42411L,42412L,42413L,42414L,42415L,42416L,42417L,
9763642418L,42419L,42420L,42421L,42422L,42423L,42424L,42425L,42426L,42427L,
9763742428L,42429L,42430L,42431L,42432L,42433L,42434L,42435L,42436L,42437L,
9763842438L,42439L,42440L,42441L,42442L,42443L,42444L,42445L,42446L,42447L,
9763942448L,42449L,42450L,42451L,42452L,42453L,42454L,42455L,42456L,42457L,
9764042458L,42459L,42460L,42461L,42462L,42463L,42464L,42465L,42466L,42467L,
9764142468L,42469L,42470L,42471L,42472L,42473L,42474L,42475L,42476L,42477L,
9764242478L,42479L,42480L,42481L,42482L,42483L,42484L,42485L,42486L,42487L,
9764342488L,42489L,42490L,42491L,42492L,42493L,42494L,42495L,42496L,42497L,
9764442498L,42499L,42500L,42501L,42502L,42503L,42504L,42505L,42506L,42507L,
9764542508L,42509L,42510L,42511L,42512L,42513L,42514L,42515L,42516L,42517L,
9764642518L,42519L,42520L,42521L,42522L,42523L,42524L,42525L,42526L,42527L,
9764742528L,42529L,42530L,42531L,42532L,42533L,42534L,42535L,42536L,42537L,
9764842538L,42539L,42540L,42541L,42542L,42543L,42544L,42545L,42546L,42547L,
9764942548L,42549L,42550L,42551L,42552L,42553L,42554L,42555L,42556L,42557L,
9765042558L,42559L,42560L,42560L,42562L,42562L,42564L,42564L,42566L,42566L,
9765142568L,42568L,42570L,42570L,42572L,42572L,42574L,42574L,42576L,42576L,
9765242578L,42578L,42580L,42580L,42582L,42582L,42584L,42584L,42586L,42586L,
9765342588L,42588L,42590L,42590L,42592L,42592L,42594L,42594L,42596L,42596L,
9765442598L,42598L,42600L,42600L,42602L,42602L,42604L,42604L,42606L,42607L,
9765542608L,42609L,42610L,42611L,42612L,42613L,42614L,42615L,42616L,42617L,
9765642618L,42619L,42620L,42621L,42622L,42623L,42624L,42624L,42626L,42626L,
9765742628L,42628L,42630L,42630L,42632L,42632L,42634L,42634L,42636L,42636L,
9765842638L,42638L,42640L,42640L,42642L,42642L,42644L,42644L,42646L,42646L,
9765942648L,42648L,42650L,42650L,42652L,42653L,42654L,42655L,42656L,42657L,
9766042658L,42659L,42660L,42661L,42662L,42663L,42664L,42665L,42666L,42667L,
9766142668L,42669L,42670L,42671L,42672L,42673L,42674L,42675L,42676L,42677L,
9766242678L,42679L,42680L,42681L,42682L,42683L,42684L,42685L,42686L,42687L,
9766342688L,42689L,42690L,42691L,42692L,42693L,42694L,42695L,42696L,42697L,
9766442698L,42699L,42700L,42701L,42702L,42703L,42704L,42705L,42706L,42707L,
9766542708L,42709L,42710L,42711L,42712L,42713L,42714L,42715L,42716L,42717L,
9766642718L,42719L,42720L,42721L,42722L,42723L,42724L,42725L,42726L,42727L,
9766742728L,42729L,42730L,42731L,42732L,42733L,42734L,42735L,42736L,42737L,
9766842738L,42739L,42740L,42741L,42742L,42743L,42744L,42745L,42746L,42747L,
9766942748L,42749L,42750L,42751L,42752L,42753L,42754L,42755L,42756L,42757L,
9767042758L,42759L,42760L,42761L,42762L,42763L,42764L,42765L,42766L,42767L,
9767142768L,42769L,42770L,42771L,42772L,42773L,42774L,42775L,42776L,42777L,
9767242778L,42779L,42780L,42781L,42782L,42783L,42784L,42785L,42786L,42786L,
9767342788L,42788L,42790L,42790L,42792L,42792L,42794L,42794L,42796L,42796L,
9767442798L,42798L,42800L,42801L,42802L,42802L,42804L,42804L,42806L,42806L,
9767542808L,42808L,42810L,42810L,42812L,42812L,42814L,42814L,42816L,42816L,
9767642818L,42818L,42820L,42820L,42822L,42822L,42824L,42824L,42826L,42826L,
9767742828L,42828L,42830L,42830L,42832L,42832L,42834L,42834L,42836L,42836L,
9767842838L,42838L,42840L,42840L,42842L,42842L,42844L,42844L,42846L,42846L,
9767942848L,42848L,42850L,42850L,42852L,42852L,42854L,42854L,42856L,42856L,
9768042858L,42858L,42860L,42860L,42862L,42862L,42864L,42865L,42866L,42867L,
9768142868L,42869L,42870L,42871L,42872L,42873L,42873L,42875L,42875L,42877L,
9768242878L,42878L,42880L,42880L,42882L,42882L,42884L,42884L,42886L,42886L,
9768342888L,42889L,42890L,42891L,42891L,42893L,42894L,42895L,42896L,42896L,
9768442898L,42898L,42948L,42901L,42902L,42902L,42904L,42904L,42906L,42906L,
9768542908L,42908L,42910L,42910L,42912L,42912L,42914L,42914L,42916L,42916L,
9768642918L,42918L,42920L,42920L,42922L,42923L,42924L,42925L,42926L,42927L,
9768742928L,42929L,42930L,42931L,42932L,42932L,42934L,42934L,42936L,42936L,
9768842938L,42938L,42940L,42940L,42942L,42942L,42944L,42945L,42946L,42946L,
9768942948L,42949L,42950L,42951L,42952L,42953L,42954L,42955L,42956L,42957L,
9769042958L,42959L,42960L,42961L,42962L,42963L,42964L,42965L,42966L,42967L,
9769142968L,42969L,42970L,42971L,42972L,42973L,42974L,42975L,42976L,42977L,
9769242978L,42979L,42980L,42981L,42982L,42983L,42984L,42985L,42986L,42987L,
9769342988L,42989L,42990L,42991L,42992L,42993L,42994L,42995L,42996L,42997L,
9769442998L,42999L,43000L,43001L,43002L,43003L,43004L,43005L,43006L,43007L,
9769543008L,43009L,43010L,43011L,43012L,43013L,43014L,43015L,43016L,43017L,
9769643018L,43019L,43020L,43021L,43022L,43023L,43024L,43025L,43026L,43027L,
9769743028L,43029L,43030L,43031L,43032L,43033L,43034L,43035L,43036L,43037L,
9769843038L,43039L,43040L,43041L,43042L,43043L,43044L,43045L,43046L,43047L,
9769943048L,43049L,43050L,43051L,43052L,43053L,43054L,43055L,43056L,43057L,
9770043058L,43059L,43060L,43061L,43062L,43063L,43064L,43065L,43066L,43067L,
9770143068L,43069L,43070L,43071L,43072L,43073L,43074L,43075L,43076L,43077L,
9770243078L,43079L,43080L,43081L,43082L,43083L,43084L,43085L,43086L,43087L,
9770343088L,43089L,43090L,43091L,43092L,43093L,43094L,43095L,43096L,43097L,
9770443098L,43099L,43100L,43101L,43102L,43103L,43104L,43105L,43106L,43107L,
9770543108L,43109L,43110L,43111L,43112L,43113L,43114L,43115L,43116L,43117L,
9770643118L,43119L,43120L,43121L,43122L,43123L,43124L,43125L,43126L,43127L,
9770743128L,43129L,43130L,43131L,43132L,43133L,43134L,43135L,43136L,43137L,
9770843138L,43139L,43140L,43141L,43142L,43143L,43144L,43145L,43146L,43147L,
9770943148L,43149L,43150L,43151L,43152L,43153L,43154L,43155L,43156L,43157L,
9771043158L,43159L,43160L,43161L,43162L,43163L,43164L,43165L,43166L,43167L,
9771143168L,43169L,43170L,43171L,43172L,43173L,43174L,43175L,43176L,43177L,
9771243178L,43179L,43180L,43181L,43182L,43183L,43184L,43185L,43186L,43187L,
9771343188L,43189L,43190L,43191L,43192L,43193L,43194L,43195L,43196L,43197L,
9771443198L,43199L,43200L,43201L,43202L,43203L,43204L,43205L,43206L,43207L,
9771543208L,43209L,43210L,43211L,43212L,43213L,43214L,43215L,43216L,43217L,
9771643218L,43219L,43220L,43221L,43222L,43223L,43224L,43225L,43226L,43227L,
9771743228L,43229L,43230L,43231L,43232L,43233L,43234L,43235L,43236L,43237L,
9771843238L,43239L,43240L,43241L,43242L,43243L,43244L,43245L,43246L,43247L,
9771943248L,43249L,43250L,43251L,43252L,43253L,43254L,43255L,43256L,43257L,
9772043258L,43259L,43260L,43261L,43262L,43263L,43264L,43265L,43266L,43267L,
9772143268L,43269L,43270L,43271L,43272L,43273L,43274L,43275L,43276L,43277L,
9772243278L,43279L,43280L,43281L,43282L,43283L,43284L,43285L,43286L,43287L,
9772343288L,43289L,43290L,43291L,43292L,43293L,43294L,43295L,43296L,43297L,
9772443298L,43299L,43300L,43301L,43302L,43303L,43304L,43305L,43306L,43307L,
9772543308L,43309L,43310L,43311L,43312L,43313L,43314L,43315L,43316L,43317L,
9772643318L,43319L,43320L,43321L,43322L,43323L,43324L,43325L,43326L,43327L,
9772743328L,43329L,43330L,43331L,43332L,43333L,43334L,43335L,43336L,43337L,
9772843338L,43339L,43340L,43341L,43342L,43343L,43344L,43345L,43346L,43347L,
9772943348L,43349L,43350L,43351L,43352L,43353L,43354L,43355L,43356L,43357L,
9773043358L,43359L,43360L,43361L,43362L,43363L,43364L,43365L,43366L,43367L,
9773143368L,43369L,43370L,43371L,43372L,43373L,43374L,43375L,43376L,43377L,
9773243378L,43379L,43380L,43381L,43382L,43383L,43384L,43385L,43386L,43387L,
9773343388L,43389L,43390L,43391L,43392L,43393L,43394L,43395L,43396L,43397L,
9773443398L,43399L,43400L,43401L,43402L,43403L,43404L,43405L,43406L,43407L,
9773543408L,43409L,43410L,43411L,43412L,43413L,43414L,43415L,43416L,43417L,
9773643418L,43419L,43420L,43421L,43422L,43423L,43424L,43425L,43426L,43427L,
9773743428L,43429L,43430L,43431L,43432L,43433L,43434L,43435L,43436L,43437L,
9773843438L,43439L,43440L,43441L,43442L,43443L,43444L,43445L,43446L,43447L,
9773943448L,43449L,43450L,43451L,43452L,43453L,43454L,43455L,43456L,43457L,
9774043458L,43459L,43460L,43461L,43462L,43463L,43464L,43465L,43466L,43467L,
9774143468L,43469L,43470L,43471L,43472L,43473L,43474L,43475L,43476L,43477L,
9774243478L,43479L,43480L,43481L,43482L,43483L,43484L,43485L,43486L,43487L,
9774343488L,43489L,43490L,43491L,43492L,43493L,43494L,43495L,43496L,43497L,
9774443498L,43499L,43500L,43501L,43502L,43503L,43504L,43505L,43506L,43507L,
9774543508L,43509L,43510L,43511L,43512L,43513L,43514L,43515L,43516L,43517L,
9774643518L,43519L,43520L,43521L,43522L,43523L,43524L,43525L,43526L,43527L,
9774743528L,43529L,43530L,43531L,43532L,43533L,43534L,43535L,43536L,43537L,
9774843538L,43539L,43540L,43541L,43542L,43543L,43544L,43545L,43546L,43547L,
9774943548L,43549L,43550L,43551L,43552L,43553L,43554L,43555L,43556L,43557L,
9775043558L,43559L,43560L,43561L,43562L,43563L,43564L,43565L,43566L,43567L,
9775143568L,43569L,43570L,43571L,43572L,43573L,43574L,43575L,43576L,43577L,
9775243578L,43579L,43580L,43581L,43582L,43583L,43584L,43585L,43586L,43587L,
9775343588L,43589L,43590L,43591L,43592L,43593L,43594L,43595L,43596L,43597L,
9775443598L,43599L,43600L,43601L,43602L,43603L,43604L,43605L,43606L,43607L,
9775543608L,43609L,43610L,43611L,43612L,43613L,43614L,43615L,43616L,43617L,
9775643618L,43619L,43620L,43621L,43622L,43623L,43624L,43625L,43626L,43627L,
9775743628L,43629L,43630L,43631L,43632L,43633L,43634L,43635L,43636L,43637L,
9775843638L,43639L,43640L,43641L,43642L,43643L,43644L,43645L,43646L,43647L,
9775943648L,43649L,43650L,43651L,43652L,43653L,43654L,43655L,43656L,43657L,
9776043658L,43659L,43660L,43661L,43662L,43663L,43664L,43665L,43666L,43667L,
9776143668L,43669L,43670L,43671L,43672L,43673L,43674L,43675L,43676L,43677L,
9776243678L,43679L,43680L,43681L,43682L,43683L,43684L,43685L,43686L,43687L,
9776343688L,43689L,43690L,43691L,43692L,43693L,43694L,43695L,43696L,43697L,
9776443698L,43699L,43700L,43701L,43702L,43703L,43704L,43705L,43706L,43707L,
9776543708L,43709L,43710L,43711L,43712L,43713L,43714L,43715L,43716L,43717L,
9776643718L,43719L,43720L,43721L,43722L,43723L,43724L,43725L,43726L,43727L,
9776743728L,43729L,43730L,43731L,43732L,43733L,43734L,43735L,43736L,43737L,
9776843738L,43739L,43740L,43741L,43742L,43743L,43744L,43745L,43746L,43747L,
9776943748L,43749L,43750L,43751L,43752L,43753L,43754L,43755L,43756L,43757L,
9777043758L,43759L,43760L,43761L,43762L,43763L,43764L,43765L,43766L,43767L,
9777143768L,43769L,43770L,43771L,43772L,43773L,43774L,43775L,43776L,43777L,
9777243778L,43779L,43780L,43781L,43782L,43783L,43784L,43785L,43786L,43787L,
9777343788L,43789L,43790L,43791L,43792L,43793L,43794L,43795L,43796L,43797L,
9777443798L,43799L,43800L,43801L,43802L,43803L,43804L,43805L,43806L,43807L,
9777543808L,43809L,43810L,43811L,43812L,43813L,43814L,43815L,43816L,43817L,
9777643818L,43819L,43820L,43821L,43822L,43823L,43824L,43825L,43826L,43827L,
9777743828L,43829L,43830L,43831L,43832L,43833L,43834L,43835L,43836L,43837L,
9777843838L,43839L,43840L,43841L,43842L,43843L,43844L,43845L,43846L,43847L,
9777943848L,43849L,43850L,43851L,43852L,43853L,43854L,43855L,43856L,43857L,
9778043858L,42931L,43860L,43861L,43862L,43863L,43864L,43865L,43866L,43867L,
9778143868L,43869L,43870L,43871L,43872L,43873L,43874L,43875L,43876L,43877L,
9778243878L,43879L,43880L,43881L,43882L,43883L,43884L,43885L,43886L,43887L,5024,
977835025,5026,5027,5028,5029,5030,5031,5032,5033,5034,5035,5036,5037,5038,5039,
977845040,5041,5042,5043,5044,5045,5046,5047,5048,5049,5050,5051,5052,5053,5054,
977855055,5056,5057,5058,5059,5060,5061,5062,5063,5064,5065,5066,5067,5068,5069,
977865070,5071,5072,5073,5074,5075,5076,5077,5078,5079,5080,5081,5082,5083,5084,
977875085,5086,5087,5088,5089,5090,5091,5092,5093,5094,5095,5096,5097,5098,5099,
977885100,5101,5102,5103,43968L,43969L,43970L,43971L,43972L,43973L,43974L,
9778943975L,43976L,43977L,43978L,43979L,43980L,43981L,43982L,43983L,43984L,
9779043985L,43986L,43987L,43988L,43989L,43990L,43991L,43992L,43993L,43994L,
9779143995L,43996L,43997L,43998L,43999L,44000L,44001L,44002L,44003L,44004L,
9779244005L,44006L,44007L,44008L,44009L,44010L,44011L,44012L,44013L,44014L,
9779344015L,44016L,44017L,44018L,44019L,44020L,44021L,44022L,44023L,44024L,
9779444025L,44026L,44027L,44028L,44029L,44030L,44031L,44032L,44033L,44034L,
9779544035L,44036L,44037L,44038L,44039L,44040L,44041L,44042L,44043L,44044L,
9779644045L,44046L,44047L,44048L,44049L,44050L,44051L,44052L,44053L,44054L,
9779744055L,44056L,44057L,44058L,44059L,44060L,44061L,44062L,44063L,44064L,
9779844065L,44066L,44067L,44068L,44069L,44070L,44071L,44072L,44073L,44074L,
9779944075L,44076L,44077L,44078L,44079L,44080L,44081L,44082L,44083L,44084L,
9780044085L,44086L,44087L,44088L,44089L,44090L,44091L,44092L,44093L,44094L,
9780144095L,44096L,44097L,44098L,44099L,44100L,44101L,44102L,44103L,44104L,
9780244105L,44106L,44107L,44108L,44109L,44110L,44111L,44112L,44113L,44114L,
9780344115L,44116L,44117L,44118L,44119L,44120L,44121L,44122L,44123L,44124L,
9780444125L,44126L,44127L,44128L,44129L,44130L,44131L,44132L,44133L,44134L,
9780544135L,44136L,44137L,44138L,44139L,44140L,44141L,44142L,44143L,44144L,
9780644145L,44146L,44147L,44148L,44149L,44150L,44151L,44152L,44153L,44154L,
9780744155L,44156L,44157L,44158L,44159L,44160L,44161L,44162L,44163L,44164L,
9780844165L,44166L,44167L,44168L,44169L,44170L,44171L,44172L,44173L,44174L,
9780944175L,44176L,44177L,44178L,44179L,44180L,44181L,44182L,44183L,44184L,
9781044185L,44186L,44187L,44188L,44189L,44190L,44191L,44192L,44193L,44194L,
9781144195L,44196L,44197L,44198L,44199L,44200L,44201L,44202L,44203L,44204L,
9781244205L,44206L,44207L,44208L,44209L,44210L,44211L,44212L,44213L,44214L,
9781344215L,44216L,44217L,44218L,44219L,44220L,44221L,44222L,44223L,44224L,
9781444225L,44226L,44227L,44228L,44229L,44230L,44231L,44232L,44233L,44234L,
9781544235L,44236L,44237L,44238L,44239L,44240L,44241L,44242L,44243L,44244L,
9781644245L,44246L,44247L,44248L,44249L,44250L,44251L,44252L,44253L,44254L,
9781744255L,44256L,44257L,44258L,44259L,44260L,44261L,44262L,44263L,44264L,
9781844265L,44266L,44267L,44268L,44269L,44270L,44271L,44272L,44273L,44274L,
9781944275L,44276L,44277L,44278L,44279L,44280L,44281L,44282L,44283L,44284L,
9782044285L,44286L,44287L,44288L,44289L,44290L,44291L,44292L,44293L,44294L,
9782144295L,44296L,44297L,44298L,44299L,44300L,44301L,44302L,44303L,44304L,
9782244305L,44306L,44307L,44308L,44309L,44310L,44311L,44312L,44313L,44314L,
9782344315L,44316L,44317L,44318L,44319L,44320L,44321L,44322L,44323L,44324L,
9782444325L,44326L,44327L,44328L,44329L,44330L,44331L,44332L,44333L,44334L,
9782544335L,44336L,44337L,44338L,44339L,44340L,44341L,44342L,44343L,44344L,
9782644345L,44346L,44347L,44348L,44349L,44350L,44351L,44352L,44353L,44354L,
9782744355L,44356L,44357L,44358L,44359L,44360L,44361L,44362L,44363L,44364L,
9782844365L,44366L,44367L,44368L,44369L,44370L,44371L,44372L,44373L,44374L,
9782944375L,44376L,44377L,44378L,44379L,44380L,44381L,44382L,44383L,44384L,
9783044385L,44386L,44387L,44388L,44389L,44390L,44391L,44392L,44393L,44394L,
9783144395L,44396L,44397L,44398L,44399L,44400L,44401L,44402L,44403L,44404L,
9783244405L,44406L,44407L,44408L,44409L,44410L,44411L,44412L,44413L,44414L,
9783344415L,44416L,44417L,44418L,44419L,44420L,44421L,44422L,44423L,44424L,
9783444425L,44426L,44427L,44428L,44429L,44430L,44431L,44432L,44433L,44434L,
9783544435L,44436L,44437L,44438L,44439L,44440L,44441L,44442L,44443L,44444L,
9783644445L,44446L,44447L,44448L,44449L,44450L,44451L,44452L,44453L,44454L,
9783744455L,44456L,44457L,44458L,44459L,44460L,44461L,44462L,44463L,44464L,
9783844465L,44466L,44467L,44468L,44469L,44470L,44471L,44472L,44473L,44474L,
9783944475L,44476L,44477L,44478L,44479L,44480L,44481L,44482L,44483L,44484L,
9784044485L,44486L,44487L,44488L,44489L,44490L,44491L,44492L,44493L,44494L,
9784144495L,44496L,44497L,44498L,44499L,44500L,44501L,44502L,44503L,44504L,
9784244505L,44506L,44507L,44508L,44509L,44510L,44511L,44512L,44513L,44514L,
9784344515L,44516L,44517L,44518L,44519L,44520L,44521L,44522L,44523L,44524L,
9784444525L,44526L,44527L,44528L,44529L,44530L,44531L,44532L,44533L,44534L,
9784544535L,44536L,44537L,44538L,44539L,44540L,44541L,44542L,44543L,44544L,
9784644545L,44546L,44547L,44548L,44549L,44550L,44551L,44552L,44553L,44554L,
9784744555L,44556L,44557L,44558L,44559L,44560L,44561L,44562L,44563L,44564L,
9784844565L,44566L,44567L,44568L,44569L,44570L,44571L,44572L,44573L,44574L,
9784944575L,44576L,44577L,44578L,44579L,44580L,44581L,44582L,44583L,44584L,
9785044585L,44586L,44587L,44588L,44589L,44590L,44591L,44592L,44593L,44594L,
9785144595L,44596L,44597L,44598L,44599L,44600L,44601L,44602L,44603L,44604L,
9785244605L,44606L,44607L,44608L,44609L,44610L,44611L,44612L,44613L,44614L,
9785344615L,44616L,44617L,44618L,44619L,44620L,44621L,44622L,44623L,44624L,
9785444625L,44626L,44627L,44628L,44629L,44630L,44631L,44632L,44633L,44634L,
9785544635L,44636L,44637L,44638L,44639L,44640L,44641L,44642L,44643L,44644L,
9785644645L,44646L,44647L,44648L,44649L,44650L,44651L,44652L,44653L,44654L,
9785744655L,44656L,44657L,44658L,44659L,44660L,44661L,44662L,44663L,44664L,
9785844665L,44666L,44667L,44668L,44669L,44670L,44671L,44672L,44673L,44674L,
9785944675L,44676L,44677L,44678L,44679L,44680L,44681L,44682L,44683L,44684L,
9786044685L,44686L,44687L,44688L,44689L,44690L,44691L,44692L,44693L,44694L,
9786144695L,44696L,44697L,44698L,44699L,44700L,44701L,44702L,44703L,44704L,
9786244705L,44706L,44707L,44708L,44709L,44710L,44711L,44712L,44713L,44714L,
9786344715L,44716L,44717L,44718L,44719L,44720L,44721L,44722L,44723L,44724L,
9786444725L,44726L,44727L,44728L,44729L,44730L,44731L,44732L,44733L,44734L,
9786544735L,44736L,44737L,44738L,44739L,44740L,44741L,44742L,44743L,44744L,
9786644745L,44746L,44747L,44748L,44749L,44750L,44751L,44752L,44753L,44754L,
9786744755L,44756L,44757L,44758L,44759L,44760L,44761L,44762L,44763L,44764L,
9786844765L,44766L,44767L,44768L,44769L,44770L,44771L,44772L,44773L,44774L,
9786944775L,44776L,44777L,44778L,44779L,44780L,44781L,44782L,44783L,44784L,
9787044785L,44786L,44787L,44788L,44789L,44790L,44791L,44792L,44793L,44794L,
9787144795L,44796L,44797L,44798L,44799L,44800L,44801L,44802L,44803L,44804L,
9787244805L,44806L,44807L,44808L,44809L,44810L,44811L,44812L,44813L,44814L,
9787344815L,44816L,44817L,44818L,44819L,44820L,44821L,44822L,44823L,44824L,
9787444825L,44826L,44827L,44828L,44829L,44830L,44831L,44832L,44833L,44834L,
9787544835L,44836L,44837L,44838L,44839L,44840L,44841L,44842L,44843L,44844L,
9787644845L,44846L,44847L,44848L,44849L,44850L,44851L,44852L,44853L,44854L,
9787744855L,44856L,44857L,44858L,44859L,44860L,44861L,44862L,44863L,44864L,
9787844865L,44866L,44867L,44868L,44869L,44870L,44871L,44872L,44873L,44874L,
9787944875L,44876L,44877L,44878L,44879L,44880L,44881L,44882L,44883L,44884L,
9788044885L,44886L,44887L,44888L,44889L,44890L,44891L,44892L,44893L,44894L,
9788144895L,44896L,44897L,44898L,44899L,44900L,44901L,44902L,44903L,44904L,
9788244905L,44906L,44907L,44908L,44909L,44910L,44911L,44912L,44913L,44914L,
9788344915L,44916L,44917L,44918L,44919L,44920L,44921L,44922L,44923L,44924L,
9788444925L,44926L,44927L,44928L,44929L,44930L,44931L,44932L,44933L,44934L,
9788544935L,44936L,44937L,44938L,44939L,44940L,44941L,44942L,44943L,44944L,
9788644945L,44946L,44947L,44948L,44949L,44950L,44951L,44952L,44953L,44954L,
9788744955L,44956L,44957L,44958L,44959L,44960L,44961L,44962L,44963L,44964L,
9788844965L,44966L,44967L,44968L,44969L,44970L,44971L,44972L,44973L,44974L,
9788944975L,44976L,44977L,44978L,44979L,44980L,44981L,44982L,44983L,44984L,
9789044985L,44986L,44987L,44988L,44989L,44990L,44991L,44992L,44993L,44994L,
9789144995L,44996L,44997L,44998L,44999L,45000L,45001L,45002L,45003L,45004L,
9789245005L,45006L,45007L,45008L,45009L,45010L,45011L,45012L,45013L,45014L,
9789345015L,45016L,45017L,45018L,45019L,45020L,45021L,45022L,45023L,45024L,
9789445025L,45026L,45027L,45028L,45029L,45030L,45031L,45032L,45033L,45034L,
9789545035L,45036L,45037L,45038L,45039L,45040L,45041L,45042L,45043L,45044L,
9789645045L,45046L,45047L,45048L,45049L,45050L,45051L,45052L,45053L,45054L,
9789745055L,45056L,45057L,45058L,45059L,45060L,45061L,45062L,45063L,45064L,
9789845065L,45066L,45067L,45068L,45069L,45070L,45071L,45072L,45073L,45074L,
9789945075L,45076L,45077L,45078L,45079L,45080L,45081L,45082L,45083L,45084L,
9790045085L,45086L,45087L,45088L,45089L,45090L,45091L,45092L,45093L,45094L,
9790145095L,45096L,45097L,45098L,45099L,45100L,45101L,45102L,45103L,45104L,
9790245105L,45106L,45107L,45108L,45109L,45110L,45111L,45112L,45113L,45114L,
9790345115L,45116L,45117L,45118L,45119L,45120L,45121L,45122L,45123L,45124L,
9790445125L,45126L,45127L,45128L,45129L,45130L,45131L,45132L,45133L,45134L,
9790545135L,45136L,45137L,45138L,45139L,45140L,45141L,45142L,45143L,45144L,
9790645145L,45146L,45147L,45148L,45149L,45150L,45151L,45152L,45153L,45154L,
9790745155L,45156L,45157L,45158L,45159L,45160L,45161L,45162L,45163L,45164L,
9790845165L,45166L,45167L,45168L,45169L,45170L,45171L,45172L,45173L,45174L,
9790945175L,45176L,45177L,45178L,45179L,45180L,45181L,45182L,45183L,45184L,
9791045185L,45186L,45187L,45188L,45189L,45190L,45191L,45192L,45193L,45194L,
9791145195L,45196L,45197L,45198L,45199L,45200L,45201L,45202L,45203L,45204L,
9791245205L,45206L,45207L,45208L,45209L,45210L,45211L,45212L,45213L,45214L,
9791345215L,45216L,45217L,45218L,45219L,45220L,45221L,45222L,45223L,45224L,
9791445225L,45226L,45227L,45228L,45229L,45230L,45231L,45232L,45233L,45234L,
9791545235L,45236L,45237L,45238L,45239L,45240L,45241L,45242L,45243L,45244L,
9791645245L,45246L,45247L,45248L,45249L,45250L,45251L,45252L,45253L,45254L,
9791745255L,45256L,45257L,45258L,45259L,45260L,45261L,45262L,45263L,45264L,
9791845265L,45266L,45267L,45268L,45269L,45270L,45271L,45272L,45273L,45274L,
9791945275L,45276L,45277L,45278L,45279L,45280L,45281L,45282L,45283L,45284L,
9792045285L,45286L,45287L,45288L,45289L,45290L,45291L,45292L,45293L,45294L,
9792145295L,45296L,45297L,45298L,45299L,45300L,45301L,45302L,45303L,45304L,
9792245305L,45306L,45307L,45308L,45309L,45310L,45311L,45312L,45313L,45314L,
9792345315L,45316L,45317L,45318L,45319L,45320L,45321L,45322L,45323L,45324L,
9792445325L,45326L,45327L,45328L,45329L,45330L,45331L,45332L,45333L,45334L,
9792545335L,45336L,45337L,45338L,45339L,45340L,45341L,45342L,45343L,45344L,
9792645345L,45346L,45347L,45348L,45349L,45350L,45351L,45352L,45353L,45354L,
9792745355L,45356L,45357L,45358L,45359L,45360L,45361L,45362L,45363L,45364L,
9792845365L,45366L,45367L,45368L,45369L,45370L,45371L,45372L,45373L,45374L,
9792945375L,45376L,45377L,45378L,45379L,45380L,45381L,45382L,45383L,45384L,
9793045385L,45386L,45387L,45388L,45389L,45390L,45391L,45392L,45393L,45394L,
9793145395L,45396L,45397L,45398L,45399L,45400L,45401L,45402L,45403L,45404L,
9793245405L,45406L,45407L,45408L,45409L,45410L,45411L,45412L,45413L,45414L,
9793345415L,45416L,45417L,45418L,45419L,45420L,45421L,45422L,45423L,45424L,
9793445425L,45426L,45427L,45428L,45429L,45430L,45431L,45432L,45433L,45434L,
9793545435L,45436L,45437L,45438L,45439L,45440L,45441L,45442L,45443L,45444L,
9793645445L,45446L,45447L,45448L,45449L,45450L,45451L,45452L,45453L,45454L,
9793745455L,45456L,45457L,45458L,45459L,45460L,45461L,45462L,45463L,45464L,
9793845465L,45466L,45467L,45468L,45469L,45470L,45471L,45472L,45473L,45474L,
9793945475L,45476L,45477L,45478L,45479L,45480L,45481L,45482L,45483L,45484L,
9794045485L,45486L,45487L,45488L,45489L,45490L,45491L,45492L,45493L,45494L,
9794145495L,45496L,45497L,45498L,45499L,45500L,45501L,45502L,45503L,45504L,
9794245505L,45506L,45507L,45508L,45509L,45510L,45511L,45512L,45513L,45514L,
9794345515L,45516L,45517L,45518L,45519L,45520L,45521L,45522L,45523L,45524L,
9794445525L,45526L,45527L,45528L,45529L,45530L,45531L,45532L,45533L,45534L,
9794545535L,45536L,45537L,45538L,45539L,45540L,45541L,45542L,45543L,45544L,
9794645545L,45546L,45547L,45548L,45549L,45550L,45551L,45552L,45553L,45554L,
9794745555L,45556L,45557L,45558L,45559L,45560L,45561L,45562L,45563L,45564L,
9794845565L,45566L,45567L,45568L,45569L,45570L,45571L,45572L,45573L,45574L,
9794945575L,45576L,45577L,45578L,45579L,45580L,45581L,45582L,45583L,45584L,
9795045585L,45586L,45587L,45588L,45589L,45590L,45591L,45592L,45593L,45594L,
9795145595L,45596L,45597L,45598L,45599L,45600L,45601L,45602L,45603L,45604L,
9795245605L,45606L,45607L,45608L,45609L,45610L,45611L,45612L,45613L,45614L,
9795345615L,45616L,45617L,45618L,45619L,45620L,45621L,45622L,45623L,45624L,
9795445625L,45626L,45627L,45628L,45629L,45630L,45631L,45632L,45633L,45634L,
9795545635L,45636L,45637L,45638L,45639L,45640L,45641L,45642L,45643L,45644L,
9795645645L,45646L,45647L,45648L,45649L,45650L,45651L,45652L,45653L,45654L,
9795745655L,45656L,45657L,45658L,45659L,45660L,45661L,45662L,45663L,45664L,
9795845665L,45666L,45667L,45668L,45669L,45670L,45671L,45672L,45673L,45674L,
9795945675L,45676L,45677L,45678L,45679L,45680L,45681L,45682L,45683L,45684L,
9796045685L,45686L,45687L,45688L,45689L,45690L,45691L,45692L,45693L,45694L,
9796145695L,45696L,45697L,45698L,45699L,45700L,45701L,45702L,45703L,45704L,
9796245705L,45706L,45707L,45708L,45709L,45710L,45711L,45712L,45713L,45714L,
9796345715L,45716L,45717L,45718L,45719L,45720L,45721L,45722L,45723L,45724L,
9796445725L,45726L,45727L,45728L,45729L,45730L,45731L,45732L,45733L,45734L,
9796545735L,45736L,45737L,45738L,45739L,45740L,45741L,45742L,45743L,45744L,
9796645745L,45746L,45747L,45748L,45749L,45750L,45751L,45752L,45753L,45754L,
9796745755L,45756L,45757L,45758L,45759L,45760L,45761L,45762L,45763L,45764L,
9796845765L,45766L,45767L,45768L,45769L,45770L,45771L,45772L,45773L,45774L,
9796945775L,45776L,45777L,45778L,45779L,45780L,45781L,45782L,45783L,45784L,
9797045785L,45786L,45787L,45788L,45789L,45790L,45791L,45792L,45793L,45794L,
9797145795L,45796L,45797L,45798L,45799L,45800L,45801L,45802L,45803L,45804L,
9797245805L,45806L,45807L,45808L,45809L,45810L,45811L,45812L,45813L,45814L,
9797345815L,45816L,45817L,45818L,45819L,45820L,45821L,45822L,45823L,45824L,
9797445825L,45826L,45827L,45828L,45829L,45830L,45831L,45832L,45833L,45834L,
9797545835L,45836L,45837L,45838L,45839L,45840L,45841L,45842L,45843L,45844L,
9797645845L,45846L,45847L,45848L,45849L,45850L,45851L,45852L,45853L,45854L,
9797745855L,45856L,45857L,45858L,45859L,45860L,45861L,45862L,45863L,45864L,
9797845865L,45866L,45867L,45868L,45869L,45870L,45871L,45872L,45873L,45874L,
9797945875L,45876L,45877L,45878L,45879L,45880L,45881L,45882L,45883L,45884L,
9798045885L,45886L,45887L,45888L,45889L,45890L,45891L,45892L,45893L,45894L,
9798145895L,45896L,45897L,45898L,45899L,45900L,45901L,45902L,45903L,45904L,
9798245905L,45906L,45907L,45908L,45909L,45910L,45911L,45912L,45913L,45914L,
9798345915L,45916L,45917L,45918L,45919L,45920L,45921L,45922L,45923L,45924L,
9798445925L,45926L,45927L,45928L,45929L,45930L,45931L,45932L,45933L,45934L,
9798545935L,45936L,45937L,45938L,45939L,45940L,45941L,45942L,45943L,45944L,
9798645945L,45946L,45947L,45948L,45949L,45950L,45951L,45952L,45953L,45954L,
9798745955L,45956L,45957L,45958L,45959L,45960L,45961L,45962L,45963L,45964L,
9798845965L,45966L,45967L,45968L,45969L,45970L,45971L,45972L,45973L,45974L,
9798945975L,45976L,45977L,45978L,45979L,45980L,45981L,45982L,45983L,45984L,
9799045985L,45986L,45987L,45988L,45989L,45990L,45991L,45992L,45993L,45994L,
9799145995L,45996L,45997L,45998L,45999L,46000L,46001L,46002L,46003L,46004L,
9799246005L,46006L,46007L,46008L,46009L,46010L,46011L,46012L,46013L,46014L,
9799346015L,46016L,46017L,46018L,46019L,46020L,46021L,46022L,46023L,46024L,
9799446025L,46026L,46027L,46028L,46029L,46030L,46031L,46032L,46033L,46034L,
9799546035L,46036L,46037L,46038L,46039L,46040L,46041L,46042L,46043L,46044L,
9799646045L,46046L,46047L,46048L,46049L,46050L,46051L,46052L,46053L,46054L,
9799746055L,46056L,46057L,46058L,46059L,46060L,46061L,46062L,46063L,46064L,
9799846065L,46066L,46067L,46068L,46069L,46070L,46071L,46072L,46073L,46074L,
9799946075L,46076L,46077L,46078L,46079L,46080L,46081L,46082L,46083L,46084L,
9800046085L,46086L,46087L,46088L,46089L,46090L,46091L,46092L,46093L,46094L,
9800146095L,46096L,46097L,46098L,46099L,46100L,46101L,46102L,46103L,46104L,
9800246105L,46106L,46107L,46108L,46109L,46110L,46111L,46112L,46113L,46114L,
9800346115L,46116L,46117L,46118L,46119L,46120L,46121L,46122L,46123L,46124L,
9800446125L,46126L,46127L,46128L,46129L,46130L,46131L,46132L,46133L,46134L,
9800546135L,46136L,46137L,46138L,46139L,46140L,46141L,46142L,46143L,46144L,
9800646145L,46146L,46147L,46148L,46149L,46150L,46151L,46152L,46153L,46154L,
9800746155L,46156L,46157L,46158L,46159L,46160L,46161L,46162L,46163L,46164L,
9800846165L,46166L,46167L,46168L,46169L,46170L,46171L,46172L,46173L,46174L,
9800946175L,46176L,46177L,46178L,46179L,46180L,46181L,46182L,46183L,46184L,
9801046185L,46186L,46187L,46188L,46189L,46190L,46191L,46192L,46193L,46194L,
9801146195L,46196L,46197L,46198L,46199L,46200L,46201L,46202L,46203L,46204L,
9801246205L,46206L,46207L,46208L,46209L,46210L,46211L,46212L,46213L,46214L,
9801346215L,46216L,46217L,46218L,46219L,46220L,46221L,46222L,46223L,46224L,
9801446225L,46226L,46227L,46228L,46229L,46230L,46231L,46232L,46233L,46234L,
9801546235L,46236L,46237L,46238L,46239L,46240L,46241L,46242L,46243L,46244L,
9801646245L,46246L,46247L,46248L,46249L,46250L,46251L,46252L,46253L,46254L,
9801746255L,46256L,46257L,46258L,46259L,46260L,46261L,46262L,46263L,46264L,
9801846265L,46266L,46267L,46268L,46269L,46270L,46271L,46272L,46273L,46274L,
9801946275L,46276L,46277L,46278L,46279L,46280L,46281L,46282L,46283L,46284L,
9802046285L,46286L,46287L,46288L,46289L,46290L,46291L,46292L,46293L,46294L,
9802146295L,46296L,46297L,46298L,46299L,46300L,46301L,46302L,46303L,46304L,
9802246305L,46306L,46307L,46308L,46309L,46310L,46311L,46312L,46313L,46314L,
9802346315L,46316L,46317L,46318L,46319L,46320L,46321L,46322L,46323L,46324L,
9802446325L,46326L,46327L,46328L,46329L,46330L,46331L,46332L,46333L,46334L,
9802546335L,46336L,46337L,46338L,46339L,46340L,46341L,46342L,46343L,46344L,
9802646345L,46346L,46347L,46348L,46349L,46350L,46351L,46352L,46353L,46354L,
9802746355L,46356L,46357L,46358L,46359L,46360L,46361L,46362L,46363L,46364L,
9802846365L,46366L,46367L,46368L,46369L,46370L,46371L,46372L,46373L,46374L,
9802946375L,46376L,46377L,46378L,46379L,46380L,46381L,46382L,46383L,46384L,
9803046385L,46386L,46387L,46388L,46389L,46390L,46391L,46392L,46393L,46394L,
9803146395L,46396L,46397L,46398L,46399L,46400L,46401L,46402L,46403L,46404L,
9803246405L,46406L,46407L,46408L,46409L,46410L,46411L,46412L,46413L,46414L,
9803346415L,46416L,46417L,46418L,46419L,46420L,46421L,46422L,46423L,46424L,
9803446425L,46426L,46427L,46428L,46429L,46430L,46431L,46432L,46433L,46434L,
9803546435L,46436L,46437L,46438L,46439L,46440L,46441L,46442L,46443L,46444L,
9803646445L,46446L,46447L,46448L,46449L,46450L,46451L,46452L,46453L,46454L,
9803746455L,46456L,46457L,46458L,46459L,46460L,46461L,46462L,46463L,46464L,
9803846465L,46466L,46467L,46468L,46469L,46470L,46471L,46472L,46473L,46474L,
9803946475L,46476L,46477L,46478L,46479L,46480L,46481L,46482L,46483L,46484L,
9804046485L,46486L,46487L,46488L,46489L,46490L,46491L,46492L,46493L,46494L,
9804146495L,46496L,46497L,46498L,46499L,46500L,46501L,46502L,46503L,46504L,
9804246505L,46506L,46507L,46508L,46509L,46510L,46511L,46512L,46513L,46514L,
9804346515L,46516L,46517L,46518L,46519L,46520L,46521L,46522L,46523L,46524L,
9804446525L,46526L,46527L,46528L,46529L,46530L,46531L,46532L,46533L,46534L,
9804546535L,46536L,46537L,46538L,46539L,46540L,46541L,46542L,46543L,46544L,
9804646545L,46546L,46547L,46548L,46549L,46550L,46551L,46552L,46553L,46554L,
9804746555L,46556L,46557L,46558L,46559L,46560L,46561L,46562L,46563L,46564L,
9804846565L,46566L,46567L,46568L,46569L,46570L,46571L,46572L,46573L,46574L,
9804946575L,46576L,46577L,46578L,46579L,46580L,46581L,46582L,46583L,46584L,
9805046585L,46586L,46587L,46588L,46589L,46590L,46591L,46592L,46593L,46594L,
9805146595L,46596L,46597L,46598L,46599L,46600L,46601L,46602L,46603L,46604L,
9805246605L,46606L,46607L,46608L,46609L,46610L,46611L,46612L,46613L,46614L,
9805346615L,46616L,46617L,46618L,46619L,46620L,46621L,46622L,46623L,46624L,
9805446625L,46626L,46627L,46628L,46629L,46630L,46631L,46632L,46633L,46634L,
9805546635L,46636L,46637L,46638L,46639L,46640L,46641L,46642L,46643L,46644L,
9805646645L,46646L,46647L,46648L,46649L,46650L,46651L,46652L,46653L,46654L,
9805746655L,46656L,46657L,46658L,46659L,46660L,46661L,46662L,46663L,46664L,
9805846665L,46666L,46667L,46668L,46669L,46670L,46671L,46672L,46673L,46674L,
9805946675L,46676L,46677L,46678L,46679L,46680L,46681L,46682L,46683L,46684L,
9806046685L,46686L,46687L,46688L,46689L,46690L,46691L,46692L,46693L,46694L,
9806146695L,46696L,46697L,46698L,46699L,46700L,46701L,46702L,46703L,46704L,
9806246705L,46706L,46707L,46708L,46709L,46710L,46711L,46712L,46713L,46714L,
9806346715L,46716L,46717L,46718L,46719L,46720L,46721L,46722L,46723L,46724L,
9806446725L,46726L,46727L,46728L,46729L,46730L,46731L,46732L,46733L,46734L,
9806546735L,46736L,46737L,46738L,46739L,46740L,46741L,46742L,46743L,46744L,
9806646745L,46746L,46747L,46748L,46749L,46750L,46751L,46752L,46753L,46754L,
9806746755L,46756L,46757L,46758L,46759L,46760L,46761L,46762L,46763L,46764L,
9806846765L,46766L,46767L,46768L,46769L,46770L,46771L,46772L,46773L,46774L,
9806946775L,46776L,46777L,46778L,46779L,46780L,46781L,46782L,46783L,46784L,
9807046785L,46786L,46787L,46788L,46789L,46790L,46791L,46792L,46793L,46794L,
9807146795L,46796L,46797L,46798L,46799L,46800L,46801L,46802L,46803L,46804L,
9807246805L,46806L,46807L,46808L,46809L,46810L,46811L,46812L,46813L,46814L,
9807346815L,46816L,46817L,46818L,46819L,46820L,46821L,46822L,46823L,46824L,
9807446825L,46826L,46827L,46828L,46829L,46830L,46831L,46832L,46833L,46834L,
9807546835L,46836L,46837L,46838L,46839L,46840L,46841L,46842L,46843L,46844L,
9807646845L,46846L,46847L,46848L,46849L,46850L,46851L,46852L,46853L,46854L,
9807746855L,46856L,46857L,46858L,46859L,46860L,46861L,46862L,46863L,46864L,
9807846865L,46866L,46867L,46868L,46869L,46870L,46871L,46872L,46873L,46874L,
9807946875L,46876L,46877L,46878L,46879L,46880L,46881L,46882L,46883L,46884L,
9808046885L,46886L,46887L,46888L,46889L,46890L,46891L,46892L,46893L,46894L,
9808146895L,46896L,46897L,46898L,46899L,46900L,46901L,46902L,46903L,46904L,
9808246905L,46906L,46907L,46908L,46909L,46910L,46911L,46912L,46913L,46914L,
9808346915L,46916L,46917L,46918L,46919L,46920L,46921L,46922L,46923L,46924L,
9808446925L,46926L,46927L,46928L,46929L,46930L,46931L,46932L,46933L,46934L,
9808546935L,46936L,46937L,46938L,46939L,46940L,46941L,46942L,46943L,46944L,
9808646945L,46946L,46947L,46948L,46949L,46950L,46951L,46952L,46953L,46954L,
9808746955L,46956L,46957L,46958L,46959L,46960L,46961L,46962L,46963L,46964L,
9808846965L,46966L,46967L,46968L,46969L,46970L,46971L,46972L,46973L,46974L,
9808946975L,46976L,46977L,46978L,46979L,46980L,46981L,46982L,46983L,46984L,
9809046985L,46986L,46987L,46988L,46989L,46990L,46991L,46992L,46993L,46994L,
9809146995L,46996L,46997L,46998L,46999L,47000L,47001L,47002L,47003L,47004L,
9809247005L,47006L,47007L,47008L,47009L,47010L,47011L,47012L,47013L,47014L,
9809347015L,47016L,47017L,47018L,47019L,47020L,47021L,47022L,47023L,47024L,
9809447025L,47026L,47027L,47028L,47029L,47030L,47031L,47032L,47033L,47034L,
9809547035L,47036L,47037L,47038L,47039L,47040L,47041L,47042L,47043L,47044L,
9809647045L,47046L,47047L,47048L,47049L,47050L,47051L,47052L,47053L,47054L,
9809747055L,47056L,47057L,47058L,47059L,47060L,47061L,47062L,47063L,47064L,
9809847065L,47066L,47067L,47068L,47069L,47070L,47071L,47072L,47073L,47074L,
9809947075L,47076L,47077L,47078L,47079L,47080L,47081L,47082L,47083L,47084L,
9810047085L,47086L,47087L,47088L,47089L,47090L,47091L,47092L,47093L,47094L,
9810147095L,47096L,47097L,47098L,47099L,47100L,47101L,47102L,47103L,47104L,
9810247105L,47106L,47107L,47108L,47109L,47110L,47111L,47112L,47113L,47114L,
9810347115L,47116L,47117L,47118L,47119L,47120L,47121L,47122L,47123L,47124L,
9810447125L,47126L,47127L,47128L,47129L,47130L,47131L,47132L,47133L,47134L,
9810547135L,47136L,47137L,47138L,47139L,47140L,47141L,47142L,47143L,47144L,
9810647145L,47146L,47147L,47148L,47149L,47150L,47151L,47152L,47153L,47154L,
9810747155L,47156L,47157L,47158L,47159L,47160L,47161L,47162L,47163L,47164L,
9810847165L,47166L,47167L,47168L,47169L,47170L,47171L,47172L,47173L,47174L,
9810947175L,47176L,47177L,47178L,47179L,47180L,47181L,47182L,47183L,47184L,
9811047185L,47186L,47187L,47188L,47189L,47190L,47191L,47192L,47193L,47194L,
9811147195L,47196L,47197L,47198L,47199L,47200L,47201L,47202L,47203L,47204L,
9811247205L,47206L,47207L,47208L,47209L,47210L,47211L,47212L,47213L,47214L,
9811347215L,47216L,47217L,47218L,47219L,47220L,47221L,47222L,47223L,47224L,
9811447225L,47226L,47227L,47228L,47229L,47230L,47231L,47232L,47233L,47234L,
9811547235L,47236L,47237L,47238L,47239L,47240L,47241L,47242L,47243L,47244L,
9811647245L,47246L,47247L,47248L,47249L,47250L,47251L,47252L,47253L,47254L,
9811747255L,47256L,47257L,47258L,47259L,47260L,47261L,47262L,47263L,47264L,
9811847265L,47266L,47267L,47268L,47269L,47270L,47271L,47272L,47273L,47274L,
9811947275L,47276L,47277L,47278L,47279L,47280L,47281L,47282L,47283L,47284L,
9812047285L,47286L,47287L,47288L,47289L,47290L,47291L,47292L,47293L,47294L,
9812147295L,47296L,47297L,47298L,47299L,47300L,47301L,47302L,47303L,47304L,
9812247305L,47306L,47307L,47308L,47309L,47310L,47311L,47312L,47313L,47314L,
9812347315L,47316L,47317L,47318L,47319L,47320L,47321L,47322L,47323L,47324L,
9812447325L,47326L,47327L,47328L,47329L,47330L,47331L,47332L,47333L,47334L,
9812547335L,47336L,47337L,47338L,47339L,47340L,47341L,47342L,47343L,47344L,
9812647345L,47346L,47347L,47348L,47349L,47350L,47351L,47352L,47353L,47354L,
9812747355L,47356L,47357L,47358L,47359L,47360L,47361L,47362L,47363L,47364L,
9812847365L,47366L,47367L,47368L,47369L,47370L,47371L,47372L,47373L,47374L,
9812947375L,47376L,47377L,47378L,47379L,47380L,47381L,47382L,47383L,47384L,
9813047385L,47386L,47387L,47388L,47389L,47390L,47391L,47392L,47393L,47394L,
9813147395L,47396L,47397L,47398L,47399L,47400L,47401L,47402L,47403L,47404L,
9813247405L,47406L,47407L,47408L,47409L,47410L,47411L,47412L,47413L,47414L,
9813347415L,47416L,47417L,47418L,47419L,47420L,47421L,47422L,47423L,47424L,
9813447425L,47426L,47427L,47428L,47429L,47430L,47431L,47432L,47433L,47434L,
9813547435L,47436L,47437L,47438L,47439L,47440L,47441L,47442L,47443L,47444L,
9813647445L,47446L,47447L,47448L,47449L,47450L,47451L,47452L,47453L,47454L,
9813747455L,47456L,47457L,47458L,47459L,47460L,47461L,47462L,47463L,47464L,
9813847465L,47466L,47467L,47468L,47469L,47470L,47471L,47472L,47473L,47474L,
9813947475L,47476L,47477L,47478L,47479L,47480L,47481L,47482L,47483L,47484L,
9814047485L,47486L,47487L,47488L,47489L,47490L,47491L,47492L,47493L,47494L,
9814147495L,47496L,47497L,47498L,47499L,47500L,47501L,47502L,47503L,47504L,
9814247505L,47506L,47507L,47508L,47509L,47510L,47511L,47512L,47513L,47514L,
9814347515L,47516L,47517L,47518L,47519L,47520L,47521L,47522L,47523L,47524L,
9814447525L,47526L,47527L,47528L,47529L,47530L,47531L,47532L,47533L,47534L,
9814547535L,47536L,47537L,47538L,47539L,47540L,47541L,47542L,47543L,47544L,
9814647545L,47546L,47547L,47548L,47549L,47550L,47551L,47552L,47553L,47554L,
9814747555L,47556L,47557L,47558L,47559L,47560L,47561L,47562L,47563L,47564L,
9814847565L,47566L,47567L,47568L,47569L,47570L,47571L,47572L,47573L,47574L,
9814947575L,47576L,47577L,47578L,47579L,47580L,47581L,47582L,47583L,47584L,
9815047585L,47586L,47587L,47588L,47589L,47590L,47591L,47592L,47593L,47594L,
9815147595L,47596L,47597L,47598L,47599L,47600L,47601L,47602L,47603L,47604L,
9815247605L,47606L,47607L,47608L,47609L,47610L,47611L,47612L,47613L,47614L,
9815347615L,47616L,47617L,47618L,47619L,47620L,47621L,47622L,47623L,47624L,
9815447625L,47626L,47627L,47628L,47629L,47630L,47631L,47632L,47633L,47634L,
9815547635L,47636L,47637L,47638L,47639L,47640L,47641L,47642L,47643L,47644L,
9815647645L,47646L,47647L,47648L,47649L,47650L,47651L,47652L,47653L,47654L,
9815747655L,47656L,47657L,47658L,47659L,47660L,47661L,47662L,47663L,47664L,
9815847665L,47666L,47667L,47668L,47669L,47670L,47671L,47672L,47673L,47674L,
9815947675L,47676L,47677L,47678L,47679L,47680L,47681L,47682L,47683L,47684L,
9816047685L,47686L,47687L,47688L,47689L,47690L,47691L,47692L,47693L,47694L,
9816147695L,47696L,47697L,47698L,47699L,47700L,47701L,47702L,47703L,47704L,
9816247705L,47706L,47707L,47708L,47709L,47710L,47711L,47712L,47713L,47714L,
9816347715L,47716L,47717L,47718L,47719L,47720L,47721L,47722L,47723L,47724L,
9816447725L,47726L,47727L,47728L,47729L,47730L,47731L,47732L,47733L,47734L,
9816547735L,47736L,47737L,47738L,47739L,47740L,47741L,47742L,47743L,47744L,
9816647745L,47746L,47747L,47748L,47749L,47750L,47751L,47752L,47753L,47754L,
9816747755L,47756L,47757L,47758L,47759L,47760L,47761L,47762L,47763L,47764L,
9816847765L,47766L,47767L,47768L,47769L,47770L,47771L,47772L,47773L,47774L,
9816947775L,47776L,47777L,47778L,47779L,47780L,47781L,47782L,47783L,47784L,
9817047785L,47786L,47787L,47788L,47789L,47790L,47791L,47792L,47793L,47794L,
9817147795L,47796L,47797L,47798L,47799L,47800L,47801L,47802L,47803L,47804L,
9817247805L,47806L,47807L,47808L,47809L,47810L,47811L,47812L,47813L,47814L,
9817347815L,47816L,47817L,47818L,47819L,47820L,47821L,47822L,47823L,47824L,
9817447825L,47826L,47827L,47828L,47829L,47830L,47831L,47832L,47833L,47834L,
9817547835L,47836L,47837L,47838L,47839L,47840L,47841L,47842L,47843L,47844L,
9817647845L,47846L,47847L,47848L,47849L,47850L,47851L,47852L,47853L,47854L,
9817747855L,47856L,47857L,47858L,47859L,47860L,47861L,47862L,47863L,47864L,
9817847865L,47866L,47867L,47868L,47869L,47870L,47871L,47872L,47873L,47874L,
9817947875L,47876L,47877L,47878L,47879L,47880L,47881L,47882L,47883L,47884L,
9818047885L,47886L,47887L,47888L,47889L,47890L,47891L,47892L,47893L,47894L,
9818147895L,47896L,47897L,47898L,47899L,47900L,47901L,47902L,47903L,47904L,
9818247905L,47906L,47907L,47908L,47909L,47910L,47911L,47912L,47913L,47914L,
9818347915L,47916L,47917L,47918L,47919L,47920L,47921L,47922L,47923L,47924L,
9818447925L,47926L,47927L,47928L,47929L,47930L,47931L,47932L,47933L,47934L,
9818547935L,47936L,47937L,47938L,47939L,47940L,47941L,47942L,47943L,47944L,
9818647945L,47946L,47947L,47948L,47949L,47950L,47951L,47952L,47953L,47954L,
9818747955L,47956L,47957L,47958L,47959L,47960L,47961L,47962L,47963L,47964L,
9818847965L,47966L,47967L,47968L,47969L,47970L,47971L,47972L,47973L,47974L,
9818947975L,47976L,47977L,47978L,47979L,47980L,47981L,47982L,47983L,47984L,
9819047985L,47986L,47987L,47988L,47989L,47990L,47991L,47992L,47993L,47994L,
9819147995L,47996L,47997L,47998L,47999L,48000L,48001L,48002L,48003L,48004L,
9819248005L,48006L,48007L,48008L,48009L,48010L,48011L,48012L,48013L,48014L,
9819348015L,48016L,48017L,48018L,48019L,48020L,48021L,48022L,48023L,48024L,
9819448025L,48026L,48027L,48028L,48029L,48030L,48031L,48032L,48033L,48034L,
9819548035L,48036L,48037L,48038L,48039L,48040L,48041L,48042L,48043L,48044L,
9819648045L,48046L,48047L,48048L,48049L,48050L,48051L,48052L,48053L,48054L,
9819748055L,48056L,48057L,48058L,48059L,48060L,48061L,48062L,48063L,48064L,
9819848065L,48066L,48067L,48068L,48069L,48070L,48071L,48072L,48073L,48074L,
9819948075L,48076L,48077L,48078L,48079L,48080L,48081L,48082L,48083L,48084L,
9820048085L,48086L,48087L,48088L,48089L,48090L,48091L,48092L,48093L,48094L,
9820148095L,48096L,48097L,48098L,48099L,48100L,48101L,48102L,48103L,48104L,
9820248105L,48106L,48107L,48108L,48109L,48110L,48111L,48112L,48113L,48114L,
9820348115L,48116L,48117L,48118L,48119L,48120L,48121L,48122L,48123L,48124L,
9820448125L,48126L,48127L,48128L,48129L,48130L,48131L,48132L,48133L,48134L,
9820548135L,48136L,48137L,48138L,48139L,48140L,48141L,48142L,48143L,48144L,
9820648145L,48146L,48147L,48148L,48149L,48150L,48151L,48152L,48153L,48154L,
9820748155L,48156L,48157L,48158L,48159L,48160L,48161L,48162L,48163L,48164L,
9820848165L,48166L,48167L,48168L,48169L,48170L,48171L,48172L,48173L,48174L,
9820948175L,48176L,48177L,48178L,48179L,48180L,48181L,48182L,48183L,48184L,
9821048185L,48186L,48187L,48188L,48189L,48190L,48191L,48192L,48193L,48194L,
9821148195L,48196L,48197L,48198L,48199L,48200L,48201L,48202L,48203L,48204L,
9821248205L,48206L,48207L,48208L,48209L,48210L,48211L,48212L,48213L,48214L,
9821348215L,48216L,48217L,48218L,48219L,48220L,48221L,48222L,48223L,48224L,
9821448225L,48226L,48227L,48228L,48229L,48230L,48231L,48232L,48233L,48234L,
9821548235L,48236L,48237L,48238L,48239L,48240L,48241L,48242L,48243L,48244L,
9821648245L,48246L,48247L,48248L,48249L,48250L,48251L,48252L,48253L,48254L,
9821748255L,48256L,48257L,48258L,48259L,48260L,48261L,48262L,48263L,48264L,
9821848265L,48266L,48267L,48268L,48269L,48270L,48271L,48272L,48273L,48274L,
9821948275L,48276L,48277L,48278L,48279L,48280L,48281L,48282L,48283L,48284L,
9822048285L,48286L,48287L,48288L,48289L,48290L,48291L,48292L,48293L,48294L,
9822148295L,48296L,48297L,48298L,48299L,48300L,48301L,48302L,48303L,48304L,
9822248305L,48306L,48307L,48308L,48309L,48310L,48311L,48312L,48313L,48314L,
9822348315L,48316L,48317L,48318L,48319L,48320L,48321L,48322L,48323L,48324L,
9822448325L,48326L,48327L,48328L,48329L,48330L,48331L,48332L,48333L,48334L,
9822548335L,48336L,48337L,48338L,48339L,48340L,48341L,48342L,48343L,48344L,
9822648345L,48346L,48347L,48348L,48349L,48350L,48351L,48352L,48353L,48354L,
9822748355L,48356L,48357L,48358L,48359L,48360L,48361L,48362L,48363L,48364L,
9822848365L,48366L,48367L,48368L,48369L,48370L,48371L,48372L,48373L,48374L,
9822948375L,48376L,48377L,48378L,48379L,48380L,48381L,48382L,48383L,48384L,
9823048385L,48386L,48387L,48388L,48389L,48390L,48391L,48392L,48393L,48394L,
9823148395L,48396L,48397L,48398L,48399L,48400L,48401L,48402L,48403L,48404L,
9823248405L,48406L,48407L,48408L,48409L,48410L,48411L,48412L,48413L,48414L,
9823348415L,48416L,48417L,48418L,48419L,48420L,48421L,48422L,48423L,48424L,
9823448425L,48426L,48427L,48428L,48429L,48430L,48431L,48432L,48433L,48434L,
9823548435L,48436L,48437L,48438L,48439L,48440L,48441L,48442L,48443L,48444L,
9823648445L,48446L,48447L,48448L,48449L,48450L,48451L,48452L,48453L,48454L,
9823748455L,48456L,48457L,48458L,48459L,48460L,48461L,48462L,48463L,48464L,
9823848465L,48466L,48467L,48468L,48469L,48470L,48471L,48472L,48473L,48474L,
9823948475L,48476L,48477L,48478L,48479L,48480L,48481L,48482L,48483L,48484L,
9824048485L,48486L,48487L,48488L,48489L,48490L,48491L,48492L,48493L,48494L,
9824148495L,48496L,48497L,48498L,48499L,48500L,48501L,48502L,48503L,48504L,
9824248505L,48506L,48507L,48508L,48509L,48510L,48511L,48512L,48513L,48514L,
9824348515L,48516L,48517L,48518L,48519L,48520L,48521L,48522L,48523L,48524L,
9824448525L,48526L,48527L,48528L,48529L,48530L,48531L,48532L,48533L,48534L,
9824548535L,48536L,48537L,48538L,48539L,48540L,48541L,48542L,48543L,48544L,
9824648545L,48546L,48547L,48548L,48549L,48550L,48551L,48552L,48553L,48554L,
9824748555L,48556L,48557L,48558L,48559L,48560L,48561L,48562L,48563L,48564L,
9824848565L,48566L,48567L,48568L,48569L,48570L,48571L,48572L,48573L,48574L,
9824948575L,48576L,48577L,48578L,48579L,48580L,48581L,48582L,48583L,48584L,
9825048585L,48586L,48587L,48588L,48589L,48590L,48591L,48592L,48593L,48594L,
9825148595L,48596L,48597L,48598L,48599L,48600L,48601L,48602L,48603L,48604L,
9825248605L,48606L,48607L,48608L,48609L,48610L,48611L,48612L,48613L,48614L,
9825348615L,48616L,48617L,48618L,48619L,48620L,48621L,48622L,48623L,48624L,
9825448625L,48626L,48627L,48628L,48629L,48630L,48631L,48632L,48633L,48634L,
9825548635L,48636L,48637L,48638L,48639L,48640L,48641L,48642L,48643L,48644L,
9825648645L,48646L,48647L,48648L,48649L,48650L,48651L,48652L,48653L,48654L,
9825748655L,48656L,48657L,48658L,48659L,48660L,48661L,48662L,48663L,48664L,
9825848665L,48666L,48667L,48668L,48669L,48670L,48671L,48672L,48673L,48674L,
9825948675L,48676L,48677L,48678L,48679L,48680L,48681L,48682L,48683L,48684L,
9826048685L,48686L,48687L,48688L,48689L,48690L,48691L,48692L,48693L,48694L,
9826148695L,48696L,48697L,48698L,48699L,48700L,48701L,48702L,48703L,48704L,
9826248705L,48706L,48707L,48708L,48709L,48710L,48711L,48712L,48713L,48714L,
9826348715L,48716L,48717L,48718L,48719L,48720L,48721L,48722L,48723L,48724L,
9826448725L,48726L,48727L,48728L,48729L,48730L,48731L,48732L,48733L,48734L,
9826548735L,48736L,48737L,48738L,48739L,48740L,48741L,48742L,48743L,48744L,
9826648745L,48746L,48747L,48748L,48749L,48750L,48751L,48752L,48753L,48754L,
9826748755L,48756L,48757L,48758L,48759L,48760L,48761L,48762L,48763L,48764L,
9826848765L,48766L,48767L,48768L,48769L,48770L,48771L,48772L,48773L,48774L,
9826948775L,48776L,48777L,48778L,48779L,48780L,48781L,48782L,48783L,48784L,
9827048785L,48786L,48787L,48788L,48789L,48790L,48791L,48792L,48793L,48794L,
9827148795L,48796L,48797L,48798L,48799L,48800L,48801L,48802L,48803L,48804L,
9827248805L,48806L,48807L,48808L,48809L,48810L,48811L,48812L,48813L,48814L,
9827348815L,48816L,48817L,48818L,48819L,48820L,48821L,48822L,48823L,48824L,
9827448825L,48826L,48827L,48828L,48829L,48830L,48831L,48832L,48833L,48834L,
9827548835L,48836L,48837L,48838L,48839L,48840L,48841L,48842L,48843L,48844L,
9827648845L,48846L,48847L,48848L,48849L,48850L,48851L,48852L,48853L,48854L,
9827748855L,48856L,48857L,48858L,48859L,48860L,48861L,48862L,48863L,48864L,
9827848865L,48866L,48867L,48868L,48869L,48870L,48871L,48872L,48873L,48874L,
9827948875L,48876L,48877L,48878L,48879L,48880L,48881L,48882L,48883L,48884L,
9828048885L,48886L,48887L,48888L,48889L,48890L,48891L,48892L,48893L,48894L,
9828148895L,48896L,48897L,48898L,48899L,48900L,48901L,48902L,48903L,48904L,
9828248905L,48906L,48907L,48908L,48909L,48910L,48911L,48912L,48913L,48914L,
9828348915L,48916L,48917L,48918L,48919L,48920L,48921L,48922L,48923L,48924L,
9828448925L,48926L,48927L,48928L,48929L,48930L,48931L,48932L,48933L,48934L,
9828548935L,48936L,48937L,48938L,48939L,48940L,48941L,48942L,48943L,48944L,
9828648945L,48946L,48947L,48948L,48949L,48950L,48951L,48952L,48953L,48954L,
9828748955L,48956L,48957L,48958L,48959L,48960L,48961L,48962L,48963L,48964L,
9828848965L,48966L,48967L,48968L,48969L,48970L,48971L,48972L,48973L,48974L,
9828948975L,48976L,48977L,48978L,48979L,48980L,48981L,48982L,48983L,48984L,
9829048985L,48986L,48987L,48988L,48989L,48990L,48991L,48992L,48993L,48994L,
9829148995L,48996L,48997L,48998L,48999L,49000L,49001L,49002L,49003L,49004L,
9829249005L,49006L,49007L,49008L,49009L,49010L,49011L,49012L,49013L,49014L,
9829349015L,49016L,49017L,49018L,49019L,49020L,49021L,49022L,49023L,49024L,
9829449025L,49026L,49027L,49028L,49029L,49030L,49031L,49032L,49033L,49034L,
9829549035L,49036L,49037L,49038L,49039L,49040L,49041L,49042L,49043L,49044L,
9829649045L,49046L,49047L,49048L,49049L,49050L,49051L,49052L,49053L,49054L,
9829749055L,49056L,49057L,49058L,49059L,49060L,49061L,49062L,49063L,49064L,
9829849065L,49066L,49067L,49068L,49069L,49070L,49071L,49072L,49073L,49074L,
9829949075L,49076L,49077L,49078L,49079L,49080L,49081L,49082L,49083L,49084L,
9830049085L,49086L,49087L,49088L,49089L,49090L,49091L,49092L,49093L,49094L,
9830149095L,49096L,49097L,49098L,49099L,49100L,49101L,49102L,49103L,49104L,
9830249105L,49106L,49107L,49108L,49109L,49110L,49111L,49112L,49113L,49114L,
9830349115L,49116L,49117L,49118L,49119L,49120L,49121L,49122L,49123L,49124L,
9830449125L,49126L,49127L,49128L,49129L,49130L,49131L,49132L,49133L,49134L,
9830549135L,49136L,49137L,49138L,49139L,49140L,49141L,49142L,49143L,49144L,
9830649145L,49146L,49147L,49148L,49149L,49150L,49151L,49152L,49153L,49154L,
9830749155L,49156L,49157L,49158L,49159L,49160L,49161L,49162L,49163L,49164L,
9830849165L,49166L,49167L,49168L,49169L,49170L,49171L,49172L,49173L,49174L,
9830949175L,49176L,49177L,49178L,49179L,49180L,49181L,49182L,49183L,49184L,
9831049185L,49186L,49187L,49188L,49189L,49190L,49191L,49192L,49193L,49194L,
9831149195L,49196L,49197L,49198L,49199L,49200L,49201L,49202L,49203L,49204L,
9831249205L,49206L,49207L,49208L,49209L,49210L,49211L,49212L,49213L,49214L,
9831349215L,49216L,49217L,49218L,49219L,49220L,49221L,49222L,49223L,49224L,
9831449225L,49226L,49227L,49228L,49229L,49230L,49231L,49232L,49233L,49234L,
9831549235L,49236L,49237L,49238L,49239L,49240L,49241L,49242L,49243L,49244L,
9831649245L,49246L,49247L,49248L,49249L,49250L,49251L,49252L,49253L,49254L,
9831749255L,49256L,49257L,49258L,49259L,49260L,49261L,49262L,49263L,49264L,
9831849265L,49266L,49267L,49268L,49269L,49270L,49271L,49272L,49273L,49274L,
9831949275L,49276L,49277L,49278L,49279L,49280L,49281L,49282L,49283L,49284L,
9832049285L,49286L,49287L,49288L,49289L,49290L,49291L,49292L,49293L,49294L,
9832149295L,49296L,49297L,49298L,49299L,49300L,49301L,49302L,49303L,49304L,
9832249305L,49306L,49307L,49308L,49309L,49310L,49311L,49312L,49313L,49314L,
9832349315L,49316L,49317L,49318L,49319L,49320L,49321L,49322L,49323L,49324L,
9832449325L,49326L,49327L,49328L,49329L,49330L,49331L,49332L,49333L,49334L,
9832549335L,49336L,49337L,49338L,49339L,49340L,49341L,49342L,49343L,49344L,
9832649345L,49346L,49347L,49348L,49349L,49350L,49351L,49352L,49353L,49354L,
9832749355L,49356L,49357L,49358L,49359L,49360L,49361L,49362L,49363L,49364L,
9832849365L,49366L,49367L,49368L,49369L,49370L,49371L,49372L,49373L,49374L,
9832949375L,49376L,49377L,49378L,49379L,49380L,49381L,49382L,49383L,49384L,
9833049385L,49386L,49387L,49388L,49389L,49390L,49391L,49392L,49393L,49394L,
9833149395L,49396L,49397L,49398L,49399L,49400L,49401L,49402L,49403L,49404L,
9833249405L,49406L,49407L,49408L,49409L,49410L,49411L,49412L,49413L,49414L,
9833349415L,49416L,49417L,49418L,49419L,49420L,49421L,49422L,49423L,49424L,
9833449425L,49426L,49427L,49428L,49429L,49430L,49431L,49432L,49433L,49434L,
9833549435L,49436L,49437L,49438L,49439L,49440L,49441L,49442L,49443L,49444L,
9833649445L,49446L,49447L,49448L,49449L,49450L,49451L,49452L,49453L,49454L,
9833749455L,49456L,49457L,49458L,49459L,49460L,49461L,49462L,49463L,49464L,
9833849465L,49466L,49467L,49468L,49469L,49470L,49471L,49472L,49473L,49474L,
9833949475L,49476L,49477L,49478L,49479L,49480L,49481L,49482L,49483L,49484L,
9834049485L,49486L,49487L,49488L,49489L,49490L,49491L,49492L,49493L,49494L,
9834149495L,49496L,49497L,49498L,49499L,49500L,49501L,49502L,49503L,49504L,
9834249505L,49506L,49507L,49508L,49509L,49510L,49511L,49512L,49513L,49514L,
9834349515L,49516L,49517L,49518L,49519L,49520L,49521L,49522L,49523L,49524L,
9834449525L,49526L,49527L,49528L,49529L,49530L,49531L,49532L,49533L,49534L,
9834549535L,49536L,49537L,49538L,49539L,49540L,49541L,49542L,49543L,49544L,
9834649545L,49546L,49547L,49548L,49549L,49550L,49551L,49552L,49553L,49554L,
9834749555L,49556L,49557L,49558L,49559L,49560L,49561L,49562L,49563L,49564L,
9834849565L,49566L,49567L,49568L,49569L,49570L,49571L,49572L,49573L,49574L,
9834949575L,49576L,49577L,49578L,49579L,49580L,49581L,49582L,49583L,49584L,
9835049585L,49586L,49587L,49588L,49589L,49590L,49591L,49592L,49593L,49594L,
9835149595L,49596L,49597L,49598L,49599L,49600L,49601L,49602L,49603L,49604L,
9835249605L,49606L,49607L,49608L,49609L,49610L,49611L,49612L,49613L,49614L,
9835349615L,49616L,49617L,49618L,49619L,49620L,49621L,49622L,49623L,49624L,
9835449625L,49626L,49627L,49628L,49629L,49630L,49631L,49632L,49633L,49634L,
9835549635L,49636L,49637L,49638L,49639L,49640L,49641L,49642L,49643L,49644L,
9835649645L,49646L,49647L,49648L,49649L,49650L,49651L,49652L,49653L,49654L,
9835749655L,49656L,49657L,49658L,49659L,49660L,49661L,49662L,49663L,49664L,
9835849665L,49666L,49667L,49668L,49669L,49670L,49671L,49672L,49673L,49674L,
9835949675L,49676L,49677L,49678L,49679L,49680L,49681L,49682L,49683L,49684L,
9836049685L,49686L,49687L,49688L,49689L,49690L,49691L,49692L,49693L,49694L,
9836149695L,49696L,49697L,49698L,49699L,49700L,49701L,49702L,49703L,49704L,
9836249705L,49706L,49707L,49708L,49709L,49710L,49711L,49712L,49713L,49714L,
9836349715L,49716L,49717L,49718L,49719L,49720L,49721L,49722L,49723L,49724L,
9836449725L,49726L,49727L,49728L,49729L,49730L,49731L,49732L,49733L,49734L,
9836549735L,49736L,49737L,49738L,49739L,49740L,49741L,49742L,49743L,49744L,
9836649745L,49746L,49747L,49748L,49749L,49750L,49751L,49752L,49753L,49754L,
9836749755L,49756L,49757L,49758L,49759L,49760L,49761L,49762L,49763L,49764L,
9836849765L,49766L,49767L,49768L,49769L,49770L,49771L,49772L,49773L,49774L,
9836949775L,49776L,49777L,49778L,49779L,49780L,49781L,49782L,49783L,49784L,
9837049785L,49786L,49787L,49788L,49789L,49790L,49791L,49792L,49793L,49794L,
9837149795L,49796L,49797L,49798L,49799L,49800L,49801L,49802L,49803L,49804L,
9837249805L,49806L,49807L,49808L,49809L,49810L,49811L,49812L,49813L,49814L,
9837349815L,49816L,49817L,49818L,49819L,49820L,49821L,49822L,49823L,49824L,
9837449825L,49826L,49827L,49828L,49829L,49830L,49831L,49832L,49833L,49834L,
9837549835L,49836L,49837L,49838L,49839L,49840L,49841L,49842L,49843L,49844L,
9837649845L,49846L,49847L,49848L,49849L,49850L,49851L,49852L,49853L,49854L,
9837749855L,49856L,49857L,49858L,49859L,49860L,49861L,49862L,49863L,49864L,
9837849865L,49866L,49867L,49868L,49869L,49870L,49871L,49872L,49873L,49874L,
9837949875L,49876L,49877L,49878L,49879L,49880L,49881L,49882L,49883L,49884L,
9838049885L,49886L,49887L,49888L,49889L,49890L,49891L,49892L,49893L,49894L,
9838149895L,49896L,49897L,49898L,49899L,49900L,49901L,49902L,49903L,49904L,
9838249905L,49906L,49907L,49908L,49909L,49910L,49911L,49912L,49913L,49914L,
9838349915L,49916L,49917L,49918L,49919L,49920L,49921L,49922L,49923L,49924L,
9838449925L,49926L,49927L,49928L,49929L,49930L,49931L,49932L,49933L,49934L,
9838549935L,49936L,49937L,49938L,49939L,49940L,49941L,49942L,49943L,49944L,
9838649945L,49946L,49947L,49948L,49949L,49950L,49951L,49952L,49953L,49954L,
9838749955L,49956L,49957L,49958L,49959L,49960L,49961L,49962L,49963L,49964L,
9838849965L,49966L,49967L,49968L,49969L,49970L,49971L,49972L,49973L,49974L,
9838949975L,49976L,49977L,49978L,49979L,49980L,49981L,49982L,49983L,49984L,
9839049985L,49986L,49987L,49988L,49989L,49990L,49991L,49992L,49993L,49994L,
9839149995L,49996L,49997L,49998L,49999L,50000L,50001L,50002L,50003L,50004L,
9839250005L,50006L,50007L,50008L,50009L,50010L,50011L,50012L,50013L,50014L,
9839350015L,50016L,50017L,50018L,50019L,50020L,50021L,50022L,50023L,50024L,
9839450025L,50026L,50027L,50028L,50029L,50030L,50031L,50032L,50033L,50034L,
9839550035L,50036L,50037L,50038L,50039L,50040L,50041L,50042L,50043L,50044L,
9839650045L,50046L,50047L,50048L,50049L,50050L,50051L,50052L,50053L,50054L,
9839750055L,50056L,50057L,50058L,50059L,50060L,50061L,50062L,50063L,50064L,
9839850065L,50066L,50067L,50068L,50069L,50070L,50071L,50072L,50073L,50074L,
9839950075L,50076L,50077L,50078L,50079L,50080L,50081L,50082L,50083L,50084L,
9840050085L,50086L,50087L,50088L,50089L,50090L,50091L,50092L,50093L,50094L,
9840150095L,50096L,50097L,50098L,50099L,50100L,50101L,50102L,50103L,50104L,
9840250105L,50106L,50107L,50108L,50109L,50110L,50111L,50112L,50113L,50114L,
9840350115L,50116L,50117L,50118L,50119L,50120L,50121L,50122L,50123L,50124L,
9840450125L,50126L,50127L,50128L,50129L,50130L,50131L,50132L,50133L,50134L,
9840550135L,50136L,50137L,50138L,50139L,50140L,50141L,50142L,50143L,50144L,
9840650145L,50146L,50147L,50148L,50149L,50150L,50151L,50152L,50153L,50154L,
9840750155L,50156L,50157L,50158L,50159L,50160L,50161L,50162L,50163L,50164L,
9840850165L,50166L,50167L,50168L,50169L,50170L,50171L,50172L,50173L,50174L,
9840950175L,50176L,50177L,50178L,50179L,50180L,50181L,50182L,50183L,50184L,
9841050185L,50186L,50187L,50188L,50189L,50190L,50191L,50192L,50193L,50194L,
9841150195L,50196L,50197L,50198L,50199L,50200L,50201L,50202L,50203L,50204L,
9841250205L,50206L,50207L,50208L,50209L,50210L,50211L,50212L,50213L,50214L,
9841350215L,50216L,50217L,50218L,50219L,50220L,50221L,50222L,50223L,50224L,
9841450225L,50226L,50227L,50228L,50229L,50230L,50231L,50232L,50233L,50234L,
9841550235L,50236L,50237L,50238L,50239L,50240L,50241L,50242L,50243L,50244L,
9841650245L,50246L,50247L,50248L,50249L,50250L,50251L,50252L,50253L,50254L,
9841750255L,50256L,50257L,50258L,50259L,50260L,50261L,50262L,50263L,50264L,
9841850265L,50266L,50267L,50268L,50269L,50270L,50271L,50272L,50273L,50274L,
9841950275L,50276L,50277L,50278L,50279L,50280L,50281L,50282L,50283L,50284L,
9842050285L,50286L,50287L,50288L,50289L,50290L,50291L,50292L,50293L,50294L,
9842150295L,50296L,50297L,50298L,50299L,50300L,50301L,50302L,50303L,50304L,
9842250305L,50306L,50307L,50308L,50309L,50310L,50311L,50312L,50313L,50314L,
9842350315L,50316L,50317L,50318L,50319L,50320L,50321L,50322L,50323L,50324L,
9842450325L,50326L,50327L,50328L,50329L,50330L,50331L,50332L,50333L,50334L,
9842550335L,50336L,50337L,50338L,50339L,50340L,50341L,50342L,50343L,50344L,
9842650345L,50346L,50347L,50348L,50349L,50350L,50351L,50352L,50353L,50354L,
9842750355L,50356L,50357L,50358L,50359L,50360L,50361L,50362L,50363L,50364L,
9842850365L,50366L,50367L,50368L,50369L,50370L,50371L,50372L,50373L,50374L,
9842950375L,50376L,50377L,50378L,50379L,50380L,50381L,50382L,50383L,50384L,
9843050385L,50386L,50387L,50388L,50389L,50390L,50391L,50392L,50393L,50394L,
9843150395L,50396L,50397L,50398L,50399L,50400L,50401L,50402L,50403L,50404L,
9843250405L,50406L,50407L,50408L,50409L,50410L,50411L,50412L,50413L,50414L,
9843350415L,50416L,50417L,50418L,50419L,50420L,50421L,50422L,50423L,50424L,
9843450425L,50426L,50427L,50428L,50429L,50430L,50431L,50432L,50433L,50434L,
9843550435L,50436L,50437L,50438L,50439L,50440L,50441L,50442L,50443L,50444L,
9843650445L,50446L,50447L,50448L,50449L,50450L,50451L,50452L,50453L,50454L,
9843750455L,50456L,50457L,50458L,50459L,50460L,50461L,50462L,50463L,50464L,
9843850465L,50466L,50467L,50468L,50469L,50470L,50471L,50472L,50473L,50474L,
9843950475L,50476L,50477L,50478L,50479L,50480L,50481L,50482L,50483L,50484L,
9844050485L,50486L,50487L,50488L,50489L,50490L,50491L,50492L,50493L,50494L,
9844150495L,50496L,50497L,50498L,50499L,50500L,50501L,50502L,50503L,50504L,
9844250505L,50506L,50507L,50508L,50509L,50510L,50511L,50512L,50513L,50514L,
9844350515L,50516L,50517L,50518L,50519L,50520L,50521L,50522L,50523L,50524L,
9844450525L,50526L,50527L,50528L,50529L,50530L,50531L,50532L,50533L,50534L,
9844550535L,50536L,50537L,50538L,50539L,50540L,50541L,50542L,50543L,50544L,
9844650545L,50546L,50547L,50548L,50549L,50550L,50551L,50552L,50553L,50554L,
9844750555L,50556L,50557L,50558L,50559L,50560L,50561L,50562L,50563L,50564L,
9844850565L,50566L,50567L,50568L,50569L,50570L,50571L,50572L,50573L,50574L,
9844950575L,50576L,50577L,50578L,50579L,50580L,50581L,50582L,50583L,50584L,
9845050585L,50586L,50587L,50588L,50589L,50590L,50591L,50592L,50593L,50594L,
9845150595L,50596L,50597L,50598L,50599L,50600L,50601L,50602L,50603L,50604L,
9845250605L,50606L,50607L,50608L,50609L,50610L,50611L,50612L,50613L,50614L,
9845350615L,50616L,50617L,50618L,50619L,50620L,50621L,50622L,50623L,50624L,
9845450625L,50626L,50627L,50628L,50629L,50630L,50631L,50632L,50633L,50634L,
9845550635L,50636L,50637L,50638L,50639L,50640L,50641L,50642L,50643L,50644L,
9845650645L,50646L,50647L,50648L,50649L,50650L,50651L,50652L,50653L,50654L,
9845750655L,50656L,50657L,50658L,50659L,50660L,50661L,50662L,50663L,50664L,
9845850665L,50666L,50667L,50668L,50669L,50670L,50671L,50672L,50673L,50674L,
9845950675L,50676L,50677L,50678L,50679L,50680L,50681L,50682L,50683L,50684L,
9846050685L,50686L,50687L,50688L,50689L,50690L,50691L,50692L,50693L,50694L,
9846150695L,50696L,50697L,50698L,50699L,50700L,50701L,50702L,50703L,50704L,
9846250705L,50706L,50707L,50708L,50709L,50710L,50711L,50712L,50713L,50714L,
9846350715L,50716L,50717L,50718L,50719L,50720L,50721L,50722L,50723L,50724L,
9846450725L,50726L,50727L,50728L,50729L,50730L,50731L,50732L,50733L,50734L,
9846550735L,50736L,50737L,50738L,50739L,50740L,50741L,50742L,50743L,50744L,
9846650745L,50746L,50747L,50748L,50749L,50750L,50751L,50752L,50753L,50754L,
9846750755L,50756L,50757L,50758L,50759L,50760L,50761L,50762L,50763L,50764L,
9846850765L,50766L,50767L,50768L,50769L,50770L,50771L,50772L,50773L,50774L,
9846950775L,50776L,50777L,50778L,50779L,50780L,50781L,50782L,50783L,50784L,
9847050785L,50786L,50787L,50788L,50789L,50790L,50791L,50792L,50793L,50794L,
9847150795L,50796L,50797L,50798L,50799L,50800L,50801L,50802L,50803L,50804L,
9847250805L,50806L,50807L,50808L,50809L,50810L,50811L,50812L,50813L,50814L,
9847350815L,50816L,50817L,50818L,50819L,50820L,50821L,50822L,50823L,50824L,
9847450825L,50826L,50827L,50828L,50829L,50830L,50831L,50832L,50833L,50834L,
9847550835L,50836L,50837L,50838L,50839L,50840L,50841L,50842L,50843L,50844L,
9847650845L,50846L,50847L,50848L,50849L,50850L,50851L,50852L,50853L,50854L,
9847750855L,50856L,50857L,50858L,50859L,50860L,50861L,50862L,50863L,50864L,
9847850865L,50866L,50867L,50868L,50869L,50870L,50871L,50872L,50873L,50874L,
9847950875L,50876L,50877L,50878L,50879L,50880L,50881L,50882L,50883L,50884L,
9848050885L,50886L,50887L,50888L,50889L,50890L,50891L,50892L,50893L,50894L,
9848150895L,50896L,50897L,50898L,50899L,50900L,50901L,50902L,50903L,50904L,
9848250905L,50906L,50907L,50908L,50909L,50910L,50911L,50912L,50913L,50914L,
9848350915L,50916L,50917L,50918L,50919L,50920L,50921L,50922L,50923L,50924L,
9848450925L,50926L,50927L,50928L,50929L,50930L,50931L,50932L,50933L,50934L,
9848550935L,50936L,50937L,50938L,50939L,50940L,50941L,50942L,50943L,50944L,
9848650945L,50946L,50947L,50948L,50949L,50950L,50951L,50952L,50953L,50954L,
9848750955L,50956L,50957L,50958L,50959L,50960L,50961L,50962L,50963L,50964L,
9848850965L,50966L,50967L,50968L,50969L,50970L,50971L,50972L,50973L,50974L,
9848950975L,50976L,50977L,50978L,50979L,50980L,50981L,50982L,50983L,50984L,
9849050985L,50986L,50987L,50988L,50989L,50990L,50991L,50992L,50993L,50994L,
9849150995L,50996L,50997L,50998L,50999L,51000L,51001L,51002L,51003L,51004L,
9849251005L,51006L,51007L,51008L,51009L,51010L,51011L,51012L,51013L,51014L,
9849351015L,51016L,51017L,51018L,51019L,51020L,51021L,51022L,51023L,51024L,
9849451025L,51026L,51027L,51028L,51029L,51030L,51031L,51032L,51033L,51034L,
9849551035L,51036L,51037L,51038L,51039L,51040L,51041L,51042L,51043L,51044L,
9849651045L,51046L,51047L,51048L,51049L,51050L,51051L,51052L,51053L,51054L,
9849751055L,51056L,51057L,51058L,51059L,51060L,51061L,51062L,51063L,51064L,
9849851065L,51066L,51067L,51068L,51069L,51070L,51071L,51072L,51073L,51074L,
9849951075L,51076L,51077L,51078L,51079L,51080L,51081L,51082L,51083L,51084L,
9850051085L,51086L,51087L,51088L,51089L,51090L,51091L,51092L,51093L,51094L,
9850151095L,51096L,51097L,51098L,51099L,51100L,51101L,51102L,51103L,51104L,
9850251105L,51106L,51107L,51108L,51109L,51110L,51111L,51112L,51113L,51114L,
9850351115L,51116L,51117L,51118L,51119L,51120L,51121L,51122L,51123L,51124L,
9850451125L,51126L,51127L,51128L,51129L,51130L,51131L,51132L,51133L,51134L,
9850551135L,51136L,51137L,51138L,51139L,51140L,51141L,51142L,51143L,51144L,
9850651145L,51146L,51147L,51148L,51149L,51150L,51151L,51152L,51153L,51154L,
9850751155L,51156L,51157L,51158L,51159L,51160L,51161L,51162L,51163L,51164L,
9850851165L,51166L,51167L,51168L,51169L,51170L,51171L,51172L,51173L,51174L,
9850951175L,51176L,51177L,51178L,51179L,51180L,51181L,51182L,51183L,51184L,
9851051185L,51186L,51187L,51188L,51189L,51190L,51191L,51192L,51193L,51194L,
9851151195L,51196L,51197L,51198L,51199L,51200L,51201L,51202L,51203L,51204L,
9851251205L,51206L,51207L,51208L,51209L,51210L,51211L,51212L,51213L,51214L,
9851351215L,51216L,51217L,51218L,51219L,51220L,51221L,51222L,51223L,51224L,
9851451225L,51226L,51227L,51228L,51229L,51230L,51231L,51232L,51233L,51234L,
9851551235L,51236L,51237L,51238L,51239L,51240L,51241L,51242L,51243L,51244L,
9851651245L,51246L,51247L,51248L,51249L,51250L,51251L,51252L,51253L,51254L,
9851751255L,51256L,51257L,51258L,51259L,51260L,51261L,51262L,51263L,51264L,
9851851265L,51266L,51267L,51268L,51269L,51270L,51271L,51272L,51273L,51274L,
9851951275L,51276L,51277L,51278L,51279L,51280L,51281L,51282L,51283L,51284L,
9852051285L,51286L,51287L,51288L,51289L,51290L,51291L,51292L,51293L,51294L,
9852151295L,51296L,51297L,51298L,51299L,51300L,51301L,51302L,51303L,51304L,
9852251305L,51306L,51307L,51308L,51309L,51310L,51311L,51312L,51313L,51314L,
9852351315L,51316L,51317L,51318L,51319L,51320L,51321L,51322L,51323L,51324L,
9852451325L,51326L,51327L,51328L,51329L,51330L,51331L,51332L,51333L,51334L,
9852551335L,51336L,51337L,51338L,51339L,51340L,51341L,51342L,51343L,51344L,
9852651345L,51346L,51347L,51348L,51349L,51350L,51351L,51352L,51353L,51354L,
9852751355L,51356L,51357L,51358L,51359L,51360L,51361L,51362L,51363L,51364L,
9852851365L,51366L,51367L,51368L,51369L,51370L,51371L,51372L,51373L,51374L,
9852951375L,51376L,51377L,51378L,51379L,51380L,51381L,51382L,51383L,51384L,
9853051385L,51386L,51387L,51388L,51389L,51390L,51391L,51392L,51393L,51394L,
9853151395L,51396L,51397L,51398L,51399L,51400L,51401L,51402L,51403L,51404L,
9853251405L,51406L,51407L,51408L,51409L,51410L,51411L,51412L,51413L,51414L,
9853351415L,51416L,51417L,51418L,51419L,51420L,51421L,51422L,51423L,51424L,
9853451425L,51426L,51427L,51428L,51429L,51430L,51431L,51432L,51433L,51434L,
9853551435L,51436L,51437L,51438L,51439L,51440L,51441L,51442L,51443L,51444L,
9853651445L,51446L,51447L,51448L,51449L,51450L,51451L,51452L,51453L,51454L,
9853751455L,51456L,51457L,51458L,51459L,51460L,51461L,51462L,51463L,51464L,
9853851465L,51466L,51467L,51468L,51469L,51470L,51471L,51472L,51473L,51474L,
9853951475L,51476L,51477L,51478L,51479L,51480L,51481L,51482L,51483L,51484L,
9854051485L,51486L,51487L,51488L,51489L,51490L,51491L,51492L,51493L,51494L,
9854151495L,51496L,51497L,51498L,51499L,51500L,51501L,51502L,51503L,51504L,
9854251505L,51506L,51507L,51508L,51509L,51510L,51511L,51512L,51513L,51514L,
9854351515L,51516L,51517L,51518L,51519L,51520L,51521L,51522L,51523L,51524L,
9854451525L,51526L,51527L,51528L,51529L,51530L,51531L,51532L,51533L,51534L,
9854551535L,51536L,51537L,51538L,51539L,51540L,51541L,51542L,51543L,51544L,
9854651545L,51546L,51547L,51548L,51549L,51550L,51551L,51552L,51553L,51554L,
9854751555L,51556L,51557L,51558L,51559L,51560L,51561L,51562L,51563L,51564L,
9854851565L,51566L,51567L,51568L,51569L,51570L,51571L,51572L,51573L,51574L,
9854951575L,51576L,51577L,51578L,51579L,51580L,51581L,51582L,51583L,51584L,
9855051585L,51586L,51587L,51588L,51589L,51590L,51591L,51592L,51593L,51594L,
9855151595L,51596L,51597L,51598L,51599L,51600L,51601L,51602L,51603L,51604L,
9855251605L,51606L,51607L,51608L,51609L,51610L,51611L,51612L,51613L,51614L,
9855351615L,51616L,51617L,51618L,51619L,51620L,51621L,51622L,51623L,51624L,
9855451625L,51626L,51627L,51628L,51629L,51630L,51631L,51632L,51633L,51634L,
9855551635L,51636L,51637L,51638L,51639L,51640L,51641L,51642L,51643L,51644L,
9855651645L,51646L,51647L,51648L,51649L,51650L,51651L,51652L,51653L,51654L,
9855751655L,51656L,51657L,51658L,51659L,51660L,51661L,51662L,51663L,51664L,
9855851665L,51666L,51667L,51668L,51669L,51670L,51671L,51672L,51673L,51674L,
9855951675L,51676L,51677L,51678L,51679L,51680L,51681L,51682L,51683L,51684L,
9856051685L,51686L,51687L,51688L,51689L,51690L,51691L,51692L,51693L,51694L,
9856151695L,51696L,51697L,51698L,51699L,51700L,51701L,51702L,51703L,51704L,
9856251705L,51706L,51707L,51708L,51709L,51710L,51711L,51712L,51713L,51714L,
9856351715L,51716L,51717L,51718L,51719L,51720L,51721L,51722L,51723L,51724L,
9856451725L,51726L,51727L,51728L,51729L,51730L,51731L,51732L,51733L,51734L,
9856551735L,51736L,51737L,51738L,51739L,51740L,51741L,51742L,51743L,51744L,
9856651745L,51746L,51747L,51748L,51749L,51750L,51751L,51752L,51753L,51754L,
9856751755L,51756L,51757L,51758L,51759L,51760L,51761L,51762L,51763L,51764L,
9856851765L,51766L,51767L,51768L,51769L,51770L,51771L,51772L,51773L,51774L,
9856951775L,51776L,51777L,51778L,51779L,51780L,51781L,51782L,51783L,51784L,
9857051785L,51786L,51787L,51788L,51789L,51790L,51791L,51792L,51793L,51794L,
9857151795L,51796L,51797L,51798L,51799L,51800L,51801L,51802L,51803L,51804L,
9857251805L,51806L,51807L,51808L,51809L,51810L,51811L,51812L,51813L,51814L,
9857351815L,51816L,51817L,51818L,51819L,51820L,51821L,51822L,51823L,51824L,
9857451825L,51826L,51827L,51828L,51829L,51830L,51831L,51832L,51833L,51834L,
9857551835L,51836L,51837L,51838L,51839L,51840L,51841L,51842L,51843L,51844L,
9857651845L,51846L,51847L,51848L,51849L,51850L,51851L,51852L,51853L,51854L,
9857751855L,51856L,51857L,51858L,51859L,51860L,51861L,51862L,51863L,51864L,
9857851865L,51866L,51867L,51868L,51869L,51870L,51871L,51872L,51873L,51874L,
9857951875L,51876L,51877L,51878L,51879L,51880L,51881L,51882L,51883L,51884L,
9858051885L,51886L,51887L,51888L,51889L,51890L,51891L,51892L,51893L,51894L,
9858151895L,51896L,51897L,51898L,51899L,51900L,51901L,51902L,51903L,51904L,
9858251905L,51906L,51907L,51908L,51909L,51910L,51911L,51912L,51913L,51914L,
9858351915L,51916L,51917L,51918L,51919L,51920L,51921L,51922L,51923L,51924L,
9858451925L,51926L,51927L,51928L,51929L,51930L,51931L,51932L,51933L,51934L,
9858551935L,51936L,51937L,51938L,51939L,51940L,51941L,51942L,51943L,51944L,
9858651945L,51946L,51947L,51948L,51949L,51950L,51951L,51952L,51953L,51954L,
9858751955L,51956L,51957L,51958L,51959L,51960L,51961L,51962L,51963L,51964L,
9858851965L,51966L,51967L,51968L,51969L,51970L,51971L,51972L,51973L,51974L,
9858951975L,51976L,51977L,51978L,51979L,51980L,51981L,51982L,51983L,51984L,
9859051985L,51986L,51987L,51988L,51989L,51990L,51991L,51992L,51993L,51994L,
9859151995L,51996L,51997L,51998L,51999L,52000L,52001L,52002L,52003L,52004L,
9859252005L,52006L,52007L,52008L,52009L,52010L,52011L,52012L,52013L,52014L,
9859352015L,52016L,52017L,52018L,52019L,52020L,52021L,52022L,52023L,52024L,
9859452025L,52026L,52027L,52028L,52029L,52030L,52031L,52032L,52033L,52034L,
9859552035L,52036L,52037L,52038L,52039L,52040L,52041L,52042L,52043L,52044L,
9859652045L,52046L,52047L,52048L,52049L,52050L,52051L,52052L,52053L,52054L,
9859752055L,52056L,52057L,52058L,52059L,52060L,52061L,52062L,52063L,52064L,
9859852065L,52066L,52067L,52068L,52069L,52070L,52071L,52072L,52073L,52074L,
9859952075L,52076L,52077L,52078L,52079L,52080L,52081L,52082L,52083L,52084L,
9860052085L,52086L,52087L,52088L,52089L,52090L,52091L,52092L,52093L,52094L,
9860152095L,52096L,52097L,52098L,52099L,52100L,52101L,52102L,52103L,52104L,
9860252105L,52106L,52107L,52108L,52109L,52110L,52111L,52112L,52113L,52114L,
9860352115L,52116L,52117L,52118L,52119L,52120L,52121L,52122L,52123L,52124L,
9860452125L,52126L,52127L,52128L,52129L,52130L,52131L,52132L,52133L,52134L,
9860552135L,52136L,52137L,52138L,52139L,52140L,52141L,52142L,52143L,52144L,
9860652145L,52146L,52147L,52148L,52149L,52150L,52151L,52152L,52153L,52154L,
9860752155L,52156L,52157L,52158L,52159L,52160L,52161L,52162L,52163L,52164L,
9860852165L,52166L,52167L,52168L,52169L,52170L,52171L,52172L,52173L,52174L,
9860952175L,52176L,52177L,52178L,52179L,52180L,52181L,52182L,52183L,52184L,
9861052185L,52186L,52187L,52188L,52189L,52190L,52191L,52192L,52193L,52194L,
9861152195L,52196L,52197L,52198L,52199L,52200L,52201L,52202L,52203L,52204L,
9861252205L,52206L,52207L,52208L,52209L,52210L,52211L,52212L,52213L,52214L,
9861352215L,52216L,52217L,52218L,52219L,52220L,52221L,52222L,52223L,52224L,
9861452225L,52226L,52227L,52228L,52229L,52230L,52231L,52232L,52233L,52234L,
9861552235L,52236L,52237L,52238L,52239L,52240L,52241L,52242L,52243L,52244L,
9861652245L,52246L,52247L,52248L,52249L,52250L,52251L,52252L,52253L,52254L,
9861752255L,52256L,52257L,52258L,52259L,52260L,52261L,52262L,52263L,52264L,
9861852265L,52266L,52267L,52268L,52269L,52270L,52271L,52272L,52273L,52274L,
9861952275L,52276L,52277L,52278L,52279L,52280L,52281L,52282L,52283L,52284L,
9862052285L,52286L,52287L,52288L,52289L,52290L,52291L,52292L,52293L,52294L,
9862152295L,52296L,52297L,52298L,52299L,52300L,52301L,52302L,52303L,52304L,
9862252305L,52306L,52307L,52308L,52309L,52310L,52311L,52312L,52313L,52314L,
9862352315L,52316L,52317L,52318L,52319L,52320L,52321L,52322L,52323L,52324L,
9862452325L,52326L,52327L,52328L,52329L,52330L,52331L,52332L,52333L,52334L,
9862552335L,52336L,52337L,52338L,52339L,52340L,52341L,52342L,52343L,52344L,
9862652345L,52346L,52347L,52348L,52349L,52350L,52351L,52352L,52353L,52354L,
9862752355L,52356L,52357L,52358L,52359L,52360L,52361L,52362L,52363L,52364L,
9862852365L,52366L,52367L,52368L,52369L,52370L,52371L,52372L,52373L,52374L,
9862952375L,52376L,52377L,52378L,52379L,52380L,52381L,52382L,52383L,52384L,
9863052385L,52386L,52387L,52388L,52389L,52390L,52391L,52392L,52393L,52394L,
9863152395L,52396L,52397L,52398L,52399L,52400L,52401L,52402L,52403L,52404L,
9863252405L,52406L,52407L,52408L,52409L,52410L,52411L,52412L,52413L,52414L,
9863352415L,52416L,52417L,52418L,52419L,52420L,52421L,52422L,52423L,52424L,
9863452425L,52426L,52427L,52428L,52429L,52430L,52431L,52432L,52433L,52434L,
9863552435L,52436L,52437L,52438L,52439L,52440L,52441L,52442L,52443L,52444L,
9863652445L,52446L,52447L,52448L,52449L,52450L,52451L,52452L,52453L,52454L,
9863752455L,52456L,52457L,52458L,52459L,52460L,52461L,52462L,52463L,52464L,
9863852465L,52466L,52467L,52468L,52469L,52470L,52471L,52472L,52473L,52474L,
9863952475L,52476L,52477L,52478L,52479L,52480L,52481L,52482L,52483L,52484L,
9864052485L,52486L,52487L,52488L,52489L,52490L,52491L,52492L,52493L,52494L,
9864152495L,52496L,52497L,52498L,52499L,52500L,52501L,52502L,52503L,52504L,
9864252505L,52506L,52507L,52508L,52509L,52510L,52511L,52512L,52513L,52514L,
9864352515L,52516L,52517L,52518L,52519L,52520L,52521L,52522L,52523L,52524L,
9864452525L,52526L,52527L,52528L,52529L,52530L,52531L,52532L,52533L,52534L,
9864552535L,52536L,52537L,52538L,52539L,52540L,52541L,52542L,52543L,52544L,
9864652545L,52546L,52547L,52548L,52549L,52550L,52551L,52552L,52553L,52554L,
9864752555L,52556L,52557L,52558L,52559L,52560L,52561L,52562L,52563L,52564L,
9864852565L,52566L,52567L,52568L,52569L,52570L,52571L,52572L,52573L,52574L,
9864952575L,52576L,52577L,52578L,52579L,52580L,52581L,52582L,52583L,52584L,
9865052585L,52586L,52587L,52588L,52589L,52590L,52591L,52592L,52593L,52594L,
9865152595L,52596L,52597L,52598L,52599L,52600L,52601L,52602L,52603L,52604L,
9865252605L,52606L,52607L,52608L,52609L,52610L,52611L,52612L,52613L,52614L,
9865352615L,52616L,52617L,52618L,52619L,52620L,52621L,52622L,52623L,52624L,
9865452625L,52626L,52627L,52628L,52629L,52630L,52631L,52632L,52633L,52634L,
9865552635L,52636L,52637L,52638L,52639L,52640L,52641L,52642L,52643L,52644L,
9865652645L,52646L,52647L,52648L,52649L,52650L,52651L,52652L,52653L,52654L,
9865752655L,52656L,52657L,52658L,52659L,52660L,52661L,52662L,52663L,52664L,
9865852665L,52666L,52667L,52668L,52669L,52670L,52671L,52672L,52673L,52674L,
9865952675L,52676L,52677L,52678L,52679L,52680L,52681L,52682L,52683L,52684L,
9866052685L,52686L,52687L,52688L,52689L,52690L,52691L,52692L,52693L,52694L,
9866152695L,52696L,52697L,52698L,52699L,52700L,52701L,52702L,52703L,52704L,
9866252705L,52706L,52707L,52708L,52709L,52710L,52711L,52712L,52713L,52714L,
9866352715L,52716L,52717L,52718L,52719L,52720L,52721L,52722L,52723L,52724L,
9866452725L,52726L,52727L,52728L,52729L,52730L,52731L,52732L,52733L,52734L,
9866552735L,52736L,52737L,52738L,52739L,52740L,52741L,52742L,52743L,52744L,
9866652745L,52746L,52747L,52748L,52749L,52750L,52751L,52752L,52753L,52754L,
9866752755L,52756L,52757L,52758L,52759L,52760L,52761L,52762L,52763L,52764L,
9866852765L,52766L,52767L,52768L,52769L,52770L,52771L,52772L,52773L,52774L,
9866952775L,52776L,52777L,52778L,52779L,52780L,52781L,52782L,52783L,52784L,
9867052785L,52786L,52787L,52788L,52789L,52790L,52791L,52792L,52793L,52794L,
9867152795L,52796L,52797L,52798L,52799L,52800L,52801L,52802L,52803L,52804L,
9867252805L,52806L,52807L,52808L,52809L,52810L,52811L,52812L,52813L,52814L,
9867352815L,52816L,52817L,52818L,52819L,52820L,52821L,52822L,52823L,52824L,
9867452825L,52826L,52827L,52828L,52829L,52830L,52831L,52832L,52833L,52834L,
9867552835L,52836L,52837L,52838L,52839L,52840L,52841L,52842L,52843L,52844L,
9867652845L,52846L,52847L,52848L,52849L,52850L,52851L,52852L,52853L,52854L,
9867752855L,52856L,52857L,52858L,52859L,52860L,52861L,52862L,52863L,52864L,
9867852865L,52866L,52867L,52868L,52869L,52870L,52871L,52872L,52873L,52874L,
9867952875L,52876L,52877L,52878L,52879L,52880L,52881L,52882L,52883L,52884L,
9868052885L,52886L,52887L,52888L,52889L,52890L,52891L,52892L,52893L,52894L,
9868152895L,52896L,52897L,52898L,52899L,52900L,52901L,52902L,52903L,52904L,
9868252905L,52906L,52907L,52908L,52909L,52910L,52911L,52912L,52913L,52914L,
9868352915L,52916L,52917L,52918L,52919L,52920L,52921L,52922L,52923L,52924L,
9868452925L,52926L,52927L,52928L,52929L,52930L,52931L,52932L,52933L,52934L,
9868552935L,52936L,52937L,52938L,52939L,52940L,52941L,52942L,52943L,52944L,
9868652945L,52946L,52947L,52948L,52949L,52950L,52951L,52952L,52953L,52954L,
9868752955L,52956L,52957L,52958L,52959L,52960L,52961L,52962L,52963L,52964L,
9868852965L,52966L,52967L,52968L,52969L,52970L,52971L,52972L,52973L,52974L,
9868952975L,52976L,52977L,52978L,52979L,52980L,52981L,52982L,52983L,52984L,
9869052985L,52986L,52987L,52988L,52989L,52990L,52991L,52992L,52993L,52994L,
9869152995L,52996L,52997L,52998L,52999L,53000L,53001L,53002L,53003L,53004L,
9869253005L,53006L,53007L,53008L,53009L,53010L,53011L,53012L,53013L,53014L,
9869353015L,53016L,53017L,53018L,53019L,53020L,53021L,53022L,53023L,53024L,
9869453025L,53026L,53027L,53028L,53029L,53030L,53031L,53032L,53033L,53034L,
9869553035L,53036L,53037L,53038L,53039L,53040L,53041L,53042L,53043L,53044L,
9869653045L,53046L,53047L,53048L,53049L,53050L,53051L,53052L,53053L,53054L,
9869753055L,53056L,53057L,53058L,53059L,53060L,53061L,53062L,53063L,53064L,
9869853065L,53066L,53067L,53068L,53069L,53070L,53071L,53072L,53073L,53074L,
9869953075L,53076L,53077L,53078L,53079L,53080L,53081L,53082L,53083L,53084L,
9870053085L,53086L,53087L,53088L,53089L,53090L,53091L,53092L,53093L,53094L,
9870153095L,53096L,53097L,53098L,53099L,53100L,53101L,53102L,53103L,53104L,
9870253105L,53106L,53107L,53108L,53109L,53110L,53111L,53112L,53113L,53114L,
9870353115L,53116L,53117L,53118L,53119L,53120L,53121L,53122L,53123L,53124L,
9870453125L,53126L,53127L,53128L,53129L,53130L,53131L,53132L,53133L,53134L,
9870553135L,53136L,53137L,53138L,53139L,53140L,53141L,53142L,53143L,53144L,
9870653145L,53146L,53147L,53148L,53149L,53150L,53151L,53152L,53153L,53154L,
9870753155L,53156L,53157L,53158L,53159L,53160L,53161L,53162L,53163L,53164L,
9870853165L,53166L,53167L,53168L,53169L,53170L,53171L,53172L,53173L,53174L,
9870953175L,53176L,53177L,53178L,53179L,53180L,53181L,53182L,53183L,53184L,
9871053185L,53186L,53187L,53188L,53189L,53190L,53191L,53192L,53193L,53194L,
9871153195L,53196L,53197L,53198L,53199L,53200L,53201L,53202L,53203L,53204L,
9871253205L,53206L,53207L,53208L,53209L,53210L,53211L,53212L,53213L,53214L,
9871353215L,53216L,53217L,53218L,53219L,53220L,53221L,53222L,53223L,53224L,
9871453225L,53226L,53227L,53228L,53229L,53230L,53231L,53232L,53233L,53234L,
9871553235L,53236L,53237L,53238L,53239L,53240L,53241L,53242L,53243L,53244L,
9871653245L,53246L,53247L,53248L,53249L,53250L,53251L,53252L,53253L,53254L,
9871753255L,53256L,53257L,53258L,53259L,53260L,53261L,53262L,53263L,53264L,
9871853265L,53266L,53267L,53268L,53269L,53270L,53271L,53272L,53273L,53274L,
9871953275L,53276L,53277L,53278L,53279L,53280L,53281L,53282L,53283L,53284L,
9872053285L,53286L,53287L,53288L,53289L,53290L,53291L,53292L,53293L,53294L,
9872153295L,53296L,53297L,53298L,53299L,53300L,53301L,53302L,53303L,53304L,
9872253305L,53306L,53307L,53308L,53309L,53310L,53311L,53312L,53313L,53314L,
9872353315L,53316L,53317L,53318L,53319L,53320L,53321L,53322L,53323L,53324L,
9872453325L,53326L,53327L,53328L,53329L,53330L,53331L,53332L,53333L,53334L,
9872553335L,53336L,53337L,53338L,53339L,53340L,53341L,53342L,53343L,53344L,
9872653345L,53346L,53347L,53348L,53349L,53350L,53351L,53352L,53353L,53354L,
9872753355L,53356L,53357L,53358L,53359L,53360L,53361L,53362L,53363L,53364L,
9872853365L,53366L,53367L,53368L,53369L,53370L,53371L,53372L,53373L,53374L,
9872953375L,53376L,53377L,53378L,53379L,53380L,53381L,53382L,53383L,53384L,
9873053385L,53386L,53387L,53388L,53389L,53390L,53391L,53392L,53393L,53394L,
9873153395L,53396L,53397L,53398L,53399L,53400L,53401L,53402L,53403L,53404L,
9873253405L,53406L,53407L,53408L,53409L,53410L,53411L,53412L,53413L,53414L,
9873353415L,53416L,53417L,53418L,53419L,53420L,53421L,53422L,53423L,53424L,
9873453425L,53426L,53427L,53428L,53429L,53430L,53431L,53432L,53433L,53434L,
9873553435L,53436L,53437L,53438L,53439L,53440L,53441L,53442L,53443L,53444L,
9873653445L,53446L,53447L,53448L,53449L,53450L,53451L,53452L,53453L,53454L,
9873753455L,53456L,53457L,53458L,53459L,53460L,53461L,53462L,53463L,53464L,
9873853465L,53466L,53467L,53468L,53469L,53470L,53471L,53472L,53473L,53474L,
9873953475L,53476L,53477L,53478L,53479L,53480L,53481L,53482L,53483L,53484L,
9874053485L,53486L,53487L,53488L,53489L,53490L,53491L,53492L,53493L,53494L,
9874153495L,53496L,53497L,53498L,53499L,53500L,53501L,53502L,53503L,53504L,
9874253505L,53506L,53507L,53508L,53509L,53510L,53511L,53512L,53513L,53514L,
9874353515L,53516L,53517L,53518L,53519L,53520L,53521L,53522L,53523L,53524L,
9874453525L,53526L,53527L,53528L,53529L,53530L,53531L,53532L,53533L,53534L,
9874553535L,53536L,53537L,53538L,53539L,53540L,53541L,53542L,53543L,53544L,
9874653545L,53546L,53547L,53548L,53549L,53550L,53551L,53552L,53553L,53554L,
9874753555L,53556L,53557L,53558L,53559L,53560L,53561L,53562L,53563L,53564L,
9874853565L,53566L,53567L,53568L,53569L,53570L,53571L,53572L,53573L,53574L,
9874953575L,53576L,53577L,53578L,53579L,53580L,53581L,53582L,53583L,53584L,
9875053585L,53586L,53587L,53588L,53589L,53590L,53591L,53592L,53593L,53594L,
9875153595L,53596L,53597L,53598L,53599L,53600L,53601L,53602L,53603L,53604L,
9875253605L,53606L,53607L,53608L,53609L,53610L,53611L,53612L,53613L,53614L,
9875353615L,53616L,53617L,53618L,53619L,53620L,53621L,53622L,53623L,53624L,
9875453625L,53626L,53627L,53628L,53629L,53630L,53631L,53632L,53633L,53634L,
9875553635L,53636L,53637L,53638L,53639L,53640L,53641L,53642L,53643L,53644L,
9875653645L,53646L,53647L,53648L,53649L,53650L,53651L,53652L,53653L,53654L,
9875753655L,53656L,53657L,53658L,53659L,53660L,53661L,53662L,53663L,53664L,
9875853665L,53666L,53667L,53668L,53669L,53670L,53671L,53672L,53673L,53674L,
9875953675L,53676L,53677L,53678L,53679L,53680L,53681L,53682L,53683L,53684L,
9876053685L,53686L,53687L,53688L,53689L,53690L,53691L,53692L,53693L,53694L,
9876153695L,53696L,53697L,53698L,53699L,53700L,53701L,53702L,53703L,53704L,
9876253705L,53706L,53707L,53708L,53709L,53710L,53711L,53712L,53713L,53714L,
9876353715L,53716L,53717L,53718L,53719L,53720L,53721L,53722L,53723L,53724L,
9876453725L,53726L,53727L,53728L,53729L,53730L,53731L,53732L,53733L,53734L,
9876553735L,53736L,53737L,53738L,53739L,53740L,53741L,53742L,53743L,53744L,
9876653745L,53746L,53747L,53748L,53749L,53750L,53751L,53752L,53753L,53754L,
9876753755L,53756L,53757L,53758L,53759L,53760L,53761L,53762L,53763L,53764L,
9876853765L,53766L,53767L,53768L,53769L,53770L,53771L,53772L,53773L,53774L,
9876953775L,53776L,53777L,53778L,53779L,53780L,53781L,53782L,53783L,53784L,
9877053785L,53786L,53787L,53788L,53789L,53790L,53791L,53792L,53793L,53794L,
9877153795L,53796L,53797L,53798L,53799L,53800L,53801L,53802L,53803L,53804L,
9877253805L,53806L,53807L,53808L,53809L,53810L,53811L,53812L,53813L,53814L,
9877353815L,53816L,53817L,53818L,53819L,53820L,53821L,53822L,53823L,53824L,
9877453825L,53826L,53827L,53828L,53829L,53830L,53831L,53832L,53833L,53834L,
9877553835L,53836L,53837L,53838L,53839L,53840L,53841L,53842L,53843L,53844L,
9877653845L,53846L,53847L,53848L,53849L,53850L,53851L,53852L,53853L,53854L,
9877753855L,53856L,53857L,53858L,53859L,53860L,53861L,53862L,53863L,53864L,
9877853865L,53866L,53867L,53868L,53869L,53870L,53871L,53872L,53873L,53874L,
9877953875L,53876L,53877L,53878L,53879L,53880L,53881L,53882L,53883L,53884L,
9878053885L,53886L,53887L,53888L,53889L,53890L,53891L,53892L,53893L,53894L,
9878153895L,53896L,53897L,53898L,53899L,53900L,53901L,53902L,53903L,53904L,
9878253905L,53906L,53907L,53908L,53909L,53910L,53911L,53912L,53913L,53914L,
9878353915L,53916L,53917L,53918L,53919L,53920L,53921L,53922L,53923L,53924L,
9878453925L,53926L,53927L,53928L,53929L,53930L,53931L,53932L,53933L,53934L,
9878553935L,53936L,53937L,53938L,53939L,53940L,53941L,53942L,53943L,53944L,
9878653945L,53946L,53947L,53948L,53949L,53950L,53951L,53952L,53953L,53954L,
9878753955L,53956L,53957L,53958L,53959L,53960L,53961L,53962L,53963L,53964L,
9878853965L,53966L,53967L,53968L,53969L,53970L,53971L,53972L,53973L,53974L,
9878953975L,53976L,53977L,53978L,53979L,53980L,53981L,53982L,53983L,53984L,
9879053985L,53986L,53987L,53988L,53989L,53990L,53991L,53992L,53993L,53994L,
9879153995L,53996L,53997L,53998L,53999L,54000L,54001L,54002L,54003L,54004L,
9879254005L,54006L,54007L,54008L,54009L,54010L,54011L,54012L,54013L,54014L,
9879354015L,54016L,54017L,54018L,54019L,54020L,54021L,54022L,54023L,54024L,
9879454025L,54026L,54027L,54028L,54029L,54030L,54031L,54032L,54033L,54034L,
9879554035L,54036L,54037L,54038L,54039L,54040L,54041L,54042L,54043L,54044L,
9879654045L,54046L,54047L,54048L,54049L,54050L,54051L,54052L,54053L,54054L,
9879754055L,54056L,54057L,54058L,54059L,54060L,54061L,54062L,54063L,54064L,
9879854065L,54066L,54067L,54068L,54069L,54070L,54071L,54072L,54073L,54074L,
9879954075L,54076L,54077L,54078L,54079L,54080L,54081L,54082L,54083L,54084L,
9880054085L,54086L,54087L,54088L,54089L,54090L,54091L,54092L,54093L,54094L,
9880154095L,54096L,54097L,54098L,54099L,54100L,54101L,54102L,54103L,54104L,
9880254105L,54106L,54107L,54108L,54109L,54110L,54111L,54112L,54113L,54114L,
9880354115L,54116L,54117L,54118L,54119L,54120L,54121L,54122L,54123L,54124L,
9880454125L,54126L,54127L,54128L,54129L,54130L,54131L,54132L,54133L,54134L,
9880554135L,54136L,54137L,54138L,54139L,54140L,54141L,54142L,54143L,54144L,
9880654145L,54146L,54147L,54148L,54149L,54150L,54151L,54152L,54153L,54154L,
9880754155L,54156L,54157L,54158L,54159L,54160L,54161L,54162L,54163L,54164L,
9880854165L,54166L,54167L,54168L,54169L,54170L,54171L,54172L,54173L,54174L,
9880954175L,54176L,54177L,54178L,54179L,54180L,54181L,54182L,54183L,54184L,
9881054185L,54186L,54187L,54188L,54189L,54190L,54191L,54192L,54193L,54194L,
9881154195L,54196L,54197L,54198L,54199L,54200L,54201L,54202L,54203L,54204L,
9881254205L,54206L,54207L,54208L,54209L,54210L,54211L,54212L,54213L,54214L,
9881354215L,54216L,54217L,54218L,54219L,54220L,54221L,54222L,54223L,54224L,
9881454225L,54226L,54227L,54228L,54229L,54230L,54231L,54232L,54233L,54234L,
9881554235L,54236L,54237L,54238L,54239L,54240L,54241L,54242L,54243L,54244L,
9881654245L,54246L,54247L,54248L,54249L,54250L,54251L,54252L,54253L,54254L,
9881754255L,54256L,54257L,54258L,54259L,54260L,54261L,54262L,54263L,54264L,
9881854265L,54266L,54267L,54268L,54269L,54270L,54271L,54272L,54273L,54274L,
9881954275L,54276L,54277L,54278L,54279L,54280L,54281L,54282L,54283L,54284L,
9882054285L,54286L,54287L,54288L,54289L,54290L,54291L,54292L,54293L,54294L,
9882154295L,54296L,54297L,54298L,54299L,54300L,54301L,54302L,54303L,54304L,
9882254305L,54306L,54307L,54308L,54309L,54310L,54311L,54312L,54313L,54314L,
9882354315L,54316L,54317L,54318L,54319L,54320L,54321L,54322L,54323L,54324L,
9882454325L,54326L,54327L,54328L,54329L,54330L,54331L,54332L,54333L,54334L,
9882554335L,54336L,54337L,54338L,54339L,54340L,54341L,54342L,54343L,54344L,
9882654345L,54346L,54347L,54348L,54349L,54350L,54351L,54352L,54353L,54354L,
9882754355L,54356L,54357L,54358L,54359L,54360L,54361L,54362L,54363L,54364L,
9882854365L,54366L,54367L,54368L,54369L,54370L,54371L,54372L,54373L,54374L,
9882954375L,54376L,54377L,54378L,54379L,54380L,54381L,54382L,54383L,54384L,
9883054385L,54386L,54387L,54388L,54389L,54390L,54391L,54392L,54393L,54394L,
9883154395L,54396L,54397L,54398L,54399L,54400L,54401L,54402L,54403L,54404L,
9883254405L,54406L,54407L,54408L,54409L,54410L,54411L,54412L,54413L,54414L,
9883354415L,54416L,54417L,54418L,54419L,54420L,54421L,54422L,54423L,54424L,
9883454425L,54426L,54427L,54428L,54429L,54430L,54431L,54432L,54433L,54434L,
9883554435L,54436L,54437L,54438L,54439L,54440L,54441L,54442L,54443L,54444L,
9883654445L,54446L,54447L,54448L,54449L,54450L,54451L,54452L,54453L,54454L,
9883754455L,54456L,54457L,54458L,54459L,54460L,54461L,54462L,54463L,54464L,
9883854465L,54466L,54467L,54468L,54469L,54470L,54471L,54472L,54473L,54474L,
9883954475L,54476L,54477L,54478L,54479L,54480L,54481L,54482L,54483L,54484L,
9884054485L,54486L,54487L,54488L,54489L,54490L,54491L,54492L,54493L,54494L,
9884154495L,54496L,54497L,54498L,54499L,54500L,54501L,54502L,54503L,54504L,
9884254505L,54506L,54507L,54508L,54509L,54510L,54511L,54512L,54513L,54514L,
9884354515L,54516L,54517L,54518L,54519L,54520L,54521L,54522L,54523L,54524L,
9884454525L,54526L,54527L,54528L,54529L,54530L,54531L,54532L,54533L,54534L,
9884554535L,54536L,54537L,54538L,54539L,54540L,54541L,54542L,54543L,54544L,
9884654545L,54546L,54547L,54548L,54549L,54550L,54551L,54552L,54553L,54554L,
9884754555L,54556L,54557L,54558L,54559L,54560L,54561L,54562L,54563L,54564L,
9884854565L,54566L,54567L,54568L,54569L,54570L,54571L,54572L,54573L,54574L,
9884954575L,54576L,54577L,54578L,54579L,54580L,54581L,54582L,54583L,54584L,
9885054585L,54586L,54587L,54588L,54589L,54590L,54591L,54592L,54593L,54594L,
9885154595L,54596L,54597L,54598L,54599L,54600L,54601L,54602L,54603L,54604L,
9885254605L,54606L,54607L,54608L,54609L,54610L,54611L,54612L,54613L,54614L,
9885354615L,54616L,54617L,54618L,54619L,54620L,54621L,54622L,54623L,54624L,
9885454625L,54626L,54627L,54628L,54629L,54630L,54631L,54632L,54633L,54634L,
9885554635L,54636L,54637L,54638L,54639L,54640L,54641L,54642L,54643L,54644L,
9885654645L,54646L,54647L,54648L,54649L,54650L,54651L,54652L,54653L,54654L,
9885754655L,54656L,54657L,54658L,54659L,54660L,54661L,54662L,54663L,54664L,
9885854665L,54666L,54667L,54668L,54669L,54670L,54671L,54672L,54673L,54674L,
9885954675L,54676L,54677L,54678L,54679L,54680L,54681L,54682L,54683L,54684L,
9886054685L,54686L,54687L,54688L,54689L,54690L,54691L,54692L,54693L,54694L,
9886154695L,54696L,54697L,54698L,54699L,54700L,54701L,54702L,54703L,54704L,
9886254705L,54706L,54707L,54708L,54709L,54710L,54711L,54712L,54713L,54714L,
9886354715L,54716L,54717L,54718L,54719L,54720L,54721L,54722L,54723L,54724L,
9886454725L,54726L,54727L,54728L,54729L,54730L,54731L,54732L,54733L,54734L,
9886554735L,54736L,54737L,54738L,54739L,54740L,54741L,54742L,54743L,54744L,
9886654745L,54746L,54747L,54748L,54749L,54750L,54751L,54752L,54753L,54754L,
9886754755L,54756L,54757L,54758L,54759L,54760L,54761L,54762L,54763L,54764L,
9886854765L,54766L,54767L,54768L,54769L,54770L,54771L,54772L,54773L,54774L,
9886954775L,54776L,54777L,54778L,54779L,54780L,54781L,54782L,54783L,54784L,
9887054785L,54786L,54787L,54788L,54789L,54790L,54791L,54792L,54793L,54794L,
9887154795L,54796L,54797L,54798L,54799L,54800L,54801L,54802L,54803L,54804L,
9887254805L,54806L,54807L,54808L,54809L,54810L,54811L,54812L,54813L,54814L,
9887354815L,54816L,54817L,54818L,54819L,54820L,54821L,54822L,54823L,54824L,
9887454825L,54826L,54827L,54828L,54829L,54830L,54831L,54832L,54833L,54834L,
9887554835L,54836L,54837L,54838L,54839L,54840L,54841L,54842L,54843L,54844L,
9887654845L,54846L,54847L,54848L,54849L,54850L,54851L,54852L,54853L,54854L,
9887754855L,54856L,54857L,54858L,54859L,54860L,54861L,54862L,54863L,54864L,
9887854865L,54866L,54867L,54868L,54869L,54870L,54871L,54872L,54873L,54874L,
9887954875L,54876L,54877L,54878L,54879L,54880L,54881L,54882L,54883L,54884L,
9888054885L,54886L,54887L,54888L,54889L,54890L,54891L,54892L,54893L,54894L,
9888154895L,54896L,54897L,54898L,54899L,54900L,54901L,54902L,54903L,54904L,
9888254905L,54906L,54907L,54908L,54909L,54910L,54911L,54912L,54913L,54914L,
9888354915L,54916L,54917L,54918L,54919L,54920L,54921L,54922L,54923L,54924L,
9888454925L,54926L,54927L,54928L,54929L,54930L,54931L,54932L,54933L,54934L,
9888554935L,54936L,54937L,54938L,54939L,54940L,54941L,54942L,54943L,54944L,
9888654945L,54946L,54947L,54948L,54949L,54950L,54951L,54952L,54953L,54954L,
9888754955L,54956L,54957L,54958L,54959L,54960L,54961L,54962L,54963L,54964L,
9888854965L,54966L,54967L,54968L,54969L,54970L,54971L,54972L,54973L,54974L,
9888954975L,54976L,54977L,54978L,54979L,54980L,54981L,54982L,54983L,54984L,
9889054985L,54986L,54987L,54988L,54989L,54990L,54991L,54992L,54993L,54994L,
9889154995L,54996L,54997L,54998L,54999L,55000L,55001L,55002L,55003L,55004L,
9889255005L,55006L,55007L,55008L,55009L,55010L,55011L,55012L,55013L,55014L,
9889355015L,55016L,55017L,55018L,55019L,55020L,55021L,55022L,55023L,55024L,
9889455025L,55026L,55027L,55028L,55029L,55030L,55031L,55032L,55033L,55034L,
9889555035L,55036L,55037L,55038L,55039L,55040L,55041L,55042L,55043L,55044L,
9889655045L,55046L,55047L,55048L,55049L,55050L,55051L,55052L,55053L,55054L,
9889755055L,55056L,55057L,55058L,55059L,55060L,55061L,55062L,55063L,55064L,
9889855065L,55066L,55067L,55068L,55069L,55070L,55071L,55072L,55073L,55074L,
9889955075L,55076L,55077L,55078L,55079L,55080L,55081L,55082L,55083L,55084L,
9890055085L,55086L,55087L,55088L,55089L,55090L,55091L,55092L,55093L,55094L,
9890155095L,55096L,55097L,55098L,55099L,55100L,55101L,55102L,55103L,55104L,
9890255105L,55106L,55107L,55108L,55109L,55110L,55111L,55112L,55113L,55114L,
9890355115L,55116L,55117L,55118L,55119L,55120L,55121L,55122L,55123L,55124L,
9890455125L,55126L,55127L,55128L,55129L,55130L,55131L,55132L,55133L,55134L,
9890555135L,55136L,55137L,55138L,55139L,55140L,55141L,55142L,55143L,55144L,
9890655145L,55146L,55147L,55148L,55149L,55150L,55151L,55152L,55153L,55154L,
9890755155L,55156L,55157L,55158L,55159L,55160L,55161L,55162L,55163L,55164L,
9890855165L,55166L,55167L,55168L,55169L,55170L,55171L,55172L,55173L,55174L,
9890955175L,55176L,55177L,55178L,55179L,55180L,55181L,55182L,55183L,55184L,
9891055185L,55186L,55187L,55188L,55189L,55190L,55191L,55192L,55193L,55194L,
9891155195L,55196L,55197L,55198L,55199L,55200L,55201L,55202L,55203L,55204L,
9891255205L,55206L,55207L,55208L,55209L,55210L,55211L,55212L,55213L,55214L,
9891355215L,55216L,55217L,55218L,55219L,55220L,55221L,55222L,55223L,55224L,
9891455225L,55226L,55227L,55228L,55229L,55230L,55231L,55232L,55233L,55234L,
9891555235L,55236L,55237L,55238L,55239L,55240L,55241L,55242L,55243L,55244L,
9891655245L,55246L,55247L,55248L,55249L,55250L,55251L,55252L,55253L,55254L,
9891755255L,55256L,55257L,55258L,55259L,55260L,55261L,55262L,55263L,55264L,
9891855265L,55266L,55267L,55268L,55269L,55270L,55271L,55272L,55273L,55274L,
9891955275L,55276L,55277L,55278L,55279L,55280L,55281L,55282L,55283L,55284L,
9892055285L,55286L,55287L,55288L,55289L,55290L,55291L,55292L,55293L,55294L,
9892155295L,55296L,55297L,55298L,55299L,55300L,55301L,55302L,55303L,55304L,
9892255305L,55306L,55307L,55308L,55309L,55310L,55311L,55312L,55313L,55314L,
9892355315L,55316L,55317L,55318L,55319L,55320L,55321L,55322L,55323L,55324L,
9892455325L,55326L,55327L,55328L,55329L,55330L,55331L,55332L,55333L,55334L,
9892555335L,55336L,55337L,55338L,55339L,55340L,55341L,55342L,55343L,55344L,
9892655345L,55346L,55347L,55348L,55349L,55350L,55351L,55352L,55353L,55354L,
9892755355L,55356L,55357L,55358L,55359L,55360L,55361L,55362L,55363L,55364L,
9892855365L,55366L,55367L,55368L,55369L,55370L,55371L,55372L,55373L,55374L,
9892955375L,55376L,55377L,55378L,55379L,55380L,55381L,55382L,55383L,55384L,
9893055385L,55386L,55387L,55388L,55389L,55390L,55391L,55392L,55393L,55394L,
9893155395L,55396L,55397L,55398L,55399L,55400L,55401L,55402L,55403L,55404L,
9893255405L,55406L,55407L,55408L,55409L,55410L,55411L,55412L,55413L,55414L,
9893355415L,55416L,55417L,55418L,55419L,55420L,55421L,55422L,55423L,55424L,
9893455425L,55426L,55427L,55428L,55429L,55430L,55431L,55432L,55433L,55434L,
9893555435L,55436L,55437L,55438L,55439L,55440L,55441L,55442L,55443L,55444L,
9893655445L,55446L,55447L,55448L,55449L,55450L,55451L,55452L,55453L,55454L,
9893755455L,55456L,55457L,55458L,55459L,55460L,55461L,55462L,55463L,55464L,
9893855465L,55466L,55467L,55468L,55469L,55470L,55471L,55472L,55473L,55474L,
9893955475L,55476L,55477L,55478L,55479L,55480L,55481L,55482L,55483L,55484L,
9894055485L,55486L,55487L,55488L,55489L,55490L,55491L,55492L,55493L,55494L,
9894155495L,55496L,55497L,55498L,55499L,55500L,55501L,55502L,55503L,55504L,
9894255505L,55506L,55507L,55508L,55509L,55510L,55511L,55512L,55513L,55514L,
9894355515L,55516L,55517L,55518L,55519L,55520L,55521L,55522L,55523L,55524L,
9894455525L,55526L,55527L,55528L,55529L,55530L,55531L,55532L,55533L,55534L,
9894555535L,55536L,55537L,55538L,55539L,55540L,55541L,55542L,55543L,55544L,
9894655545L,55546L,55547L,55548L,55549L,55550L,55551L,55552L,55553L,55554L,
9894755555L,55556L,55557L,55558L,55559L,55560L,55561L,55562L,55563L,55564L,
9894855565L,55566L,55567L,55568L,55569L,55570L,55571L,55572L,55573L,55574L,
9894955575L,55576L,55577L,55578L,55579L,55580L,55581L,55582L,55583L,55584L,
9895055585L,55586L,55587L,55588L,55589L,55590L,55591L,55592L,55593L,55594L,
9895155595L,55596L,55597L,55598L,55599L,55600L,55601L,55602L,55603L,55604L,
9895255605L,55606L,55607L,55608L,55609L,55610L,55611L,55612L,55613L,55614L,
9895355615L,55616L,55617L,55618L,55619L,55620L,55621L,55622L,55623L,55624L,
9895455625L,55626L,55627L,55628L,55629L,55630L,55631L,55632L,55633L,55634L,
9895555635L,55636L,55637L,55638L,55639L,55640L,55641L,55642L,55643L,55644L,
9895655645L,55646L,55647L,55648L,55649L,55650L,55651L,55652L,55653L,55654L,
9895755655L,55656L,55657L,55658L,55659L,55660L,55661L,55662L,55663L,55664L,
9895855665L,55666L,55667L,55668L,55669L,55670L,55671L,55672L,55673L,55674L,
9895955675L,55676L,55677L,55678L,55679L,55680L,55681L,55682L,55683L,55684L,
9896055685L,55686L,55687L,55688L,55689L,55690L,55691L,55692L,55693L,55694L,
9896155695L,55696L,55697L,55698L,55699L,55700L,55701L,55702L,55703L,55704L,
9896255705L,55706L,55707L,55708L,55709L,55710L,55711L,55712L,55713L,55714L,
9896355715L,55716L,55717L,55718L,55719L,55720L,55721L,55722L,55723L,55724L,
9896455725L,55726L,55727L,55728L,55729L,55730L,55731L,55732L,55733L,55734L,
9896555735L,55736L,55737L,55738L,55739L,55740L,55741L,55742L,55743L,55744L,
9896655745L,55746L,55747L,55748L,55749L,55750L,55751L,55752L,55753L,55754L,
9896755755L,55756L,55757L,55758L,55759L,55760L,55761L,55762L,55763L,55764L,
9896855765L,55766L,55767L,55768L,55769L,55770L,55771L,55772L,55773L,55774L,
9896955775L,55776L,55777L,55778L,55779L,55780L,55781L,55782L,55783L,55784L,
9897055785L,55786L,55787L,55788L,55789L,55790L,55791L,55792L,55793L,55794L,
9897155795L,55796L,55797L,55798L,55799L,55800L,55801L,55802L,55803L,55804L,
9897255805L,55806L,55807L,55808L,55809L,55810L,55811L,55812L,55813L,55814L,
9897355815L,55816L,55817L,55818L,55819L,55820L,55821L,55822L,55823L,55824L,
9897455825L,55826L,55827L,55828L,55829L,55830L,55831L,55832L,55833L,55834L,
9897555835L,55836L,55837L,55838L,55839L,55840L,55841L,55842L,55843L,55844L,
9897655845L,55846L,55847L,55848L,55849L,55850L,55851L,55852L,55853L,55854L,
9897755855L,55856L,55857L,55858L,55859L,55860L,55861L,55862L,55863L,55864L,
9897855865L,55866L,55867L,55868L,55869L,55870L,55871L,55872L,55873L,55874L,
9897955875L,55876L,55877L,55878L,55879L,55880L,55881L,55882L,55883L,55884L,
9898055885L,55886L,55887L,55888L,55889L,55890L,55891L,55892L,55893L,55894L,
9898155895L,55896L,55897L,55898L,55899L,55900L,55901L,55902L,55903L,55904L,
9898255905L,55906L,55907L,55908L,55909L,55910L,55911L,55912L,55913L,55914L,
9898355915L,55916L,55917L,55918L,55919L,55920L,55921L,55922L,55923L,55924L,
9898455925L,55926L,55927L,55928L,55929L,55930L,55931L,55932L,55933L,55934L,
9898555935L,55936L,55937L,55938L,55939L,55940L,55941L,55942L,55943L,55944L,
9898655945L,55946L,55947L,55948L,55949L,55950L,55951L,55952L,55953L,55954L,
9898755955L,55956L,55957L,55958L,55959L,55960L,55961L,55962L,55963L,55964L,
9898855965L,55966L,55967L,55968L,55969L,55970L,55971L,55972L,55973L,55974L,
9898955975L,55976L,55977L,55978L,55979L,55980L,55981L,55982L,55983L,55984L,
9899055985L,55986L,55987L,55988L,55989L,55990L,55991L,55992L,55993L,55994L,
9899155995L,55996L,55997L,55998L,55999L,56000L,56001L,56002L,56003L,56004L,
9899256005L,56006L,56007L,56008L,56009L,56010L,56011L,56012L,56013L,56014L,
9899356015L,56016L,56017L,56018L,56019L,56020L,56021L,56022L,56023L,56024L,
9899456025L,56026L,56027L,56028L,56029L,56030L,56031L,56032L,56033L,56034L,
9899556035L,56036L,56037L,56038L,56039L,56040L,56041L,56042L,56043L,56044L,
9899656045L,56046L,56047L,56048L,56049L,56050L,56051L,56052L,56053L,56054L,
9899756055L,56056L,56057L,56058L,56059L,56060L,56061L,56062L,56063L,56064L,
9899856065L,56066L,56067L,56068L,56069L,56070L,56071L,56072L,56073L,56074L,
9899956075L,56076L,56077L,56078L,56079L,56080L,56081L,56082L,56083L,56084L,
9900056085L,56086L,56087L,56088L,56089L,56090L,56091L,56092L,56093L,56094L,
9900156095L,56096L,56097L,56098L,56099L,56100L,56101L,56102L,56103L,56104L,
9900256105L,56106L,56107L,56108L,56109L,56110L,56111L,56112L,56113L,56114L,
9900356115L,56116L,56117L,56118L,56119L,56120L,56121L,56122L,56123L,56124L,
9900456125L,56126L,56127L,56128L,56129L,56130L,56131L,56132L,56133L,56134L,
9900556135L,56136L,56137L,56138L,56139L,56140L,56141L,56142L,56143L,56144L,
9900656145L,56146L,56147L,56148L,56149L,56150L,56151L,56152L,56153L,56154L,
9900756155L,56156L,56157L,56158L,56159L,56160L,56161L,56162L,56163L,56164L,
9900856165L,56166L,56167L,56168L,56169L,56170L,56171L,56172L,56173L,56174L,
9900956175L,56176L,56177L,56178L,56179L,56180L,56181L,56182L,56183L,56184L,
9901056185L,56186L,56187L,56188L,56189L,56190L,56191L,56192L,56193L,56194L,
9901156195L,56196L,56197L,56198L,56199L,56200L,56201L,56202L,56203L,56204L,
9901256205L,56206L,56207L,56208L,56209L,56210L,56211L,56212L,56213L,56214L,
9901356215L,56216L,56217L,56218L,56219L,56220L,56221L,56222L,56223L,56224L,
9901456225L,56226L,56227L,56228L,56229L,56230L,56231L,56232L,56233L,56234L,
9901556235L,56236L,56237L,56238L,56239L,56240L,56241L,56242L,56243L,56244L,
9901656245L,56246L,56247L,56248L,56249L,56250L,56251L,56252L,56253L,56254L,
9901756255L,56256L,56257L,56258L,56259L,56260L,56261L,56262L,56263L,56264L,
9901856265L,56266L,56267L,56268L,56269L,56270L,56271L,56272L,56273L,56274L,
9901956275L,56276L,56277L,56278L,56279L,56280L,56281L,56282L,56283L,56284L,
9902056285L,56286L,56287L,56288L,56289L,56290L,56291L,56292L,56293L,56294L,
9902156295L,56296L,56297L,56298L,56299L,56300L,56301L,56302L,56303L,56304L,
9902256305L,56306L,56307L,56308L,56309L,56310L,56311L,56312L,56313L,56314L,
9902356315L,56316L,56317L,56318L,56319L,56320L,56321L,56322L,56323L,56324L,
9902456325L,56326L,56327L,56328L,56329L,56330L,56331L,56332L,56333L,56334L,
9902556335L,56336L,56337L,56338L,56339L,56340L,56341L,56342L,56343L,56344L,
9902656345L,56346L,56347L,56348L,56349L,56350L,56351L,56352L,56353L,56354L,
9902756355L,56356L,56357L,56358L,56359L,56360L,56361L,56362L,56363L,56364L,
9902856365L,56366L,56367L,56368L,56369L,56370L,56371L,56372L,56373L,56374L,
9902956375L,56376L,56377L,56378L,56379L,56380L,56381L,56382L,56383L,56384L,
9903056385L,56386L,56387L,56388L,56389L,56390L,56391L,56392L,56393L,56394L,
9903156395L,56396L,56397L,56398L,56399L,56400L,56401L,56402L,56403L,56404L,
9903256405L,56406L,56407L,56408L,56409L,56410L,56411L,56412L,56413L,56414L,
9903356415L,56416L,56417L,56418L,56419L,56420L,56421L,56422L,56423L,56424L,
9903456425L,56426L,56427L,56428L,56429L,56430L,56431L,56432L,56433L,56434L,
9903556435L,56436L,56437L,56438L,56439L,56440L,56441L,56442L,56443L,56444L,
9903656445L,56446L,56447L,56448L,56449L,56450L,56451L,56452L,56453L,56454L,
9903756455L,56456L,56457L,56458L,56459L,56460L,56461L,56462L,56463L,56464L,
9903856465L,56466L,56467L,56468L,56469L,56470L,56471L,56472L,56473L,56474L,
9903956475L,56476L,56477L,56478L,56479L,56480L,56481L,56482L,56483L,56484L,
9904056485L,56486L,56487L,56488L,56489L,56490L,56491L,56492L,56493L,56494L,
9904156495L,56496L,56497L,56498L,56499L,56500L,56501L,56502L,56503L,56504L,
9904256505L,56506L,56507L,56508L,56509L,56510L,56511L,56512L,56513L,56514L,
9904356515L,56516L,56517L,56518L,56519L,56520L,56521L,56522L,56523L,56524L,
9904456525L,56526L,56527L,56528L,56529L,56530L,56531L,56532L,56533L,56534L,
9904556535L,56536L,56537L,56538L,56539L,56540L,56541L,56542L,56543L,56544L,
9904656545L,56546L,56547L,56548L,56549L,56550L,56551L,56552L,56553L,56554L,
9904756555L,56556L,56557L,56558L,56559L,56560L,56561L,56562L,56563L,56564L,
9904856565L,56566L,56567L,56568L,56569L,56570L,56571L,56572L,56573L,56574L,
9904956575L,56576L,56577L,56578L,56579L,56580L,56581L,56582L,56583L,56584L,
9905056585L,56586L,56587L,56588L,56589L,56590L,56591L,56592L,56593L,56594L,
9905156595L,56596L,56597L,56598L,56599L,56600L,56601L,56602L,56603L,56604L,
9905256605L,56606L,56607L,56608L,56609L,56610L,56611L,56612L,56613L,56614L,
9905356615L,56616L,56617L,56618L,56619L,56620L,56621L,56622L,56623L,56624L,
9905456625L,56626L,56627L,56628L,56629L,56630L,56631L,56632L,56633L,56634L,
9905556635L,56636L,56637L,56638L,56639L,56640L,56641L,56642L,56643L,56644L,
9905656645L,56646L,56647L,56648L,56649L,56650L,56651L,56652L,56653L,56654L,
9905756655L,56656L,56657L,56658L,56659L,56660L,56661L,56662L,56663L,56664L,
9905856665L,56666L,56667L,56668L,56669L,56670L,56671L,56672L,56673L,56674L,
9905956675L,56676L,56677L,56678L,56679L,56680L,56681L,56682L,56683L,56684L,
9906056685L,56686L,56687L,56688L,56689L,56690L,56691L,56692L,56693L,56694L,
9906156695L,56696L,56697L,56698L,56699L,56700L,56701L,56702L,56703L,56704L,
9906256705L,56706L,56707L,56708L,56709L,56710L,56711L,56712L,56713L,56714L,
9906356715L,56716L,56717L,56718L,56719L,56720L,56721L,56722L,56723L,56724L,
9906456725L,56726L,56727L,56728L,56729L,56730L,56731L,56732L,56733L,56734L,
9906556735L,56736L,56737L,56738L,56739L,56740L,56741L,56742L,56743L,56744L,
9906656745L,56746L,56747L,56748L,56749L,56750L,56751L,56752L,56753L,56754L,
9906756755L,56756L,56757L,56758L,56759L,56760L,56761L,56762L,56763L,56764L,
9906856765L,56766L,56767L,56768L,56769L,56770L,56771L,56772L,56773L,56774L,
9906956775L,56776L,56777L,56778L,56779L,56780L,56781L,56782L,56783L,56784L,
9907056785L,56786L,56787L,56788L,56789L,56790L,56791L,56792L,56793L,56794L,
9907156795L,56796L,56797L,56798L,56799L,56800L,56801L,56802L,56803L,56804L,
9907256805L,56806L,56807L,56808L,56809L,56810L,56811L,56812L,56813L,56814L,
9907356815L,56816L,56817L,56818L,56819L,56820L,56821L,56822L,56823L,56824L,
9907456825L,56826L,56827L,56828L,56829L,56830L,56831L,56832L,56833L,56834L,
9907556835L,56836L,56837L,56838L,56839L,56840L,56841L,56842L,56843L,56844L,
9907656845L,56846L,56847L,56848L,56849L,56850L,56851L,56852L,56853L,56854L,
9907756855L,56856L,56857L,56858L,56859L,56860L,56861L,56862L,56863L,56864L,
9907856865L,56866L,56867L,56868L,56869L,56870L,56871L,56872L,56873L,56874L,
9907956875L,56876L,56877L,56878L,56879L,56880L,56881L,56882L,56883L,56884L,
9908056885L,56886L,56887L,56888L,56889L,56890L,56891L,56892L,56893L,56894L,
9908156895L,56896L,56897L,56898L,56899L,56900L,56901L,56902L,56903L,56904L,
9908256905L,56906L,56907L,56908L,56909L,56910L,56911L,56912L,56913L,56914L,
9908356915L,56916L,56917L,56918L,56919L,56920L,56921L,56922L,56923L,56924L,
9908456925L,56926L,56927L,56928L,56929L,56930L,56931L,56932L,56933L,56934L,
9908556935L,56936L,56937L,56938L,56939L,56940L,56941L,56942L,56943L,56944L,
9908656945L,56946L,56947L,56948L,56949L,56950L,56951L,56952L,56953L,56954L,
9908756955L,56956L,56957L,56958L,56959L,56960L,56961L,56962L,56963L,56964L,
9908856965L,56966L,56967L,56968L,56969L,56970L,56971L,56972L,56973L,56974L,
9908956975L,56976L,56977L,56978L,56979L,56980L,56981L,56982L,56983L,56984L,
9909056985L,56986L,56987L,56988L,56989L,56990L,56991L,56992L,56993L,56994L,
9909156995L,56996L,56997L,56998L,56999L,57000L,57001L,57002L,57003L,57004L,
9909257005L,57006L,57007L,57008L,57009L,57010L,57011L,57012L,57013L,57014L,
9909357015L,57016L,57017L,57018L,57019L,57020L,57021L,57022L,57023L,57024L,
9909457025L,57026L,57027L,57028L,57029L,57030L,57031L,57032L,57033L,57034L,
9909557035L,57036L,57037L,57038L,57039L,57040L,57041L,57042L,57043L,57044L,
9909657045L,57046L,57047L,57048L,57049L,57050L,57051L,57052L,57053L,57054L,
9909757055L,57056L,57057L,57058L,57059L,57060L,57061L,57062L,57063L,57064L,
9909857065L,57066L,57067L,57068L,57069L,57070L,57071L,57072L,57073L,57074L,
9909957075L,57076L,57077L,57078L,57079L,57080L,57081L,57082L,57083L,57084L,
9910057085L,57086L,57087L,57088L,57089L,57090L,57091L,57092L,57093L,57094L,
9910157095L,57096L,57097L,57098L,57099L,57100L,57101L,57102L,57103L,57104L,
9910257105L,57106L,57107L,57108L,57109L,57110L,57111L,57112L,57113L,57114L,
9910357115L,57116L,57117L,57118L,57119L,57120L,57121L,57122L,57123L,57124L,
9910457125L,57126L,57127L,57128L,57129L,57130L,57131L,57132L,57133L,57134L,
9910557135L,57136L,57137L,57138L,57139L,57140L,57141L,57142L,57143L,57144L,
9910657145L,57146L,57147L,57148L,57149L,57150L,57151L,57152L,57153L,57154L,
9910757155L,57156L,57157L,57158L,57159L,57160L,57161L,57162L,57163L,57164L,
9910857165L,57166L,57167L,57168L,57169L,57170L,57171L,57172L,57173L,57174L,
9910957175L,57176L,57177L,57178L,57179L,57180L,57181L,57182L,57183L,57184L,
9911057185L,57186L,57187L,57188L,57189L,57190L,57191L,57192L,57193L,57194L,
9911157195L,57196L,57197L,57198L,57199L,57200L,57201L,57202L,57203L,57204L,
9911257205L,57206L,57207L,57208L,57209L,57210L,57211L,57212L,57213L,57214L,
9911357215L,57216L,57217L,57218L,57219L,57220L,57221L,57222L,57223L,57224L,
9911457225L,57226L,57227L,57228L,57229L,57230L,57231L,57232L,57233L,57234L,
9911557235L,57236L,57237L,57238L,57239L,57240L,57241L,57242L,57243L,57244L,
9911657245L,57246L,57247L,57248L,57249L,57250L,57251L,57252L,57253L,57254L,
9911757255L,57256L,57257L,57258L,57259L,57260L,57261L,57262L,57263L,57264L,
9911857265L,57266L,57267L,57268L,57269L,57270L,57271L,57272L,57273L,57274L,
9911957275L,57276L,57277L,57278L,57279L,57280L,57281L,57282L,57283L,57284L,
9912057285L,57286L,57287L,57288L,57289L,57290L,57291L,57292L,57293L,57294L,
9912157295L,57296L,57297L,57298L,57299L,57300L,57301L,57302L,57303L,57304L,
9912257305L,57306L,57307L,57308L,57309L,57310L,57311L,57312L,57313L,57314L,
9912357315L,57316L,57317L,57318L,57319L,57320L,57321L,57322L,57323L,57324L,
9912457325L,57326L,57327L,57328L,57329L,57330L,57331L,57332L,57333L,57334L,
9912557335L,57336L,57337L,57338L,57339L,57340L,57341L,57342L,57343L,57344L,
9912657345L,57346L,57347L,57348L,57349L,57350L,57351L,57352L,57353L,57354L,
9912757355L,57356L,57357L,57358L,57359L,57360L,57361L,57362L,57363L,57364L,
9912857365L,57366L,57367L,57368L,57369L,57370L,57371L,57372L,57373L,57374L,
9912957375L,57376L,57377L,57378L,57379L,57380L,57381L,57382L,57383L,57384L,
9913057385L,57386L,57387L,57388L,57389L,57390L,57391L,57392L,57393L,57394L,
9913157395L,57396L,57397L,57398L,57399L,57400L,57401L,57402L,57403L,57404L,
9913257405L,57406L,57407L,57408L,57409L,57410L,57411L,57412L,57413L,57414L,
9913357415L,57416L,57417L,57418L,57419L,57420L,57421L,57422L,57423L,57424L,
9913457425L,57426L,57427L,57428L,57429L,57430L,57431L,57432L,57433L,57434L,
9913557435L,57436L,57437L,57438L,57439L,57440L,57441L,57442L,57443L,57444L,
9913657445L,57446L,57447L,57448L,57449L,57450L,57451L,57452L,57453L,57454L,
9913757455L,57456L,57457L,57458L,57459L,57460L,57461L,57462L,57463L,57464L,
9913857465L,57466L,57467L,57468L,57469L,57470L,57471L,57472L,57473L,57474L,
9913957475L,57476L,57477L,57478L,57479L,57480L,57481L,57482L,57483L,57484L,
9914057485L,57486L,57487L,57488L,57489L,57490L,57491L,57492L,57493L,57494L,
9914157495L,57496L,57497L,57498L,57499L,57500L,57501L,57502L,57503L,57504L,
9914257505L,57506L,57507L,57508L,57509L,57510L,57511L,57512L,57513L,57514L,
9914357515L,57516L,57517L,57518L,57519L,57520L,57521L,57522L,57523L,57524L,
9914457525L,57526L,57527L,57528L,57529L,57530L,57531L,57532L,57533L,57534L,
9914557535L,57536L,57537L,57538L,57539L,57540L,57541L,57542L,57543L,57544L,
9914657545L,57546L,57547L,57548L,57549L,57550L,57551L,57552L,57553L,57554L,
9914757555L,57556L,57557L,57558L,57559L,57560L,57561L,57562L,57563L,57564L,
9914857565L,57566L,57567L,57568L,57569L,57570L,57571L,57572L,57573L,57574L,
9914957575L,57576L,57577L,57578L,57579L,57580L,57581L,57582L,57583L,57584L,
9915057585L,57586L,57587L,57588L,57589L,57590L,57591L,57592L,57593L,57594L,
9915157595L,57596L,57597L,57598L,57599L,57600L,57601L,57602L,57603L,57604L,
9915257605L,57606L,57607L,57608L,57609L,57610L,57611L,57612L,57613L,57614L,
9915357615L,57616L,57617L,57618L,57619L,57620L,57621L,57622L,57623L,57624L,
9915457625L,57626L,57627L,57628L,57629L,57630L,57631L,57632L,57633L,57634L,
9915557635L,57636L,57637L,57638L,57639L,57640L,57641L,57642L,57643L,57644L,
9915657645L,57646L,57647L,57648L,57649L,57650L,57651L,57652L,57653L,57654L,
9915757655L,57656L,57657L,57658L,57659L,57660L,57661L,57662L,57663L,57664L,
9915857665L,57666L,57667L,57668L,57669L,57670L,57671L,57672L,57673L,57674L,
9915957675L,57676L,57677L,57678L,57679L,57680L,57681L,57682L,57683L,57684L,
9916057685L,57686L,57687L,57688L,57689L,57690L,57691L,57692L,57693L,57694L,
9916157695L,57696L,57697L,57698L,57699L,57700L,57701L,57702L,57703L,57704L,
9916257705L,57706L,57707L,57708L,57709L,57710L,57711L,57712L,57713L,57714L,
9916357715L,57716L,57717L,57718L,57719L,57720L,57721L,57722L,57723L,57724L,
9916457725L,57726L,57727L,57728L,57729L,57730L,57731L,57732L,57733L,57734L,
9916557735L,57736L,57737L,57738L,57739L,57740L,57741L,57742L,57743L,57744L,
9916657745L,57746L,57747L,57748L,57749L,57750L,57751L,57752L,57753L,57754L,
9916757755L,57756L,57757L,57758L,57759L,57760L,57761L,57762L,57763L,57764L,
9916857765L,57766L,57767L,57768L,57769L,57770L,57771L,57772L,57773L,57774L,
9916957775L,57776L,57777L,57778L,57779L,57780L,57781L,57782L,57783L,57784L,
9917057785L,57786L,57787L,57788L,57789L,57790L,57791L,57792L,57793L,57794L,
9917157795L,57796L,57797L,57798L,57799L,57800L,57801L,57802L,57803L,57804L,
9917257805L,57806L,57807L,57808L,57809L,57810L,57811L,57812L,57813L,57814L,
9917357815L,57816L,57817L,57818L,57819L,57820L,57821L,57822L,57823L,57824L,
9917457825L,57826L,57827L,57828L,57829L,57830L,57831L,57832L,57833L,57834L,
9917557835L,57836L,57837L,57838L,57839L,57840L,57841L,57842L,57843L,57844L,
9917657845L,57846L,57847L,57848L,57849L,57850L,57851L,57852L,57853L,57854L,
9917757855L,57856L,57857L,57858L,57859L,57860L,57861L,57862L,57863L,57864L,
9917857865L,57866L,57867L,57868L,57869L,57870L,57871L,57872L,57873L,57874L,
9917957875L,57876L,57877L,57878L,57879L,57880L,57881L,57882L,57883L,57884L,
9918057885L,57886L,57887L,57888L,57889L,57890L,57891L,57892L,57893L,57894L,
9918157895L,57896L,57897L,57898L,57899L,57900L,57901L,57902L,57903L,57904L,
9918257905L,57906L,57907L,57908L,57909L,57910L,57911L,57912L,57913L,57914L,
9918357915L,57916L,57917L,57918L,57919L,57920L,57921L,57922L,57923L,57924L,
9918457925L,57926L,57927L,57928L,57929L,57930L,57931L,57932L,57933L,57934L,
9918557935L,57936L,57937L,57938L,57939L,57940L,57941L,57942L,57943L,57944L,
9918657945L,57946L,57947L,57948L,57949L,57950L,57951L,57952L,57953L,57954L,
9918757955L,57956L,57957L,57958L,57959L,57960L,57961L,57962L,57963L,57964L,
9918857965L,57966L,57967L,57968L,57969L,57970L,57971L,57972L,57973L,57974L,
9918957975L,57976L,57977L,57978L,57979L,57980L,57981L,57982L,57983L,57984L,
9919057985L,57986L,57987L,57988L,57989L,57990L,57991L,57992L,57993L,57994L,
9919157995L,57996L,57997L,57998L,57999L,58000L,58001L,58002L,58003L,58004L,
9919258005L,58006L,58007L,58008L,58009L,58010L,58011L,58012L,58013L,58014L,
9919358015L,58016L,58017L,58018L,58019L,58020L,58021L,58022L,58023L,58024L,
9919458025L,58026L,58027L,58028L,58029L,58030L,58031L,58032L,58033L,58034L,
9919558035L,58036L,58037L,58038L,58039L,58040L,58041L,58042L,58043L,58044L,
9919658045L,58046L,58047L,58048L,58049L,58050L,58051L,58052L,58053L,58054L,
9919758055L,58056L,58057L,58058L,58059L,58060L,58061L,58062L,58063L,58064L,
9919858065L,58066L,58067L,58068L,58069L,58070L,58071L,58072L,58073L,58074L,
9919958075L,58076L,58077L,58078L,58079L,58080L,58081L,58082L,58083L,58084L,
9920058085L,58086L,58087L,58088L,58089L,58090L,58091L,58092L,58093L,58094L,
9920158095L,58096L,58097L,58098L,58099L,58100L,58101L,58102L,58103L,58104L,
9920258105L,58106L,58107L,58108L,58109L,58110L,58111L,58112L,58113L,58114L,
9920358115L,58116L,58117L,58118L,58119L,58120L,58121L,58122L,58123L,58124L,
9920458125L,58126L,58127L,58128L,58129L,58130L,58131L,58132L,58133L,58134L,
9920558135L,58136L,58137L,58138L,58139L,58140L,58141L,58142L,58143L,58144L,
9920658145L,58146L,58147L,58148L,58149L,58150L,58151L,58152L,58153L,58154L,
9920758155L,58156L,58157L,58158L,58159L,58160L,58161L,58162L,58163L,58164L,
9920858165L,58166L,58167L,58168L,58169L,58170L,58171L,58172L,58173L,58174L,
9920958175L,58176L,58177L,58178L,58179L,58180L,58181L,58182L,58183L,58184L,
9921058185L,58186L,58187L,58188L,58189L,58190L,58191L,58192L,58193L,58194L,
9921158195L,58196L,58197L,58198L,58199L,58200L,58201L,58202L,58203L,58204L,
9921258205L,58206L,58207L,58208L,58209L,58210L,58211L,58212L,58213L,58214L,
9921358215L,58216L,58217L,58218L,58219L,58220L,58221L,58222L,58223L,58224L,
9921458225L,58226L,58227L,58228L,58229L,58230L,58231L,58232L,58233L,58234L,
9921558235L,58236L,58237L,58238L,58239L,58240L,58241L,58242L,58243L,58244L,
9921658245L,58246L,58247L,58248L,58249L,58250L,58251L,58252L,58253L,58254L,
9921758255L,58256L,58257L,58258L,58259L,58260L,58261L,58262L,58263L,58264L,
9921858265L,58266L,58267L,58268L,58269L,58270L,58271L,58272L,58273L,58274L,
9921958275L,58276L,58277L,58278L,58279L,58280L,58281L,58282L,58283L,58284L,
9922058285L,58286L,58287L,58288L,58289L,58290L,58291L,58292L,58293L,58294L,
9922158295L,58296L,58297L,58298L,58299L,58300L,58301L,58302L,58303L,58304L,
9922258305L,58306L,58307L,58308L,58309L,58310L,58311L,58312L,58313L,58314L,
9922358315L,58316L,58317L,58318L,58319L,58320L,58321L,58322L,58323L,58324L,
9922458325L,58326L,58327L,58328L,58329L,58330L,58331L,58332L,58333L,58334L,
9922558335L,58336L,58337L,58338L,58339L,58340L,58341L,58342L,58343L,58344L,
9922658345L,58346L,58347L,58348L,58349L,58350L,58351L,58352L,58353L,58354L,
9922758355L,58356L,58357L,58358L,58359L,58360L,58361L,58362L,58363L,58364L,
9922858365L,58366L,58367L,58368L,58369L,58370L,58371L,58372L,58373L,58374L,
9922958375L,58376L,58377L,58378L,58379L,58380L,58381L,58382L,58383L,58384L,
9923058385L,58386L,58387L,58388L,58389L,58390L,58391L,58392L,58393L,58394L,
9923158395L,58396L,58397L,58398L,58399L,58400L,58401L,58402L,58403L,58404L,
9923258405L,58406L,58407L,58408L,58409L,58410L,58411L,58412L,58413L,58414L,
9923358415L,58416L,58417L,58418L,58419L,58420L,58421L,58422L,58423L,58424L,
9923458425L,58426L,58427L,58428L,58429L,58430L,58431L,58432L,58433L,58434L,
9923558435L,58436L,58437L,58438L,58439L,58440L,58441L,58442L,58443L,58444L,
9923658445L,58446L,58447L,58448L,58449L,58450L,58451L,58452L,58453L,58454L,
9923758455L,58456L,58457L,58458L,58459L,58460L,58461L,58462L,58463L,58464L,
9923858465L,58466L,58467L,58468L,58469L,58470L,58471L,58472L,58473L,58474L,
9923958475L,58476L,58477L,58478L,58479L,58480L,58481L,58482L,58483L,58484L,
9924058485L,58486L,58487L,58488L,58489L,58490L,58491L,58492L,58493L,58494L,
9924158495L,58496L,58497L,58498L,58499L,58500L,58501L,58502L,58503L,58504L,
9924258505L,58506L,58507L,58508L,58509L,58510L,58511L,58512L,58513L,58514L,
9924358515L,58516L,58517L,58518L,58519L,58520L,58521L,58522L,58523L,58524L,
9924458525L,58526L,58527L,58528L,58529L,58530L,58531L,58532L,58533L,58534L,
9924558535L,58536L,58537L,58538L,58539L,58540L,58541L,58542L,58543L,58544L,
9924658545L,58546L,58547L,58548L,58549L,58550L,58551L,58552L,58553L,58554L,
9924758555L,58556L,58557L,58558L,58559L,58560L,58561L,58562L,58563L,58564L,
9924858565L,58566L,58567L,58568L,58569L,58570L,58571L,58572L,58573L,58574L,
9924958575L,58576L,58577L,58578L,58579L,58580L,58581L,58582L,58583L,58584L,
9925058585L,58586L,58587L,58588L,58589L,58590L,58591L,58592L,58593L,58594L,
9925158595L,58596L,58597L,58598L,58599L,58600L,58601L,58602L,58603L,58604L,
9925258605L,58606L,58607L,58608L,58609L,58610L,58611L,58612L,58613L,58614L,
9925358615L,58616L,58617L,58618L,58619L,58620L,58621L,58622L,58623L,58624L,
9925458625L,58626L,58627L,58628L,58629L,58630L,58631L,58632L,58633L,58634L,
9925558635L,58636L,58637L,58638L,58639L,58640L,58641L,58642L,58643L,58644L,
9925658645L,58646L,58647L,58648L,58649L,58650L,58651L,58652L,58653L,58654L,
9925758655L,58656L,58657L,58658L,58659L,58660L,58661L,58662L,58663L,58664L,
9925858665L,58666L,58667L,58668L,58669L,58670L,58671L,58672L,58673L,58674L,
9925958675L,58676L,58677L,58678L,58679L,58680L,58681L,58682L,58683L,58684L,
9926058685L,58686L,58687L,58688L,58689L,58690L,58691L,58692L,58693L,58694L,
9926158695L,58696L,58697L,58698L,58699L,58700L,58701L,58702L,58703L,58704L,
9926258705L,58706L,58707L,58708L,58709L,58710L,58711L,58712L,58713L,58714L,
9926358715L,58716L,58717L,58718L,58719L,58720L,58721L,58722L,58723L,58724L,
9926458725L,58726L,58727L,58728L,58729L,58730L,58731L,58732L,58733L,58734L,
9926558735L,58736L,58737L,58738L,58739L,58740L,58741L,58742L,58743L,58744L,
9926658745L,58746L,58747L,58748L,58749L,58750L,58751L,58752L,58753L,58754L,
9926758755L,58756L,58757L,58758L,58759L,58760L,58761L,58762L,58763L,58764L,
9926858765L,58766L,58767L,58768L,58769L,58770L,58771L,58772L,58773L,58774L,
9926958775L,58776L,58777L,58778L,58779L,58780L,58781L,58782L,58783L,58784L,
9927058785L,58786L,58787L,58788L,58789L,58790L,58791L,58792L,58793L,58794L,
9927158795L,58796L,58797L,58798L,58799L,58800L,58801L,58802L,58803L,58804L,
9927258805L,58806L,58807L,58808L,58809L,58810L,58811L,58812L,58813L,58814L,
9927358815L,58816L,58817L,58818L,58819L,58820L,58821L,58822L,58823L,58824L,
9927458825L,58826L,58827L,58828L,58829L,58830L,58831L,58832L,58833L,58834L,
9927558835L,58836L,58837L,58838L,58839L,58840L,58841L,58842L,58843L,58844L,
9927658845L,58846L,58847L,58848L,58849L,58850L,58851L,58852L,58853L,58854L,
9927758855L,58856L,58857L,58858L,58859L,58860L,58861L,58862L,58863L,58864L,
9927858865L,58866L,58867L,58868L,58869L,58870L,58871L,58872L,58873L,58874L,
9927958875L,58876L,58877L,58878L,58879L,58880L,58881L,58882L,58883L,58884L,
9928058885L,58886L,58887L,58888L,58889L,58890L,58891L,58892L,58893L,58894L,
9928158895L,58896L,58897L,58898L,58899L,58900L,58901L,58902L,58903L,58904L,
9928258905L,58906L,58907L,58908L,58909L,58910L,58911L,58912L,58913L,58914L,
9928358915L,58916L,58917L,58918L,58919L,58920L,58921L,58922L,58923L,58924L,
9928458925L,58926L,58927L,58928L,58929L,58930L,58931L,58932L,58933L,58934L,
9928558935L,58936L,58937L,58938L,58939L,58940L,58941L,58942L,58943L,58944L,
9928658945L,58946L,58947L,58948L,58949L,58950L,58951L,58952L,58953L,58954L,
9928758955L,58956L,58957L,58958L,58959L,58960L,58961L,58962L,58963L,58964L,
9928858965L,58966L,58967L,58968L,58969L,58970L,58971L,58972L,58973L,58974L,
9928958975L,58976L,58977L,58978L,58979L,58980L,58981L,58982L,58983L,58984L,
9929058985L,58986L,58987L,58988L,58989L,58990L,58991L,58992L,58993L,58994L,
9929158995L,58996L,58997L,58998L,58999L,59000L,59001L,59002L,59003L,59004L,
9929259005L,59006L,59007L,59008L,59009L,59010L,59011L,59012L,59013L,59014L,
9929359015L,59016L,59017L,59018L,59019L,59020L,59021L,59022L,59023L,59024L,
9929459025L,59026L,59027L,59028L,59029L,59030L,59031L,59032L,59033L,59034L,
9929559035L,59036L,59037L,59038L,59039L,59040L,59041L,59042L,59043L,59044L,
9929659045L,59046L,59047L,59048L,59049L,59050L,59051L,59052L,59053L,59054L,
9929759055L,59056L,59057L,59058L,59059L,59060L,59061L,59062L,59063L,59064L,
9929859065L,59066L,59067L,59068L,59069L,59070L,59071L,59072L,59073L,59074L,
9929959075L,59076L,59077L,59078L,59079L,59080L,59081L,59082L,59083L,59084L,
9930059085L,59086L,59087L,59088L,59089L,59090L,59091L,59092L,59093L,59094L,
9930159095L,59096L,59097L,59098L,59099L,59100L,59101L,59102L,59103L,59104L,
9930259105L,59106L,59107L,59108L,59109L,59110L,59111L,59112L,59113L,59114L,
9930359115L,59116L,59117L,59118L,59119L,59120L,59121L,59122L,59123L,59124L,
9930459125L,59126L,59127L,59128L,59129L,59130L,59131L,59132L,59133L,59134L,
9930559135L,59136L,59137L,59138L,59139L,59140L,59141L,59142L,59143L,59144L,
9930659145L,59146L,59147L,59148L,59149L,59150L,59151L,59152L,59153L,59154L,
9930759155L,59156L,59157L,59158L,59159L,59160L,59161L,59162L,59163L,59164L,
9930859165L,59166L,59167L,59168L,59169L,59170L,59171L,59172L,59173L,59174L,
9930959175L,59176L,59177L,59178L,59179L,59180L,59181L,59182L,59183L,59184L,
9931059185L,59186L,59187L,59188L,59189L,59190L,59191L,59192L,59193L,59194L,
9931159195L,59196L,59197L,59198L,59199L,59200L,59201L,59202L,59203L,59204L,
9931259205L,59206L,59207L,59208L,59209L,59210L,59211L,59212L,59213L,59214L,
9931359215L,59216L,59217L,59218L,59219L,59220L,59221L,59222L,59223L,59224L,
9931459225L,59226L,59227L,59228L,59229L,59230L,59231L,59232L,59233L,59234L,
9931559235L,59236L,59237L,59238L,59239L,59240L,59241L,59242L,59243L,59244L,
9931659245L,59246L,59247L,59248L,59249L,59250L,59251L,59252L,59253L,59254L,
9931759255L,59256L,59257L,59258L,59259L,59260L,59261L,59262L,59263L,59264L,
9931859265L,59266L,59267L,59268L,59269L,59270L,59271L,59272L,59273L,59274L,
9931959275L,59276L,59277L,59278L,59279L,59280L,59281L,59282L,59283L,59284L,
9932059285L,59286L,59287L,59288L,59289L,59290L,59291L,59292L,59293L,59294L,
9932159295L,59296L,59297L,59298L,59299L,59300L,59301L,59302L,59303L,59304L,
9932259305L,59306L,59307L,59308L,59309L,59310L,59311L,59312L,59313L,59314L,
9932359315L,59316L,59317L,59318L,59319L,59320L,59321L,59322L,59323L,59324L,
9932459325L,59326L,59327L,59328L,59329L,59330L,59331L,59332L,59333L,59334L,
9932559335L,59336L,59337L,59338L,59339L,59340L,59341L,59342L,59343L,59344L,
9932659345L,59346L,59347L,59348L,59349L,59350L,59351L,59352L,59353L,59354L,
9932759355L,59356L,59357L,59358L,59359L,59360L,59361L,59362L,59363L,59364L,
9932859365L,59366L,59367L,59368L,59369L,59370L,59371L,59372L,59373L,59374L,
9932959375L,59376L,59377L,59378L,59379L,59380L,59381L,59382L,59383L,59384L,
9933059385L,59386L,59387L,59388L,59389L,59390L,59391L,59392L,59393L,59394L,
9933159395L,59396L,59397L,59398L,59399L,59400L,59401L,59402L,59403L,59404L,
9933259405L,59406L,59407L,59408L,59409L,59410L,59411L,59412L,59413L,59414L,
9933359415L,59416L,59417L,59418L,59419L,59420L,59421L,59422L,59423L,59424L,
9933459425L,59426L,59427L,59428L,59429L,59430L,59431L,59432L,59433L,59434L,
9933559435L,59436L,59437L,59438L,59439L,59440L,59441L,59442L,59443L,59444L,
9933659445L,59446L,59447L,59448L,59449L,59450L,59451L,59452L,59453L,59454L,
9933759455L,59456L,59457L,59458L,59459L,59460L,59461L,59462L,59463L,59464L,
9933859465L,59466L,59467L,59468L,59469L,59470L,59471L,59472L,59473L,59474L,
9933959475L,59476L,59477L,59478L,59479L,59480L,59481L,59482L,59483L,59484L,
9934059485L,59486L,59487L,59488L,59489L,59490L,59491L,59492L,59493L,59494L,
9934159495L,59496L,59497L,59498L,59499L,59500L,59501L,59502L,59503L,59504L,
9934259505L,59506L,59507L,59508L,59509L,59510L,59511L,59512L,59513L,59514L,
9934359515L,59516L,59517L,59518L,59519L,59520L,59521L,59522L,59523L,59524L,
9934459525L,59526L,59527L,59528L,59529L,59530L,59531L,59532L,59533L,59534L,
9934559535L,59536L,59537L,59538L,59539L,59540L,59541L,59542L,59543L,59544L,
9934659545L,59546L,59547L,59548L,59549L,59550L,59551L,59552L,59553L,59554L,
9934759555L,59556L,59557L,59558L,59559L,59560L,59561L,59562L,59563L,59564L,
9934859565L,59566L,59567L,59568L,59569L,59570L,59571L,59572L,59573L,59574L,
9934959575L,59576L,59577L,59578L,59579L,59580L,59581L,59582L,59583L,59584L,
9935059585L,59586L,59587L,59588L,59589L,59590L,59591L,59592L,59593L,59594L,
9935159595L,59596L,59597L,59598L,59599L,59600L,59601L,59602L,59603L,59604L,
9935259605L,59606L,59607L,59608L,59609L,59610L,59611L,59612L,59613L,59614L,
9935359615L,59616L,59617L,59618L,59619L,59620L,59621L,59622L,59623L,59624L,
9935459625L,59626L,59627L,59628L,59629L,59630L,59631L,59632L,59633L,59634L,
9935559635L,59636L,59637L,59638L,59639L,59640L,59641L,59642L,59643L,59644L,
9935659645L,59646L,59647L,59648L,59649L,59650L,59651L,59652L,59653L,59654L,
9935759655L,59656L,59657L,59658L,59659L,59660L,59661L,59662L,59663L,59664L,
9935859665L,59666L,59667L,59668L,59669L,59670L,59671L,59672L,59673L,59674L,
9935959675L,59676L,59677L,59678L,59679L,59680L,59681L,59682L,59683L,59684L,
9936059685L,59686L,59687L,59688L,59689L,59690L,59691L,59692L,59693L,59694L,
9936159695L,59696L,59697L,59698L,59699L,59700L,59701L,59702L,59703L,59704L,
9936259705L,59706L,59707L,59708L,59709L,59710L,59711L,59712L,59713L,59714L,
9936359715L,59716L,59717L,59718L,59719L,59720L,59721L,59722L,59723L,59724L,
9936459725L,59726L,59727L,59728L,59729L,59730L,59731L,59732L,59733L,59734L,
9936559735L,59736L,59737L,59738L,59739L,59740L,59741L,59742L,59743L,59744L,
9936659745L,59746L,59747L,59748L,59749L,59750L,59751L,59752L,59753L,59754L,
9936759755L,59756L,59757L,59758L,59759L,59760L,59761L,59762L,59763L,59764L,
9936859765L,59766L,59767L,59768L,59769L,59770L,59771L,59772L,59773L,59774L,
9936959775L,59776L,59777L,59778L,59779L,59780L,59781L,59782L,59783L,59784L,
9937059785L,59786L,59787L,59788L,59789L,59790L,59791L,59792L,59793L,59794L,
9937159795L,59796L,59797L,59798L,59799L,59800L,59801L,59802L,59803L,59804L,
9937259805L,59806L,59807L,59808L,59809L,59810L,59811L,59812L,59813L,59814L,
9937359815L,59816L,59817L,59818L,59819L,59820L,59821L,59822L,59823L,59824L,
9937459825L,59826L,59827L,59828L,59829L,59830L,59831L,59832L,59833L,59834L,
9937559835L,59836L,59837L,59838L,59839L,59840L,59841L,59842L,59843L,59844L,
9937659845L,59846L,59847L,59848L,59849L,59850L,59851L,59852L,59853L,59854L,
9937759855L,59856L,59857L,59858L,59859L,59860L,59861L,59862L,59863L,59864L,
9937859865L,59866L,59867L,59868L,59869L,59870L,59871L,59872L,59873L,59874L,
9937959875L,59876L,59877L,59878L,59879L,59880L,59881L,59882L,59883L,59884L,
9938059885L,59886L,59887L,59888L,59889L,59890L,59891L,59892L,59893L,59894L,
9938159895L,59896L,59897L,59898L,59899L,59900L,59901L,59902L,59903L,59904L,
9938259905L,59906L,59907L,59908L,59909L,59910L,59911L,59912L,59913L,59914L,
9938359915L,59916L,59917L,59918L,59919L,59920L,59921L,59922L,59923L,59924L,
9938459925L,59926L,59927L,59928L,59929L,59930L,59931L,59932L,59933L,59934L,
9938559935L,59936L,59937L,59938L,59939L,59940L,59941L,59942L,59943L,59944L,
9938659945L,59946L,59947L,59948L,59949L,59950L,59951L,59952L,59953L,59954L,
9938759955L,59956L,59957L,59958L,59959L,59960L,59961L,59962L,59963L,59964L,
9938859965L,59966L,59967L,59968L,59969L,59970L,59971L,59972L,59973L,59974L,
9938959975L,59976L,59977L,59978L,59979L,59980L,59981L,59982L,59983L,59984L,
9939059985L,59986L,59987L,59988L,59989L,59990L,59991L,59992L,59993L,59994L,
9939159995L,59996L,59997L,59998L,59999L,60000L,60001L,60002L,60003L,60004L,
9939260005L,60006L,60007L,60008L,60009L,60010L,60011L,60012L,60013L,60014L,
9939360015L,60016L,60017L,60018L,60019L,60020L,60021L,60022L,60023L,60024L,
9939460025L,60026L,60027L,60028L,60029L,60030L,60031L,60032L,60033L,60034L,
9939560035L,60036L,60037L,60038L,60039L,60040L,60041L,60042L,60043L,60044L,
9939660045L,60046L,60047L,60048L,60049L,60050L,60051L,60052L,60053L,60054L,
9939760055L,60056L,60057L,60058L,60059L,60060L,60061L,60062L,60063L,60064L,
9939860065L,60066L,60067L,60068L,60069L,60070L,60071L,60072L,60073L,60074L,
9939960075L,60076L,60077L,60078L,60079L,60080L,60081L,60082L,60083L,60084L,
9940060085L,60086L,60087L,60088L,60089L,60090L,60091L,60092L,60093L,60094L,
9940160095L,60096L,60097L,60098L,60099L,60100L,60101L,60102L,60103L,60104L,
9940260105L,60106L,60107L,60108L,60109L,60110L,60111L,60112L,60113L,60114L,
9940360115L,60116L,60117L,60118L,60119L,60120L,60121L,60122L,60123L,60124L,
9940460125L,60126L,60127L,60128L,60129L,60130L,60131L,60132L,60133L,60134L,
9940560135L,60136L,60137L,60138L,60139L,60140L,60141L,60142L,60143L,60144L,
9940660145L,60146L,60147L,60148L,60149L,60150L,60151L,60152L,60153L,60154L,
9940760155L,60156L,60157L,60158L,60159L,60160L,60161L,60162L,60163L,60164L,
9940860165L,60166L,60167L,60168L,60169L,60170L,60171L,60172L,60173L,60174L,
9940960175L,60176L,60177L,60178L,60179L,60180L,60181L,60182L,60183L,60184L,
9941060185L,60186L,60187L,60188L,60189L,60190L,60191L,60192L,60193L,60194L,
9941160195L,60196L,60197L,60198L,60199L,60200L,60201L,60202L,60203L,60204L,
9941260205L,60206L,60207L,60208L,60209L,60210L,60211L,60212L,60213L,60214L,
9941360215L,60216L,60217L,60218L,60219L,60220L,60221L,60222L,60223L,60224L,
9941460225L,60226L,60227L,60228L,60229L,60230L,60231L,60232L,60233L,60234L,
9941560235L,60236L,60237L,60238L,60239L,60240L,60241L,60242L,60243L,60244L,
9941660245L,60246L,60247L,60248L,60249L,60250L,60251L,60252L,60253L,60254L,
9941760255L,60256L,60257L,60258L,60259L,60260L,60261L,60262L,60263L,60264L,
9941860265L,60266L,60267L,60268L,60269L,60270L,60271L,60272L,60273L,60274L,
9941960275L,60276L,60277L,60278L,60279L,60280L,60281L,60282L,60283L,60284L,
9942060285L,60286L,60287L,60288L,60289L,60290L,60291L,60292L,60293L,60294L,
9942160295L,60296L,60297L,60298L,60299L,60300L,60301L,60302L,60303L,60304L,
9942260305L,60306L,60307L,60308L,60309L,60310L,60311L,60312L,60313L,60314L,
9942360315L,60316L,60317L,60318L,60319L,60320L,60321L,60322L,60323L,60324L,
9942460325L,60326L,60327L,60328L,60329L,60330L,60331L,60332L,60333L,60334L,
9942560335L,60336L,60337L,60338L,60339L,60340L,60341L,60342L,60343L,60344L,
9942660345L,60346L,60347L,60348L,60349L,60350L,60351L,60352L,60353L,60354L,
9942760355L,60356L,60357L,60358L,60359L,60360L,60361L,60362L,60363L,60364L,
9942860365L,60366L,60367L,60368L,60369L,60370L,60371L,60372L,60373L,60374L,
9942960375L,60376L,60377L,60378L,60379L,60380L,60381L,60382L,60383L,60384L,
9943060385L,60386L,60387L,60388L,60389L,60390L,60391L,60392L,60393L,60394L,
9943160395L,60396L,60397L,60398L,60399L,60400L,60401L,60402L,60403L,60404L,
9943260405L,60406L,60407L,60408L,60409L,60410L,60411L,60412L,60413L,60414L,
9943360415L,60416L,60417L,60418L,60419L,60420L,60421L,60422L,60423L,60424L,
9943460425L,60426L,60427L,60428L,60429L,60430L,60431L,60432L,60433L,60434L,
9943560435L,60436L,60437L,60438L,60439L,60440L,60441L,60442L,60443L,60444L,
9943660445L,60446L,60447L,60448L,60449L,60450L,60451L,60452L,60453L,60454L,
9943760455L,60456L,60457L,60458L,60459L,60460L,60461L,60462L,60463L,60464L,
9943860465L,60466L,60467L,60468L,60469L,60470L,60471L,60472L,60473L,60474L,
9943960475L,60476L,60477L,60478L,60479L,60480L,60481L,60482L,60483L,60484L,
9944060485L,60486L,60487L,60488L,60489L,60490L,60491L,60492L,60493L,60494L,
9944160495L,60496L,60497L,60498L,60499L,60500L,60501L,60502L,60503L,60504L,
9944260505L,60506L,60507L,60508L,60509L,60510L,60511L,60512L,60513L,60514L,
9944360515L,60516L,60517L,60518L,60519L,60520L,60521L,60522L,60523L,60524L,
9944460525L,60526L,60527L,60528L,60529L,60530L,60531L,60532L,60533L,60534L,
9944560535L,60536L,60537L,60538L,60539L,60540L,60541L,60542L,60543L,60544L,
9944660545L,60546L,60547L,60548L,60549L,60550L,60551L,60552L,60553L,60554L,
9944760555L,60556L,60557L,60558L,60559L,60560L,60561L,60562L,60563L,60564L,
9944860565L,60566L,60567L,60568L,60569L,60570L,60571L,60572L,60573L,60574L,
9944960575L,60576L,60577L,60578L,60579L,60580L,60581L,60582L,60583L,60584L,
9945060585L,60586L,60587L,60588L,60589L,60590L,60591L,60592L,60593L,60594L,
9945160595L,60596L,60597L,60598L,60599L,60600L,60601L,60602L,60603L,60604L,
9945260605L,60606L,60607L,60608L,60609L,60610L,60611L,60612L,60613L,60614L,
9945360615L,60616L,60617L,60618L,60619L,60620L,60621L,60622L,60623L,60624L,
9945460625L,60626L,60627L,60628L,60629L,60630L,60631L,60632L,60633L,60634L,
9945560635L,60636L,60637L,60638L,60639L,60640L,60641L,60642L,60643L,60644L,
9945660645L,60646L,60647L,60648L,60649L,60650L,60651L,60652L,60653L,60654L,
9945760655L,60656L,60657L,60658L,60659L,60660L,60661L,60662L,60663L,60664L,
9945860665L,60666L,60667L,60668L,60669L,60670L,60671L,60672L,60673L,60674L,
9945960675L,60676L,60677L,60678L,60679L,60680L,60681L,60682L,60683L,60684L,
9946060685L,60686L,60687L,60688L,60689L,60690L,60691L,60692L,60693L,60694L,
9946160695L,60696L,60697L,60698L,60699L,60700L,60701L,60702L,60703L,60704L,
9946260705L,60706L,60707L,60708L,60709L,60710L,60711L,60712L,60713L,60714L,
9946360715L,60716L,60717L,60718L,60719L,60720L,60721L,60722L,60723L,60724L,
9946460725L,60726L,60727L,60728L,60729L,60730L,60731L,60732L,60733L,60734L,
9946560735L,60736L,60737L,60738L,60739L,60740L,60741L,60742L,60743L,60744L,
9946660745L,60746L,60747L,60748L,60749L,60750L,60751L,60752L,60753L,60754L,
9946760755L,60756L,60757L,60758L,60759L,60760L,60761L,60762L,60763L,60764L,
9946860765L,60766L,60767L,60768L,60769L,60770L,60771L,60772L,60773L,60774L,
9946960775L,60776L,60777L,60778L,60779L,60780L,60781L,60782L,60783L,60784L,
9947060785L,60786L,60787L,60788L,60789L,60790L,60791L,60792L,60793L,60794L,
9947160795L,60796L,60797L,60798L,60799L,60800L,60801L,60802L,60803L,60804L,
9947260805L,60806L,60807L,60808L,60809L,60810L,60811L,60812L,60813L,60814L,
9947360815L,60816L,60817L,60818L,60819L,60820L,60821L,60822L,60823L,60824L,
9947460825L,60826L,60827L,60828L,60829L,60830L,60831L,60832L,60833L,60834L,
9947560835L,60836L,60837L,60838L,60839L,60840L,60841L,60842L,60843L,60844L,
9947660845L,60846L,60847L,60848L,60849L,60850L,60851L,60852L,60853L,60854L,
9947760855L,60856L,60857L,60858L,60859L,60860L,60861L,60862L,60863L,60864L,
9947860865L,60866L,60867L,60868L,60869L,60870L,60871L,60872L,60873L,60874L,
9947960875L,60876L,60877L,60878L,60879L,60880L,60881L,60882L,60883L,60884L,
9948060885L,60886L,60887L,60888L,60889L,60890L,60891L,60892L,60893L,60894L,
9948160895L,60896L,60897L,60898L,60899L,60900L,60901L,60902L,60903L,60904L,
9948260905L,60906L,60907L,60908L,60909L,60910L,60911L,60912L,60913L,60914L,
9948360915L,60916L,60917L,60918L,60919L,60920L,60921L,60922L,60923L,60924L,
9948460925L,60926L,60927L,60928L,60929L,60930L,60931L,60932L,60933L,60934L,
9948560935L,60936L,60937L,60938L,60939L,60940L,60941L,60942L,60943L,60944L,
9948660945L,60946L,60947L,60948L,60949L,60950L,60951L,60952L,60953L,60954L,
9948760955L,60956L,60957L,60958L,60959L,60960L,60961L,60962L,60963L,60964L,
9948860965L,60966L,60967L,60968L,60969L,60970L,60971L,60972L,60973L,60974L,
9948960975L,60976L,60977L,60978L,60979L,60980L,60981L,60982L,60983L,60984L,
9949060985L,60986L,60987L,60988L,60989L,60990L,60991L,60992L,60993L,60994L,
9949160995L,60996L,60997L,60998L,60999L,61000L,61001L,61002L,61003L,61004L,
9949261005L,61006L,61007L,61008L,61009L,61010L,61011L,61012L,61013L,61014L,
9949361015L,61016L,61017L,61018L,61019L,61020L,61021L,61022L,61023L,61024L,
9949461025L,61026L,61027L,61028L,61029L,61030L,61031L,61032L,61033L,61034L,
9949561035L,61036L,61037L,61038L,61039L,61040L,61041L,61042L,61043L,61044L,
9949661045L,61046L,61047L,61048L,61049L,61050L,61051L,61052L,61053L,61054L,
9949761055L,61056L,61057L,61058L,61059L,61060L,61061L,61062L,61063L,61064L,
9949861065L,61066L,61067L,61068L,61069L,61070L,61071L,61072L,61073L,61074L,
9949961075L,61076L,61077L,61078L,61079L,61080L,61081L,61082L,61083L,61084L,
9950061085L,61086L,61087L,61088L,61089L,61090L,61091L,61092L,61093L,61094L,
9950161095L,61096L,61097L,61098L,61099L,61100L,61101L,61102L,61103L,61104L,
9950261105L,61106L,61107L,61108L,61109L,61110L,61111L,61112L,61113L,61114L,
9950361115L,61116L,61117L,61118L,61119L,61120L,61121L,61122L,61123L,61124L,
9950461125L,61126L,61127L,61128L,61129L,61130L,61131L,61132L,61133L,61134L,
9950561135L,61136L,61137L,61138L,61139L,61140L,61141L,61142L,61143L,61144L,
9950661145L,61146L,61147L,61148L,61149L,61150L,61151L,61152L,61153L,61154L,
9950761155L,61156L,61157L,61158L,61159L,61160L,61161L,61162L,61163L,61164L,
9950861165L,61166L,61167L,61168L,61169L,61170L,61171L,61172L,61173L,61174L,
9950961175L,61176L,61177L,61178L,61179L,61180L,61181L,61182L,61183L,61184L,
9951061185L,61186L,61187L,61188L,61189L,61190L,61191L,61192L,61193L,61194L,
9951161195L,61196L,61197L,61198L,61199L,61200L,61201L,61202L,61203L,61204L,
9951261205L,61206L,61207L,61208L,61209L,61210L,61211L,61212L,61213L,61214L,
9951361215L,61216L,61217L,61218L,61219L,61220L,61221L,61222L,61223L,61224L,
9951461225L,61226L,61227L,61228L,61229L,61230L,61231L,61232L,61233L,61234L,
9951561235L,61236L,61237L,61238L,61239L,61240L,61241L,61242L,61243L,61244L,
9951661245L,61246L,61247L,61248L,61249L,61250L,61251L,61252L,61253L,61254L,
9951761255L,61256L,61257L,61258L,61259L,61260L,61261L,61262L,61263L,61264L,
9951861265L,61266L,61267L,61268L,61269L,61270L,61271L,61272L,61273L,61274L,
9951961275L,61276L,61277L,61278L,61279L,61280L,61281L,61282L,61283L,61284L,
9952061285L,61286L,61287L,61288L,61289L,61290L,61291L,61292L,61293L,61294L,
9952161295L,61296L,61297L,61298L,61299L,61300L,61301L,61302L,61303L,61304L,
9952261305L,61306L,61307L,61308L,61309L,61310L,61311L,61312L,61313L,61314L,
9952361315L,61316L,61317L,61318L,61319L,61320L,61321L,61322L,61323L,61324L,
9952461325L,61326L,61327L,61328L,61329L,61330L,61331L,61332L,61333L,61334L,
9952561335L,61336L,61337L,61338L,61339L,61340L,61341L,61342L,61343L,61344L,
9952661345L,61346L,61347L,61348L,61349L,61350L,61351L,61352L,61353L,61354L,
9952761355L,61356L,61357L,61358L,61359L,61360L,61361L,61362L,61363L,61364L,
9952861365L,61366L,61367L,61368L,61369L,61370L,61371L,61372L,61373L,61374L,
9952961375L,61376L,61377L,61378L,61379L,61380L,61381L,61382L,61383L,61384L,
9953061385L,61386L,61387L,61388L,61389L,61390L,61391L,61392L,61393L,61394L,
9953161395L,61396L,61397L,61398L,61399L,61400L,61401L,61402L,61403L,61404L,
9953261405L,61406L,61407L,61408L,61409L,61410L,61411L,61412L,61413L,61414L,
9953361415L,61416L,61417L,61418L,61419L,61420L,61421L,61422L,61423L,61424L,
9953461425L,61426L,61427L,61428L,61429L,61430L,61431L,61432L,61433L,61434L,
9953561435L,61436L,61437L,61438L,61439L,61440L,61441L,61442L,61443L,61444L,
9953661445L,61446L,61447L,61448L,61449L,61450L,61451L,61452L,61453L,61454L,
9953761455L,61456L,61457L,61458L,61459L,61460L,61461L,61462L,61463L,61464L,
9953861465L,61466L,61467L,61468L,61469L,61470L,61471L,61472L,61473L,61474L,
9953961475L,61476L,61477L,61478L,61479L,61480L,61481L,61482L,61483L,61484L,
9954061485L,61486L,61487L,61488L,61489L,61490L,61491L,61492L,61493L,61494L,
9954161495L,61496L,61497L,61498L,61499L,61500L,61501L,61502L,61503L,61504L,
9954261505L,61506L,61507L,61508L,61509L,61510L,61511L,61512L,61513L,61514L,
9954361515L,61516L,61517L,61518L,61519L,61520L,61521L,61522L,61523L,61524L,
9954461525L,61526L,61527L,61528L,61529L,61530L,61531L,61532L,61533L,61534L,
9954561535L,61536L,61537L,61538L,61539L,61540L,61541L,61542L,61543L,61544L,
9954661545L,61546L,61547L,61548L,61549L,61550L,61551L,61552L,61553L,61554L,
9954761555L,61556L,61557L,61558L,61559L,61560L,61561L,61562L,61563L,61564L,
9954861565L,61566L,61567L,61568L,61569L,61570L,61571L,61572L,61573L,61574L,
9954961575L,61576L,61577L,61578L,61579L,61580L,61581L,61582L,61583L,61584L,
9955061585L,61586L,61587L,61588L,61589L,61590L,61591L,61592L,61593L,61594L,
9955161595L,61596L,61597L,61598L,61599L,61600L,61601L,61602L,61603L,61604L,
9955261605L,61606L,61607L,61608L,61609L,61610L,61611L,61612L,61613L,61614L,
9955361615L,61616L,61617L,61618L,61619L,61620L,61621L,61622L,61623L,61624L,
9955461625L,61626L,61627L,61628L,61629L,61630L,61631L,61632L,61633L,61634L,
9955561635L,61636L,61637L,61638L,61639L,61640L,61641L,61642L,61643L,61644L,
9955661645L,61646L,61647L,61648L,61649L,61650L,61651L,61652L,61653L,61654L,
9955761655L,61656L,61657L,61658L,61659L,61660L,61661L,61662L,61663L,61664L,
9955861665L,61666L,61667L,61668L,61669L,61670L,61671L,61672L,61673L,61674L,
9955961675L,61676L,61677L,61678L,61679L,61680L,61681L,61682L,61683L,61684L,
9956061685L,61686L,61687L,61688L,61689L,61690L,61691L,61692L,61693L,61694L,
9956161695L,61696L,61697L,61698L,61699L,61700L,61701L,61702L,61703L,61704L,
9956261705L,61706L,61707L,61708L,61709L,61710L,61711L,61712L,61713L,61714L,
9956361715L,61716L,61717L,61718L,61719L,61720L,61721L,61722L,61723L,61724L,
9956461725L,61726L,61727L,61728L,61729L,61730L,61731L,61732L,61733L,61734L,
9956561735L,61736L,61737L,61738L,61739L,61740L,61741L,61742L,61743L,61744L,
9956661745L,61746L,61747L,61748L,61749L,61750L,61751L,61752L,61753L,61754L,
9956761755L,61756L,61757L,61758L,61759L,61760L,61761L,61762L,61763L,61764L,
9956861765L,61766L,61767L,61768L,61769L,61770L,61771L,61772L,61773L,61774L,
9956961775L,61776L,61777L,61778L,61779L,61780L,61781L,61782L,61783L,61784L,
9957061785L,61786L,61787L,61788L,61789L,61790L,61791L,61792L,61793L,61794L,
9957161795L,61796L,61797L,61798L,61799L,61800L,61801L,61802L,61803L,61804L,
9957261805L,61806L,61807L,61808L,61809L,61810L,61811L,61812L,61813L,61814L,
9957361815L,61816L,61817L,61818L,61819L,61820L,61821L,61822L,61823L,61824L,
9957461825L,61826L,61827L,61828L,61829L,61830L,61831L,61832L,61833L,61834L,
9957561835L,61836L,61837L,61838L,61839L,61840L,61841L,61842L,61843L,61844L,
9957661845L,61846L,61847L,61848L,61849L,61850L,61851L,61852L,61853L,61854L,
9957761855L,61856L,61857L,61858L,61859L,61860L,61861L,61862L,61863L,61864L,
9957861865L,61866L,61867L,61868L,61869L,61870L,61871L,61872L,61873L,61874L,
9957961875L,61876L,61877L,61878L,61879L,61880L,61881L,61882L,61883L,61884L,
9958061885L,61886L,61887L,61888L,61889L,61890L,61891L,61892L,61893L,61894L,
9958161895L,61896L,61897L,61898L,61899L,61900L,61901L,61902L,61903L,61904L,
9958261905L,61906L,61907L,61908L,61909L,61910L,61911L,61912L,61913L,61914L,
9958361915L,61916L,61917L,61918L,61919L,61920L,61921L,61922L,61923L,61924L,
9958461925L,61926L,61927L,61928L,61929L,61930L,61931L,61932L,61933L,61934L,
9958561935L,61936L,61937L,61938L,61939L,61940L,61941L,61942L,61943L,61944L,
9958661945L,61946L,61947L,61948L,61949L,61950L,61951L,61952L,61953L,61954L,
9958761955L,61956L,61957L,61958L,61959L,61960L,61961L,61962L,61963L,61964L,
9958861965L,61966L,61967L,61968L,61969L,61970L,61971L,61972L,61973L,61974L,
9958961975L,61976L,61977L,61978L,61979L,61980L,61981L,61982L,61983L,61984L,
9959061985L,61986L,61987L,61988L,61989L,61990L,61991L,61992L,61993L,61994L,
9959161995L,61996L,61997L,61998L,61999L,62000L,62001L,62002L,62003L,62004L,
9959262005L,62006L,62007L,62008L,62009L,62010L,62011L,62012L,62013L,62014L,
9959362015L,62016L,62017L,62018L,62019L,62020L,62021L,62022L,62023L,62024L,
9959462025L,62026L,62027L,62028L,62029L,62030L,62031L,62032L,62033L,62034L,
9959562035L,62036L,62037L,62038L,62039L,62040L,62041L,62042L,62043L,62044L,
9959662045L,62046L,62047L,62048L,62049L,62050L,62051L,62052L,62053L,62054L,
9959762055L,62056L,62057L,62058L,62059L,62060L,62061L,62062L,62063L,62064L,
9959862065L,62066L,62067L,62068L,62069L,62070L,62071L,62072L,62073L,62074L,
9959962075L,62076L,62077L,62078L,62079L,62080L,62081L,62082L,62083L,62084L,
9960062085L,62086L,62087L,62088L,62089L,62090L,62091L,62092L,62093L,62094L,
9960162095L,62096L,62097L,62098L,62099L,62100L,62101L,62102L,62103L,62104L,
9960262105L,62106L,62107L,62108L,62109L,62110L,62111L,62112L,62113L,62114L,
9960362115L,62116L,62117L,62118L,62119L,62120L,62121L,62122L,62123L,62124L,
9960462125L,62126L,62127L,62128L,62129L,62130L,62131L,62132L,62133L,62134L,
9960562135L,62136L,62137L,62138L,62139L,62140L,62141L,62142L,62143L,62144L,
9960662145L,62146L,62147L,62148L,62149L,62150L,62151L,62152L,62153L,62154L,
9960762155L,62156L,62157L,62158L,62159L,62160L,62161L,62162L,62163L,62164L,
9960862165L,62166L,62167L,62168L,62169L,62170L,62171L,62172L,62173L,62174L,
9960962175L,62176L,62177L,62178L,62179L,62180L,62181L,62182L,62183L,62184L,
9961062185L,62186L,62187L,62188L,62189L,62190L,62191L,62192L,62193L,62194L,
9961162195L,62196L,62197L,62198L,62199L,62200L,62201L,62202L,62203L,62204L,
9961262205L,62206L,62207L,62208L,62209L,62210L,62211L,62212L,62213L,62214L,
9961362215L,62216L,62217L,62218L,62219L,62220L,62221L,62222L,62223L,62224L,
9961462225L,62226L,62227L,62228L,62229L,62230L,62231L,62232L,62233L,62234L,
9961562235L,62236L,62237L,62238L,62239L,62240L,62241L,62242L,62243L,62244L,
9961662245L,62246L,62247L,62248L,62249L,62250L,62251L,62252L,62253L,62254L,
9961762255L,62256L,62257L,62258L,62259L,62260L,62261L,62262L,62263L,62264L,
9961862265L,62266L,62267L,62268L,62269L,62270L,62271L,62272L,62273L,62274L,
9961962275L,62276L,62277L,62278L,62279L,62280L,62281L,62282L,62283L,62284L,
9962062285L,62286L,62287L,62288L,62289L,62290L,62291L,62292L,62293L,62294L,
9962162295L,62296L,62297L,62298L,62299L,62300L,62301L,62302L,62303L,62304L,
9962262305L,62306L,62307L,62308L,62309L,62310L,62311L,62312L,62313L,62314L,
9962362315L,62316L,62317L,62318L,62319L,62320L,62321L,62322L,62323L,62324L,
9962462325L,62326L,62327L,62328L,62329L,62330L,62331L,62332L,62333L,62334L,
9962562335L,62336L,62337L,62338L,62339L,62340L,62341L,62342L,62343L,62344L,
9962662345L,62346L,62347L,62348L,62349L,62350L,62351L,62352L,62353L,62354L,
9962762355L,62356L,62357L,62358L,62359L,62360L,62361L,62362L,62363L,62364L,
9962862365L,62366L,62367L,62368L,62369L,62370L,62371L,62372L,62373L,62374L,
9962962375L,62376L,62377L,62378L,62379L,62380L,62381L,62382L,62383L,62384L,
9963062385L,62386L,62387L,62388L,62389L,62390L,62391L,62392L,62393L,62394L,
9963162395L,62396L,62397L,62398L,62399L,62400L,62401L,62402L,62403L,62404L,
9963262405L,62406L,62407L,62408L,62409L,62410L,62411L,62412L,62413L,62414L,
9963362415L,62416L,62417L,62418L,62419L,62420L,62421L,62422L,62423L,62424L,
9963462425L,62426L,62427L,62428L,62429L,62430L,62431L,62432L,62433L,62434L,
9963562435L,62436L,62437L,62438L,62439L,62440L,62441L,62442L,62443L,62444L,
9963662445L,62446L,62447L,62448L,62449L,62450L,62451L,62452L,62453L,62454L,
9963762455L,62456L,62457L,62458L,62459L,62460L,62461L,62462L,62463L,62464L,
9963862465L,62466L,62467L,62468L,62469L,62470L,62471L,62472L,62473L,62474L,
9963962475L,62476L,62477L,62478L,62479L,62480L,62481L,62482L,62483L,62484L,
9964062485L,62486L,62487L,62488L,62489L,62490L,62491L,62492L,62493L,62494L,
9964162495L,62496L,62497L,62498L,62499L,62500L,62501L,62502L,62503L,62504L,
9964262505L,62506L,62507L,62508L,62509L,62510L,62511L,62512L,62513L,62514L,
9964362515L,62516L,62517L,62518L,62519L,62520L,62521L,62522L,62523L,62524L,
9964462525L,62526L,62527L,62528L,62529L,62530L,62531L,62532L,62533L,62534L,
9964562535L,62536L,62537L,62538L,62539L,62540L,62541L,62542L,62543L,62544L,
9964662545L,62546L,62547L,62548L,62549L,62550L,62551L,62552L,62553L,62554L,
9964762555L,62556L,62557L,62558L,62559L,62560L,62561L,62562L,62563L,62564L,
9964862565L,62566L,62567L,62568L,62569L,62570L,62571L,62572L,62573L,62574L,
9964962575L,62576L,62577L,62578L,62579L,62580L,62581L,62582L,62583L,62584L,
9965062585L,62586L,62587L,62588L,62589L,62590L,62591L,62592L,62593L,62594L,
9965162595L,62596L,62597L,62598L,62599L,62600L,62601L,62602L,62603L,62604L,
9965262605L,62606L,62607L,62608L,62609L,62610L,62611L,62612L,62613L,62614L,
9965362615L,62616L,62617L,62618L,62619L,62620L,62621L,62622L,62623L,62624L,
9965462625L,62626L,62627L,62628L,62629L,62630L,62631L,62632L,62633L,62634L,
9965562635L,62636L,62637L,62638L,62639L,62640L,62641L,62642L,62643L,62644L,
9965662645L,62646L,62647L,62648L,62649L,62650L,62651L,62652L,62653L,62654L,
9965762655L,62656L,62657L,62658L,62659L,62660L,62661L,62662L,62663L,62664L,
9965862665L,62666L,62667L,62668L,62669L,62670L,62671L,62672L,62673L,62674L,
9965962675L,62676L,62677L,62678L,62679L,62680L,62681L,62682L,62683L,62684L,
9966062685L,62686L,62687L,62688L,62689L,62690L,62691L,62692L,62693L,62694L,
9966162695L,62696L,62697L,62698L,62699L,62700L,62701L,62702L,62703L,62704L,
9966262705L,62706L,62707L,62708L,62709L,62710L,62711L,62712L,62713L,62714L,
9966362715L,62716L,62717L,62718L,62719L,62720L,62721L,62722L,62723L,62724L,
9966462725L,62726L,62727L,62728L,62729L,62730L,62731L,62732L,62733L,62734L,
9966562735L,62736L,62737L,62738L,62739L,62740L,62741L,62742L,62743L,62744L,
9966662745L,62746L,62747L,62748L,62749L,62750L,62751L,62752L,62753L,62754L,
9966762755L,62756L,62757L,62758L,62759L,62760L,62761L,62762L,62763L,62764L,
9966862765L,62766L,62767L,62768L,62769L,62770L,62771L,62772L,62773L,62774L,
9966962775L,62776L,62777L,62778L,62779L,62780L,62781L,62782L,62783L,62784L,
9967062785L,62786L,62787L,62788L,62789L,62790L,62791L,62792L,62793L,62794L,
9967162795L,62796L,62797L,62798L,62799L,62800L,62801L,62802L,62803L,62804L,
9967262805L,62806L,62807L,62808L,62809L,62810L,62811L,62812L,62813L,62814L,
9967362815L,62816L,62817L,62818L,62819L,62820L,62821L,62822L,62823L,62824L,
9967462825L,62826L,62827L,62828L,62829L,62830L,62831L,62832L,62833L,62834L,
9967562835L,62836L,62837L,62838L,62839L,62840L,62841L,62842L,62843L,62844L,
9967662845L,62846L,62847L,62848L,62849L,62850L,62851L,62852L,62853L,62854L,
9967762855L,62856L,62857L,62858L,62859L,62860L,62861L,62862L,62863L,62864L,
9967862865L,62866L,62867L,62868L,62869L,62870L,62871L,62872L,62873L,62874L,
9967962875L,62876L,62877L,62878L,62879L,62880L,62881L,62882L,62883L,62884L,
9968062885L,62886L,62887L,62888L,62889L,62890L,62891L,62892L,62893L,62894L,
9968162895L,62896L,62897L,62898L,62899L,62900L,62901L,62902L,62903L,62904L,
9968262905L,62906L,62907L,62908L,62909L,62910L,62911L,62912L,62913L,62914L,
9968362915L,62916L,62917L,62918L,62919L,62920L,62921L,62922L,62923L,62924L,
9968462925L,62926L,62927L,62928L,62929L,62930L,62931L,62932L,62933L,62934L,
9968562935L,62936L,62937L,62938L,62939L,62940L,62941L,62942L,62943L,62944L,
9968662945L,62946L,62947L,62948L,62949L,62950L,62951L,62952L,62953L,62954L,
9968762955L,62956L,62957L,62958L,62959L,62960L,62961L,62962L,62963L,62964L,
9968862965L,62966L,62967L,62968L,62969L,62970L,62971L,62972L,62973L,62974L,
9968962975L,62976L,62977L,62978L,62979L,62980L,62981L,62982L,62983L,62984L,
9969062985L,62986L,62987L,62988L,62989L,62990L,62991L,62992L,62993L,62994L,
9969162995L,62996L,62997L,62998L,62999L,63000L,63001L,63002L,63003L,63004L,
9969263005L,63006L,63007L,63008L,63009L,63010L,63011L,63012L,63013L,63014L,
9969363015L,63016L,63017L,63018L,63019L,63020L,63021L,63022L,63023L,63024L,
9969463025L,63026L,63027L,63028L,63029L,63030L,63031L,63032L,63033L,63034L,
9969563035L,63036L,63037L,63038L,63039L,63040L,63041L,63042L,63043L,63044L,
9969663045L,63046L,63047L,63048L,63049L,63050L,63051L,63052L,63053L,63054L,
9969763055L,63056L,63057L,63058L,63059L,63060L,63061L,63062L,63063L,63064L,
9969863065L,63066L,63067L,63068L,63069L,63070L,63071L,63072L,63073L,63074L,
9969963075L,63076L,63077L,63078L,63079L,63080L,63081L,63082L,63083L,63084L,
9970063085L,63086L,63087L,63088L,63089L,63090L,63091L,63092L,63093L,63094L,
9970163095L,63096L,63097L,63098L,63099L,63100L,63101L,63102L,63103L,63104L,
9970263105L,63106L,63107L,63108L,63109L,63110L,63111L,63112L,63113L,63114L,
9970363115L,63116L,63117L,63118L,63119L,63120L,63121L,63122L,63123L,63124L,
9970463125L,63126L,63127L,63128L,63129L,63130L,63131L,63132L,63133L,63134L,
9970563135L,63136L,63137L,63138L,63139L,63140L,63141L,63142L,63143L,63144L,
9970663145L,63146L,63147L,63148L,63149L,63150L,63151L,63152L,63153L,63154L,
9970763155L,63156L,63157L,63158L,63159L,63160L,63161L,63162L,63163L,63164L,
9970863165L,63166L,63167L,63168L,63169L,63170L,63171L,63172L,63173L,63174L,
9970963175L,63176L,63177L,63178L,63179L,63180L,63181L,63182L,63183L,63184L,
9971063185L,63186L,63187L,63188L,63189L,63190L,63191L,63192L,63193L,63194L,
9971163195L,63196L,63197L,63198L,63199L,63200L,63201L,63202L,63203L,63204L,
9971263205L,63206L,63207L,63208L,63209L,63210L,63211L,63212L,63213L,63214L,
9971363215L,63216L,63217L,63218L,63219L,63220L,63221L,63222L,63223L,63224L,
9971463225L,63226L,63227L,63228L,63229L,63230L,63231L,63232L,63233L,63234L,
9971563235L,63236L,63237L,63238L,63239L,63240L,63241L,63242L,63243L,63244L,
9971663245L,63246L,63247L,63248L,63249L,63250L,63251L,63252L,63253L,63254L,
9971763255L,63256L,63257L,63258L,63259L,63260L,63261L,63262L,63263L,63264L,
9971863265L,63266L,63267L,63268L,63269L,63270L,63271L,63272L,63273L,63274L,
9971963275L,63276L,63277L,63278L,63279L,63280L,63281L,63282L,63283L,63284L,
9972063285L,63286L,63287L,63288L,63289L,63290L,63291L,63292L,63293L,63294L,
9972163295L,63296L,63297L,63298L,63299L,63300L,63301L,63302L,63303L,63304L,
9972263305L,63306L,63307L,63308L,63309L,63310L,63311L,63312L,63313L,63314L,
9972363315L,63316L,63317L,63318L,63319L,63320L,63321L,63322L,63323L,63324L,
9972463325L,63326L,63327L,63328L,63329L,63330L,63331L,63332L,63333L,63334L,
9972563335L,63336L,63337L,63338L,63339L,63340L,63341L,63342L,63343L,63344L,
9972663345L,63346L,63347L,63348L,63349L,63350L,63351L,63352L,63353L,63354L,
9972763355L,63356L,63357L,63358L,63359L,63360L,63361L,63362L,63363L,63364L,
9972863365L,63366L,63367L,63368L,63369L,63370L,63371L,63372L,63373L,63374L,
9972963375L,63376L,63377L,63378L,63379L,63380L,63381L,63382L,63383L,63384L,
9973063385L,63386L,63387L,63388L,63389L,63390L,63391L,63392L,63393L,63394L,
9973163395L,63396L,63397L,63398L,63399L,63400L,63401L,63402L,63403L,63404L,
9973263405L,63406L,63407L,63408L,63409L,63410L,63411L,63412L,63413L,63414L,
9973363415L,63416L,63417L,63418L,63419L,63420L,63421L,63422L,63423L,63424L,
9973463425L,63426L,63427L,63428L,63429L,63430L,63431L,63432L,63433L,63434L,
9973563435L,63436L,63437L,63438L,63439L,63440L,63441L,63442L,63443L,63444L,
9973663445L,63446L,63447L,63448L,63449L,63450L,63451L,63452L,63453L,63454L,
9973763455L,63456L,63457L,63458L,63459L,63460L,63461L,63462L,63463L,63464L,
9973863465L,63466L,63467L,63468L,63469L,63470L,63471L,63472L,63473L,63474L,
9973963475L,63476L,63477L,63478L,63479L,63480L,63481L,63482L,63483L,63484L,
9974063485L,63486L,63487L,63488L,63489L,63490L,63491L,63492L,63493L,63494L,
9974163495L,63496L,63497L,63498L,63499L,63500L,63501L,63502L,63503L,63504L,
9974263505L,63506L,63507L,63508L,63509L,63510L,63511L,63512L,63513L,63514L,
9974363515L,63516L,63517L,63518L,63519L,63520L,63521L,63522L,63523L,63524L,
9974463525L,63526L,63527L,63528L,63529L,63530L,63531L,63532L,63533L,63534L,
9974563535L,63536L,63537L,63538L,63539L,63540L,63541L,63542L,63543L,63544L,
9974663545L,63546L,63547L,63548L,63549L,63550L,63551L,63552L,63553L,63554L,
9974763555L,63556L,63557L,63558L,63559L,63560L,63561L,63562L,63563L,63564L,
9974863565L,63566L,63567L,63568L,63569L,63570L,63571L,63572L,63573L,63574L,
9974963575L,63576L,63577L,63578L,63579L,63580L,63581L,63582L,63583L,63584L,
9975063585L,63586L,63587L,63588L,63589L,63590L,63591L,63592L,63593L,63594L,
9975163595L,63596L,63597L,63598L,63599L,63600L,63601L,63602L,63603L,63604L,
9975263605L,63606L,63607L,63608L,63609L,63610L,63611L,63612L,63613L,63614L,
9975363615L,63616L,63617L,63618L,63619L,63620L,63621L,63622L,63623L,63624L,
9975463625L,63626L,63627L,63628L,63629L,63630L,63631L,63632L,63633L,63634L,
9975563635L,63636L,63637L,63638L,63639L,63640L,63641L,63642L,63643L,63644L,
9975663645L,63646L,63647L,63648L,63649L,63650L,63651L,63652L,63653L,63654L,
9975763655L,63656L,63657L,63658L,63659L,63660L,63661L,63662L,63663L,63664L,
9975863665L,63666L,63667L,63668L,63669L,63670L,63671L,63672L,63673L,63674L,
9975963675L,63676L,63677L,63678L,63679L,63680L,63681L,63682L,63683L,63684L,
9976063685L,63686L,63687L,63688L,63689L,63690L,63691L,63692L,63693L,63694L,
9976163695L,63696L,63697L,63698L,63699L,63700L,63701L,63702L,63703L,63704L,
9976263705L,63706L,63707L,63708L,63709L,63710L,63711L,63712L,63713L,63714L,
9976363715L,63716L,63717L,63718L,63719L,63720L,63721L,63722L,63723L,63724L,
9976463725L,63726L,63727L,63728L,63729L,63730L,63731L,63732L,63733L,63734L,
9976563735L,63736L,63737L,63738L,63739L,63740L,63741L,63742L,63743L,63744L,
9976663745L,63746L,63747L,63748L,63749L,63750L,63751L,63752L,63753L,63754L,
9976763755L,63756L,63757L,63758L,63759L,63760L,63761L,63762L,63763L,63764L,
9976863765L,63766L,63767L,63768L,63769L,63770L,63771L,63772L,63773L,63774L,
9976963775L,63776L,63777L,63778L,63779L,63780L,63781L,63782L,63783L,63784L,
9977063785L,63786L,63787L,63788L,63789L,63790L,63791L,63792L,63793L,63794L,
9977163795L,63796L,63797L,63798L,63799L,63800L,63801L,63802L,63803L,63804L,
9977263805L,63806L,63807L,63808L,63809L,63810L,63811L,63812L,63813L,63814L,
9977363815L,63816L,63817L,63818L,63819L,63820L,63821L,63822L,63823L,63824L,
9977463825L,63826L,63827L,63828L,63829L,63830L,63831L,63832L,63833L,63834L,
9977563835L,63836L,63837L,63838L,63839L,63840L,63841L,63842L,63843L,63844L,
9977663845L,63846L,63847L,63848L,63849L,63850L,63851L,63852L,63853L,63854L,
9977763855L,63856L,63857L,63858L,63859L,63860L,63861L,63862L,63863L,63864L,
9977863865L,63866L,63867L,63868L,63869L,63870L,63871L,63872L,63873L,63874L,
9977963875L,63876L,63877L,63878L,63879L,63880L,63881L,63882L,63883L,63884L,
9978063885L,63886L,63887L,63888L,63889L,63890L,63891L,63892L,63893L,63894L,
9978163895L,63896L,63897L,63898L,63899L,63900L,63901L,63902L,63903L,63904L,
9978263905L,63906L,63907L,63908L,63909L,63910L,63911L,63912L,63913L,63914L,
9978363915L,63916L,63917L,63918L,63919L,63920L,63921L,63922L,63923L,63924L,
9978463925L,63926L,63927L,63928L,63929L,63930L,63931L,63932L,63933L,63934L,
9978563935L,63936L,63937L,63938L,63939L,63940L,63941L,63942L,63943L,63944L,
9978663945L,63946L,63947L,63948L,63949L,63950L,63951L,63952L,63953L,63954L,
9978763955L,63956L,63957L,63958L,63959L,63960L,63961L,63962L,63963L,63964L,
9978863965L,63966L,63967L,63968L,63969L,63970L,63971L,63972L,63973L,63974L,
9978963975L,63976L,63977L,63978L,63979L,63980L,63981L,63982L,63983L,63984L,
9979063985L,63986L,63987L,63988L,63989L,63990L,63991L,63992L,63993L,63994L,
9979163995L,63996L,63997L,63998L,63999L,64000L,64001L,64002L,64003L,64004L,
9979264005L,64006L,64007L,64008L,64009L,64010L,64011L,64012L,64013L,64014L,
9979364015L,64016L,64017L,64018L,64019L,64020L,64021L,64022L,64023L,64024L,
9979464025L,64026L,64027L,64028L,64029L,64030L,64031L,64032L,64033L,64034L,
9979564035L,64036L,64037L,64038L,64039L,64040L,64041L,64042L,64043L,64044L,
9979664045L,64046L,64047L,64048L,64049L,64050L,64051L,64052L,64053L,64054L,
9979764055L,64056L,64057L,64058L,64059L,64060L,64061L,64062L,64063L,64064L,
9979864065L,64066L,64067L,64068L,64069L,64070L,64071L,64072L,64073L,64074L,
9979964075L,64076L,64077L,64078L,64079L,64080L,64081L,64082L,64083L,64084L,
9980064085L,64086L,64087L,64088L,64089L,64090L,64091L,64092L,64093L,64094L,
9980164095L,64096L,64097L,64098L,64099L,64100L,64101L,64102L,64103L,64104L,
9980264105L,64106L,64107L,64108L,64109L,64110L,64111L,64112L,64113L,64114L,
9980364115L,64116L,64117L,64118L,64119L,64120L,64121L,64122L,64123L,64124L,
9980464125L,64126L,64127L,64128L,64129L,64130L,64131L,64132L,64133L,64134L,
9980564135L,64136L,64137L,64138L,64139L,64140L,64141L,64142L,64143L,64144L,
9980664145L,64146L,64147L,64148L,64149L,64150L,64151L,64152L,64153L,64154L,
9980764155L,64156L,64157L,64158L,64159L,64160L,64161L,64162L,64163L,64164L,
9980864165L,64166L,64167L,64168L,64169L,64170L,64171L,64172L,64173L,64174L,
9980964175L,64176L,64177L,64178L,64179L,64180L,64181L,64182L,64183L,64184L,
9981064185L,64186L,64187L,64188L,64189L,64190L,64191L,64192L,64193L,64194L,
9981164195L,64196L,64197L,64198L,64199L,64200L,64201L,64202L,64203L,64204L,
9981264205L,64206L,64207L,64208L,64209L,64210L,64211L,64212L,64213L,64214L,
9981364215L,64216L,64217L,64218L,64219L,64220L,64221L,64222L,64223L,64224L,
9981464225L,64226L,64227L,64228L,64229L,64230L,64231L,64232L,64233L,64234L,
9981564235L,64236L,64237L,64238L,64239L,64240L,64241L,64242L,64243L,64244L,
9981664245L,64246L,64247L,64248L,64249L,64250L,64251L,64252L,64253L,64254L,
9981764255L,64256L,64257L,64258L,64259L,64260L,64261L,64262L,64263L,64264L,
9981864265L,64266L,64267L,64268L,64269L,64270L,64271L,64272L,64273L,64274L,
9981964275L,64276L,64277L,64278L,64279L,64280L,64281L,64282L,64283L,64284L,
9982064285L,64286L,64287L,64288L,64289L,64290L,64291L,64292L,64293L,64294L,
9982164295L,64296L,64297L,64298L,64299L,64300L,64301L,64302L,64303L,64304L,
9982264305L,64306L,64307L,64308L,64309L,64310L,64311L,64312L,64313L,64314L,
9982364315L,64316L,64317L,64318L,64319L,64320L,64321L,64322L,64323L,64324L,
9982464325L,64326L,64327L,64328L,64329L,64330L,64331L,64332L,64333L,64334L,
9982564335L,64336L,64337L,64338L,64339L,64340L,64341L,64342L,64343L,64344L,
9982664345L,64346L,64347L,64348L,64349L,64350L,64351L,64352L,64353L,64354L,
9982764355L,64356L,64357L,64358L,64359L,64360L,64361L,64362L,64363L,64364L,
9982864365L,64366L,64367L,64368L,64369L,64370L,64371L,64372L,64373L,64374L,
9982964375L,64376L,64377L,64378L,64379L,64380L,64381L,64382L,64383L,64384L,
9983064385L,64386L,64387L,64388L,64389L,64390L,64391L,64392L,64393L,64394L,
9983164395L,64396L,64397L,64398L,64399L,64400L,64401L,64402L,64403L,64404L,
9983264405L,64406L,64407L,64408L,64409L,64410L,64411L,64412L,64413L,64414L,
9983364415L,64416L,64417L,64418L,64419L,64420L,64421L,64422L,64423L,64424L,
9983464425L,64426L,64427L,64428L,64429L,64430L,64431L,64432L,64433L,64434L,
9983564435L,64436L,64437L,64438L,64439L,64440L,64441L,64442L,64443L,64444L,
9983664445L,64446L,64447L,64448L,64449L,64450L,64451L,64452L,64453L,64454L,
9983764455L,64456L,64457L,64458L,64459L,64460L,64461L,64462L,64463L,64464L,
9983864465L,64466L,64467L,64468L,64469L,64470L,64471L,64472L,64473L,64474L,
9983964475L,64476L,64477L,64478L,64479L,64480L,64481L,64482L,64483L,64484L,
9984064485L,64486L,64487L,64488L,64489L,64490L,64491L,64492L,64493L,64494L,
9984164495L,64496L,64497L,64498L,64499L,64500L,64501L,64502L,64503L,64504L,
9984264505L,64506L,64507L,64508L,64509L,64510L,64511L,64512L,64513L,64514L,
9984364515L,64516L,64517L,64518L,64519L,64520L,64521L,64522L,64523L,64524L,
9984464525L,64526L,64527L,64528L,64529L,64530L,64531L,64532L,64533L,64534L,
9984564535L,64536L,64537L,64538L,64539L,64540L,64541L,64542L,64543L,64544L,
9984664545L,64546L,64547L,64548L,64549L,64550L,64551L,64552L,64553L,64554L,
9984764555L,64556L,64557L,64558L,64559L,64560L,64561L,64562L,64563L,64564L,
9984864565L,64566L,64567L,64568L,64569L,64570L,64571L,64572L,64573L,64574L,
9984964575L,64576L,64577L,64578L,64579L,64580L,64581L,64582L,64583L,64584L,
9985064585L,64586L,64587L,64588L,64589L,64590L,64591L,64592L,64593L,64594L,
9985164595L,64596L,64597L,64598L,64599L,64600L,64601L,64602L,64603L,64604L,
9985264605L,64606L,64607L,64608L,64609L,64610L,64611L,64612L,64613L,64614L,
9985364615L,64616L,64617L,64618L,64619L,64620L,64621L,64622L,64623L,64624L,
9985464625L,64626L,64627L,64628L,64629L,64630L,64631L,64632L,64633L,64634L,
9985564635L,64636L,64637L,64638L,64639L,64640L,64641L,64642L,64643L,64644L,
9985664645L,64646L,64647L,64648L,64649L,64650L,64651L,64652L,64653L,64654L,
9985764655L,64656L,64657L,64658L,64659L,64660L,64661L,64662L,64663L,64664L,
9985864665L,64666L,64667L,64668L,64669L,64670L,64671L,64672L,64673L,64674L,
9985964675L,64676L,64677L,64678L,64679L,64680L,64681L,64682L,64683L,64684L,
9986064685L,64686L,64687L,64688L,64689L,64690L,64691L,64692L,64693L,64694L,
9986164695L,64696L,64697L,64698L,64699L,64700L,64701L,64702L,64703L,64704L,
9986264705L,64706L,64707L,64708L,64709L,64710L,64711L,64712L,64713L,64714L,
9986364715L,64716L,64717L,64718L,64719L,64720L,64721L,64722L,64723L,64724L,
9986464725L,64726L,64727L,64728L,64729L,64730L,64731L,64732L,64733L,64734L,
9986564735L,64736L,64737L,64738L,64739L,64740L,64741L,64742L,64743L,64744L,
9986664745L,64746L,64747L,64748L,64749L,64750L,64751L,64752L,64753L,64754L,
9986764755L,64756L,64757L,64758L,64759L,64760L,64761L,64762L,64763L,64764L,
9986864765L,64766L,64767L,64768L,64769L,64770L,64771L,64772L,64773L,64774L,
9986964775L,64776L,64777L,64778L,64779L,64780L,64781L,64782L,64783L,64784L,
9987064785L,64786L,64787L,64788L,64789L,64790L,64791L,64792L,64793L,64794L,
9987164795L,64796L,64797L,64798L,64799L,64800L,64801L,64802L,64803L,64804L,
9987264805L,64806L,64807L,64808L,64809L,64810L,64811L,64812L,64813L,64814L,
9987364815L,64816L,64817L,64818L,64819L,64820L,64821L,64822L,64823L,64824L,
9987464825L,64826L,64827L,64828L,64829L,64830L,64831L,64832L,64833L,64834L,
9987564835L,64836L,64837L,64838L,64839L,64840L,64841L,64842L,64843L,64844L,
9987664845L,64846L,64847L,64848L,64849L,64850L,64851L,64852L,64853L,64854L,
9987764855L,64856L,64857L,64858L,64859L,64860L,64861L,64862L,64863L,64864L,
9987864865L,64866L,64867L,64868L,64869L,64870L,64871L,64872L,64873L,64874L,
9987964875L,64876L,64877L,64878L,64879L,64880L,64881L,64882L,64883L,64884L,
9988064885L,64886L,64887L,64888L,64889L,64890L,64891L,64892L,64893L,64894L,
9988164895L,64896L,64897L,64898L,64899L,64900L,64901L,64902L,64903L,64904L,
9988264905L,64906L,64907L,64908L,64909L,64910L,64911L,64912L,64913L,64914L,
9988364915L,64916L,64917L,64918L,64919L,64920L,64921L,64922L,64923L,64924L,
9988464925L,64926L,64927L,64928L,64929L,64930L,64931L,64932L,64933L,64934L,
9988564935L,64936L,64937L,64938L,64939L,64940L,64941L,64942L,64943L,64944L,
9988664945L,64946L,64947L,64948L,64949L,64950L,64951L,64952L,64953L,64954L,
9988764955L,64956L,64957L,64958L,64959L,64960L,64961L,64962L,64963L,64964L,
9988864965L,64966L,64967L,64968L,64969L,64970L,64971L,64972L,64973L,64974L,
9988964975L,64976L,64977L,64978L,64979L,64980L,64981L,64982L,64983L,64984L,
9989064985L,64986L,64987L,64988L,64989L,64990L,64991L,64992L,64993L,64994L,
9989164995L,64996L,64997L,64998L,64999L,65000L,65001L,65002L,65003L,65004L,
9989265005L,65006L,65007L,65008L,65009L,65010L,65011L,65012L,65013L,65014L,
9989365015L,65016L,65017L,65018L,65019L,65020L,65021L,65022L,65023L,65024L,
9989465025L,65026L,65027L,65028L,65029L,65030L,65031L,65032L,65033L,65034L,
9989565035L,65036L,65037L,65038L,65039L,65040L,65041L,65042L,65043L,65044L,
9989665045L,65046L,65047L,65048L,65049L,65050L,65051L,65052L,65053L,65054L,
9989765055L,65056L,65057L,65058L,65059L,65060L,65061L,65062L,65063L,65064L,
9989865065L,65066L,65067L,65068L,65069L,65070L,65071L,65072L,65073L,65074L,
9989965075L,65076L,65077L,65078L,65079L,65080L,65081L,65082L,65083L,65084L,
9990065085L,65086L,65087L,65088L,65089L,65090L,65091L,65092L,65093L,65094L,
9990165095L,65096L,65097L,65098L,65099L,65100L,65101L,65102L,65103L,65104L,
9990265105L,65106L,65107L,65108L,65109L,65110L,65111L,65112L,65113L,65114L,
9990365115L,65116L,65117L,65118L,65119L,65120L,65121L,65122L,65123L,65124L,
9990465125L,65126L,65127L,65128L,65129L,65130L,65131L,65132L,65133L,65134L,
9990565135L,65136L,65137L,65138L,65139L,65140L,65141L,65142L,65143L,65144L,
9990665145L,65146L,65147L,65148L,65149L,65150L,65151L,65152L,65153L,65154L,
9990765155L,65156L,65157L,65158L,65159L,65160L,65161L,65162L,65163L,65164L,
9990865165L,65166L,65167L,65168L,65169L,65170L,65171L,65172L,65173L,65174L,
9990965175L,65176L,65177L,65178L,65179L,65180L,65181L,65182L,65183L,65184L,
9991065185L,65186L,65187L,65188L,65189L,65190L,65191L,65192L,65193L,65194L,
9991165195L,65196L,65197L,65198L,65199L,65200L,65201L,65202L,65203L,65204L,
9991265205L,65206L,65207L,65208L,65209L,65210L,65211L,65212L,65213L,65214L,
9991365215L,65216L,65217L,65218L,65219L,65220L,65221L,65222L,65223L,65224L,
9991465225L,65226L,65227L,65228L,65229L,65230L,65231L,65232L,65233L,65234L,
9991565235L,65236L,65237L,65238L,65239L,65240L,65241L,65242L,65243L,65244L,
9991665245L,65246L,65247L,65248L,65249L,65250L,65251L,65252L,65253L,65254L,
9991765255L,65256L,65257L,65258L,65259L,65260L,65261L,65262L,65263L,65264L,
9991865265L,65266L,65267L,65268L,65269L,65270L,65271L,65272L,65273L,65274L,
9991965275L,65276L,65277L,65278L,65279L,65280L,65281L,65282L,65283L,65284L,
9992065285L,65286L,65287L,65288L,65289L,65290L,65291L,65292L,65293L,65294L,
9992165295L,65296L,65297L,65298L,65299L,65300L,65301L,65302L,65303L,65304L,
9992265305L,65306L,65307L,65308L,65309L,65310L,65311L,65312L,65313L,65314L,
9992365315L,65316L,65317L,65318L,65319L,65320L,65321L,65322L,65323L,65324L,
9992465325L,65326L,65327L,65328L,65329L,65330L,65331L,65332L,65333L,65334L,
9992565335L,65336L,65337L,65338L,65339L,65340L,65341L,65342L,65343L,65344L,
9992665313L,65314L,65315L,65316L,65317L,65318L,65319L,65320L,65321L,65322L,
9992765323L,65324L,65325L,65326L,65327L,65328L,65329L,65330L,65331L,65332L,
9992865333L,65334L,65335L,65336L,65337L,65338L,65371L,65372L,65373L,65374L,
9992965375L,65376L,65377L,65378L,65379L,65380L,65381L,65382L,65383L,65384L,
9993065385L,65386L,65387L,65388L,65389L,65390L,65391L,65392L,65393L,65394L,
9993165395L,65396L,65397L,65398L,65399L,65400L,65401L,65402L,65403L,65404L,
9993265405L,65406L,65407L,65408L,65409L,65410L,65411L,65412L,65413L,65414L,
9993365415L,65416L,65417L,65418L,65419L,65420L,65421L,65422L,65423L,65424L,
9993465425L,65426L,65427L,65428L,65429L,65430L,65431L,65432L,65433L,65434L,
9993565435L,65436L,65437L,65438L,65439L,65440L,65441L,65442L,65443L,65444L,
9993665445L,65446L,65447L,65448L,65449L,65450L,65451L,65452L,65453L,65454L,
9993765455L,65456L,65457L,65458L,65459L,65460L,65461L,65462L,65463L,65464L,
9993865465L,65466L,65467L,65468L,65469L,65470L,65471L,65472L,65473L,65474L,
9993965475L,65476L,65477L,65478L,65479L,65480L,65481L,65482L,65483L,65484L,
9994065485L,65486L,65487L,65488L,65489L,65490L,65491L,65492L,65493L,65494L,
9994165495L,65496L,65497L,65498L,65499L,65500L,65501L,65502L,65503L,65504L,
9994265505L,65506L,65507L,65508L,65509L,65510L,65511L,65512L,65513L,65514L,
9994365515L,65516L,65517L,65518L,65519L,65520L,65521L,65522L,65523L,65524L,
9994465525L,65526L,65527L,65528L,65529L,65530L,65531L,65532L,65533L,65534L,
9994565535L,
99946};
99947#endif
99948
99949#if defined(DUK_USE_REGEXP_CANON_BITMAP)
99950/*
99951 * Automatically generated by extract_caseconv.py, do not edit!
99952 */
99953
99954const duk_uint8_t duk_unicode_re_canon_bitmap[256] = {
9995523,0,224,19,1,228,255,255,255,255,255,255,255,255,255,255,63,254,255,127,
99956255,255,255,255,255,255,255,255,231,231,0,16,255,227,255,255,63,255,255,
99957255,255,255,255,255,1,252,255,255,255,255,255,255,255,255,255,255,255,255,
99958255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,
99959255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,
99960255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,
99961255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,
99962255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,
99963255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,
99964227,129,255,255,255,147,255,255,255,255,255,255,255,255,255,255,255,255,
99965255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,
99966255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,
99967255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,
99968255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,251,
99969};
99970#endif
99971/*
99972 * Bitstream decoder.
99973 */
99974
99975/* #include duk_internal.h -> already included */
99976
99977/* Decode 'bits' bits from the input stream (bits must be 1...24).
99978 * When reading past bitstream end, zeroes are shifted in. The result
99979 * is signed to match duk_bd_decode_flagged.
99980 */
99982 duk_small_int_t shift;
99983 duk_uint32_t mask;
99984 duk_uint32_t tmp;
99985
99986 /* Note: cannot read more than 24 bits without possibly shifting top bits out.
99987 * Fixable, but adds complexity.
99988 */
99989 DUK_ASSERT(bits >= 1 && bits <= 24);
99990
99991 while (ctx->currbits < bits) {
99992#if 0
99993 DUK_DDD(DUK_DDDPRINT("decode_bits: shift more data (bits=%ld, currbits=%ld)",
99994 (long) bits, (long) ctx->currbits));
99995#endif
99996 ctx->currval <<= 8;
99997 if (ctx->offset < ctx->length) {
99998 /* If ctx->offset >= ctx->length, we "shift zeroes in"
99999 * instead of croaking.
100000 */
100001 ctx->currval |= ctx->data[ctx->offset++];
100002 }
100003 ctx->currbits += 8;
100004 }
100005#if 0
100006 DUK_DDD(DUK_DDDPRINT("decode_bits: bits=%ld, currbits=%ld, currval=0x%08lx",
100007 (long) bits, (long) ctx->currbits, (unsigned long) ctx->currval));
100008#endif
100009
100010 /* Extract 'top' bits of currval; note that the extracted bits do not need
100011 * to be cleared, we just ignore them on next round.
100012 */
100013 shift = ctx->currbits - bits;
100014 mask = (((duk_uint32_t) 1U) << bits) - 1U;
100015 tmp = (ctx->currval >> shift) & mask;
100016 ctx->currbits = shift; /* remaining */
100017
100018#if 0
100019 DUK_DDD(DUK_DDDPRINT("decode_bits: %ld bits -> 0x%08lx (%ld), currbits=%ld, currval=0x%08lx",
100020 (long) bits, (unsigned long) tmp, (long) tmp, (long) ctx->currbits, (unsigned long) ctx->currval));
100021#endif
100022
100023 return tmp;
100024}
100025
100027 return (duk_small_uint_t) duk_bd_decode(ctx, 1);
100028}
100029
100030/* Decode a one-bit flag, and if set, decode a value of 'bits', otherwise return
100031 * default value.
100032 */
100033DUK_INTERNAL duk_uint32_t duk_bd_decode_flagged(duk_bitdecoder_ctx *ctx, duk_small_int_t bits, duk_uint32_t def_value) {
100034 if (duk_bd_decode_flag(ctx)) {
100035 return duk_bd_decode(ctx, bits);
100036 } else {
100037 return def_value;
100041/* Signed variant, allows negative marker value. */
100042DUK_INTERNAL duk_int32_t duk_bd_decode_flagged_signed(duk_bitdecoder_ctx *ctx, duk_small_int_t bits, duk_int32_t def_value) {
100043 return (duk_int32_t) duk_bd_decode_flagged(ctx, bits, (duk_uint32_t) def_value);
100044}
100045
100046/* Shared varint encoding. Match dukutil.py BitEncode.varuint(). */
100049
100050 /* The bit encoding choices here are based on manual testing against
100051 * the actual varuints generated by genbuiltins.py.
100052 */
100053 switch (duk_bd_decode(ctx, 2)) {
100054 case 0:
100055 return 0; /* [0,0] */
100056 case 1:
100057 return duk_bd_decode(ctx, 2) + 1; /* [1,4] */
100058 case 2:
100059 return duk_bd_decode(ctx, 5) + 5; /* [5,36] */
100060 default:
100061 t = duk_bd_decode(ctx, 7);
100062 if (t == 0) {
100063 return duk_bd_decode(ctx, 20);
100064 }
100065 return (t - 1) + 37; /* [37,163] */
100066 }
100067}
100068
100069/* Decode a bit packed string from a custom format used by genbuiltins.py.
100070 * This function is here because it's used for both heap and thread inits.
100071 * Caller must supply the output buffer whose size is NOT checked!
100072 */
100073
100074#define DUK__BITPACK_LETTER_LIMIT 26
100075#define DUK__BITPACK_LOOKUP1 26
100076#define DUK__BITPACK_LOOKUP2 27
100077#define DUK__BITPACK_SWITCH1 28
100078#define DUK__BITPACK_SWITCH 29
100079#define DUK__BITPACK_UNUSED1 30
100080#define DUK__BITPACK_EIGHTBIT 31
100081
100085 0x82, 0x80, DUK_ASC_DOUBLEQUOTE, DUK_ASC_LCURLY };
100086
100088 duk_small_uint_t len;
100092
100093 len = duk_bd_decode(bd, 5);
100094 if (len == 31) {
100095 len = duk_bd_decode(bd, 8); /* Support up to 256 bytes; rare. */
100096 }
100097
100098 mode = 32; /* 0 = uppercase, 32 = lowercase (= 'a' - 'A') */
100099 for (i = 0; i < len; i++) {
100100 t = duk_bd_decode(bd, 5);
100101 if (t < DUK__BITPACK_LETTER_LIMIT) {
100103 } else if (t == DUK__BITPACK_LOOKUP1) {
100105 } else if (t == DUK__BITPACK_LOOKUP2) {
100106 t = duk__bitpacked_lookup[8 + duk_bd_decode(bd, 3)];
100107 } else if (t == DUK__BITPACK_SWITCH1) {
100108 t = duk_bd_decode(bd, 5);
100109 DUK_ASSERT_DISABLE(t >= 0); /* unsigned */
100110 DUK_ASSERT(t <= 25);
100111 t = t + DUK_ASC_UC_A + (mode ^ 32);
100112 } else if (t == DUK__BITPACK_SWITCH) {
100113 mode = mode ^ 32;
100114 t = duk_bd_decode(bd, 5);
100115 DUK_ASSERT_DISABLE(t >= 0);
100116 DUK_ASSERT(t <= 25);
100117 t = t + DUK_ASC_UC_A + mode;
100118 } else if (t == DUK__BITPACK_EIGHTBIT) {
100119 t = duk_bd_decode(bd, 8);
100120 }
100121 out[i] = (duk_uint8_t) t;
100122 }
100123
100124 return len;
100125}
100126
100127/* automatic undefs */
100128#undef DUK__BITPACK_EIGHTBIT
100129#undef DUK__BITPACK_LETTER_LIMIT
100130#undef DUK__BITPACK_LOOKUP1
100131#undef DUK__BITPACK_LOOKUP2
100132#undef DUK__BITPACK_SWITCH
100133#undef DUK__BITPACK_SWITCH1
100134#undef DUK__BITPACK_UNUSED1
100135/*
100136 * Bitstream encoder.
100137 */
100138
100139/* #include duk_internal.h -> already included */
100140
100141DUK_INTERNAL void duk_be_encode(duk_bitencoder_ctx *ctx, duk_uint32_t data, duk_small_int_t bits) {
100142 duk_uint8_t tmp;
100143
100144 DUK_ASSERT(ctx != NULL);
100145 DUK_ASSERT(ctx->currbits < 8);
100146
100147 /* This limitation would be fixable but adds unnecessary complexity. */
100148 DUK_ASSERT(bits >= 1 && bits <= 24);
100149
100150 ctx->currval = (ctx->currval << bits) | data;
100151 ctx->currbits += bits;
100152
100153 while (ctx->currbits >= 8) {
100154 if (ctx->offset < ctx->length) {
100155 tmp = (duk_uint8_t) ((ctx->currval >> (ctx->currbits - 8)) & 0xff);
100156 ctx->data[ctx->offset++] = tmp;
100157 } else {
100158 /* If buffer has been exhausted, truncate bitstream */
100159 ctx->truncated = 1;
100160 }
100161
100162 ctx->currbits -= 8;
100163 }
100164}
100165
100167 duk_small_int_t npad;
100168
100169 DUK_ASSERT(ctx != NULL);
100171
100172 npad = (duk_small_int_t) (8 - ctx->currbits);
100173 if (npad > 0) {
100174 duk_be_encode(ctx, 0, npad);
100175 }
100176 DUK_ASSERT(ctx->currbits == 0);
100177}
100178/*
100179 * Fast buffer writer with slack management.
100180 */
100181
100182/* #include duk_internal.h -> already included */
100183
100184/* XXX: Avoid duk_{memcmp,memmove}_unsafe() by imposing a minimum length of
100185 * >0 for the underlying dynamic buffer.
100186 */
100187
100188/*
100189 * Macro support functions (use only macros in calling code)
100190 */
100191
100193 duk_uint8_t *p;
100194
100195 DUK_ASSERT(thr != NULL);
100196 DUK_ASSERT(bw_ctx != NULL);
100197 DUK_UNREF(thr);
100198
100199 /* 'p' might be NULL when the underlying buffer is zero size. If so,
100200 * the resulting pointers are not used unsafely.
100201 */
100202 p = (duk_uint8_t *) DUK_HBUFFER_DYNAMIC_GET_DATA_PTR(thr->heap, bw_ctx->buf);
100203 DUK_ASSERT(p != NULL || (DUK_HBUFFER_DYNAMIC_GET_SIZE(bw_ctx->buf) == 0 && curr_offset == 0 && new_length == 0));
100204 bw_ctx->p = p + curr_offset;
100205 bw_ctx->p_base = p;
100206 bw_ctx->p_limit = p + new_length;
100207}
100208
100210 DUK_ASSERT(thr != NULL);
100211 DUK_ASSERT(bw_ctx != NULL);
100212 DUK_ASSERT(h_buf != NULL);
100213
100214 bw_ctx->buf = h_buf;
100215 duk__bw_update_ptrs(thr, bw_ctx, 0, DUK_HBUFFER_DYNAMIC_GET_SIZE(h_buf));
100216}
100217
100219 DUK_ASSERT(thr != NULL);
100220 DUK_ASSERT(bw_ctx != NULL);
100221
100222 (void) duk_push_dynamic_buffer(thr, buf_size);
100223 bw_ctx->buf = (duk_hbuffer_dynamic *) duk_known_hbuffer(thr, -1);
100224 DUK_ASSERT(bw_ctx->buf != NULL);
100225 duk__bw_update_ptrs(thr, bw_ctx, 0, buf_size);
100226}
100227
100228/* Resize target buffer for requested size. Called by the macro only when the
100229 * fast path test (= there is space) fails.
100231DUK_INTERNAL duk_uint8_t *duk_bw_resize(duk_hthread *thr, duk_bufwriter_ctx *bw_ctx, duk_size_t sz) {
100232 duk_size_t curr_off;
100233 duk_size_t add_sz;
100234 duk_size_t new_sz;
100235
100236 DUK_ASSERT(thr != NULL);
100237 DUK_ASSERT(bw_ctx != NULL);
100238
100239 /* We could do this operation without caller updating bw_ctx->ptr,
100240 * but by writing it back here we can share code better.
100241 */
100243 curr_off = (duk_size_t) (bw_ctx->p - bw_ctx->p_base);
100244 add_sz = (curr_off >> DUK_BW_SLACK_SHIFT) + DUK_BW_SLACK_ADD;
100245 new_sz = curr_off + sz + add_sz;
100246 if (DUK_UNLIKELY(new_sz < curr_off)) {
100247 /* overflow */
100249 DUK_WO_NORETURN(return NULL;);
100250 }
100251#if 0 /* for manual torture testing: tight allocation, useful with valgrind */
100252 new_sz = curr_off + sz;
100253#endif
100254
100255 /* This is important to ensure dynamic buffer data pointer is not
100256 * NULL (which is possible if buffer size is zero), which in turn
100257 * causes portability issues with e.g. memmove() and memcpy().
100258 */
100259 DUK_ASSERT(new_sz >= 1);
100260
100261 DUK_DD(DUK_DDPRINT("resize bufferwriter from %ld to %ld (add_sz=%ld)", (long) curr_off, (long) new_sz, (long) add_sz));
100262
100263 duk_hbuffer_resize(thr, bw_ctx->buf, new_sz);
100264 duk__bw_update_ptrs(thr, bw_ctx, curr_off, new_sz);
100265 return bw_ctx->p;
100266}
100267
100268/* Make buffer compact, matching current written size. */
100270 duk_size_t len;
100271
100272 DUK_ASSERT(thr != NULL);
100273 DUK_ASSERT(bw_ctx != NULL);
100274 DUK_UNREF(thr);
100275
100276 len = (duk_size_t) (bw_ctx->p - bw_ctx->p_base);
100277 duk_hbuffer_resize(thr, bw_ctx->buf, len);
100278 duk__bw_update_ptrs(thr, bw_ctx, len, len);
100279}
100280
100282 duk_uint8_t *p_base;
100283
100284 DUK_ASSERT(thr != NULL);
100285 DUK_ASSERT(bw != NULL);
100286 DUK_ASSERT(src_off <= DUK_BW_GET_SIZE(thr, bw));
100287 DUK_ASSERT(len <= DUK_BW_GET_SIZE(thr, bw));
100288 DUK_ASSERT(src_off + len <= DUK_BW_GET_SIZE(thr, bw));
100289 DUK_UNREF(thr);
100290
100291 p_base = bw->p_base;
100292 duk_memcpy_unsafe((void *) bw->p, (const void *) (p_base + src_off), (size_t) len);
100293 bw->p += len;
100294}
100295
100297 DUK_ASSERT(thr != NULL);
100298 DUK_ASSERT(bw != NULL);
100299 DUK_ASSERT(src_off <= DUK_BW_GET_SIZE(thr, bw));
100300 DUK_ASSERT(len <= DUK_BW_GET_SIZE(thr, bw));
100301 DUK_ASSERT(src_off + len <= DUK_BW_GET_SIZE(thr, bw));
100302
100303 DUK_BW_ENSURE(thr, bw, len);
100304 duk_bw_write_raw_slice(thr, bw, src_off, len);
100305}
100308 duk_bufwriter_ctx *bw,
100309 duk_size_t dst_off,
100310 const duk_uint8_t *buf,
100311 duk_size_t len) {
100312 duk_uint8_t *p_base;
100313 duk_size_t buf_sz, move_sz;
100314
100315 DUK_ASSERT(thr != NULL);
100316 DUK_ASSERT(bw != NULL);
100317 DUK_ASSERT(dst_off <= DUK_BW_GET_SIZE(thr, bw));
100318 DUK_ASSERT(buf != NULL);
100319 DUK_UNREF(thr);
100320
100321 p_base = bw->p_base;
100322 buf_sz = (duk_size_t) (bw->p - p_base); /* constrained by maximum buffer size */
100323 move_sz = buf_sz - dst_off;
100324
100325 DUK_ASSERT(p_base != NULL); /* buffer size is >= 1 */
100326 duk_memmove_unsafe((void *) (p_base + dst_off + len), (const void *) (p_base + dst_off), (size_t) move_sz);
100327 duk_memcpy_unsafe((void *) (p_base + dst_off), (const void *) buf, (size_t) len);
100328 bw->p += len;
100329}
100330
100332 duk_bufwriter_ctx *bw,
100333 duk_size_t dst_off,
100334 const duk_uint8_t *buf,
100335 duk_size_t len) {
100336 DUK_ASSERT(thr != NULL);
100337 DUK_ASSERT(bw != NULL);
100338 DUK_ASSERT(dst_off <= DUK_BW_GET_SIZE(thr, bw));
100339 DUK_ASSERT(buf != NULL);
100340
100341 DUK_BW_ENSURE(thr, bw, len);
100342 duk_bw_insert_raw_bytes(thr, bw, dst_off, buf, len);
100344
100346 duk_bufwriter_ctx *bw,
100347 duk_size_t dst_off,
100348 duk_size_t src_off,
100349 duk_size_t len) {
100350 duk_uint8_t *p_base;
100351 duk_size_t buf_sz, move_sz;
100352
100353 DUK_ASSERT(thr != NULL);
100354 DUK_ASSERT(bw != NULL);
100355 DUK_ASSERT(dst_off <= DUK_BW_GET_SIZE(thr, bw));
100356 DUK_ASSERT(src_off <= DUK_BW_GET_SIZE(thr, bw));
100357 DUK_ASSERT(len <= DUK_BW_GET_SIZE(thr, bw));
100358 DUK_ASSERT(src_off + len <= DUK_BW_GET_SIZE(thr, bw));
100359 DUK_UNREF(thr);
100360
100361 p_base = bw->p_base;
100363 /* Don't support "straddled" source now. */
100364 DUK_ASSERT(dst_off <= src_off || dst_off >= src_off + len);
100365
100366 if (dst_off <= src_off) {
100367 /* Target is before source. Source offset is expressed as
100368 * a "before change" offset. Account for the memmove.
100369 */
100370 src_off += len;
100371 }
100372
100373 buf_sz = (duk_size_t) (bw->p - p_base);
100374 move_sz = buf_sz - dst_off;
100375
100376 DUK_ASSERT(p_base != NULL); /* buffer size is >= 1 */
100377 duk_memmove_unsafe((void *) (p_base + dst_off + len), (const void *) (p_base + dst_off), (size_t) move_sz);
100378 duk_memcpy_unsafe((void *) (p_base + dst_off), (const void *) (p_base + src_off), (size_t) len);
100379 bw->p += len;
100381
100383 duk_bufwriter_ctx *bw,
100384 duk_size_t dst_off,
100385 duk_size_t src_off,
100386 duk_size_t len) {
100387 DUK_ASSERT(thr != NULL);
100388 DUK_ASSERT(bw != NULL);
100389 DUK_ASSERT(dst_off <= DUK_BW_GET_SIZE(thr, bw));
100390 DUK_ASSERT(src_off <= DUK_BW_GET_SIZE(thr, bw));
100391 DUK_ASSERT(len <= DUK_BW_GET_SIZE(thr, bw));
100392 DUK_ASSERT(src_off + len <= DUK_BW_GET_SIZE(thr, bw));
100393
100394 /* Don't support "straddled" source now. */
100395 DUK_ASSERT(dst_off <= src_off || dst_off >= src_off + len);
100396
100397 DUK_BW_ENSURE(thr, bw, len);
100398 duk_bw_insert_raw_slice(thr, bw, dst_off, src_off, len);
100399}
100400
100402 duk_uint8_t *p_base, *p_dst, *p_src;
100403 duk_size_t buf_sz, move_sz;
100404
100405 DUK_ASSERT(thr != NULL);
100406 DUK_ASSERT(bw != NULL);
100407 DUK_ASSERT(off <= DUK_BW_GET_SIZE(thr, bw));
100408 DUK_UNREF(thr);
100409
100410 p_base = bw->p_base;
100411 buf_sz = (duk_size_t) (bw->p - p_base);
100412 move_sz = buf_sz - off;
100413 p_dst = p_base + off + len;
100414 p_src = p_base + off;
100415 duk_memmove_unsafe((void *) p_dst, (const void *) p_src, (size_t) move_sz);
100416 return p_src; /* point to start of 'reserved area' */
100417}
100418
100420 DUK_ASSERT(thr != NULL);
100421 DUK_ASSERT(bw != NULL);
100422 DUK_ASSERT(off <= DUK_BW_GET_SIZE(thr, bw));
100423
100424 DUK_BW_ENSURE(thr, bw, len);
100425 return duk_bw_insert_raw_area(thr, bw, off, len);
100426}
100427
100429 duk_size_t move_sz;
100430
100431 duk_uint8_t *p_base;
100432 duk_uint8_t *p_src;
100433 duk_uint8_t *p_dst;
100434
100435 DUK_ASSERT(thr != NULL);
100436 DUK_ASSERT(bw != NULL);
100437 DUK_ASSERT(off <= DUK_BW_GET_SIZE(thr, bw));
100438 DUK_ASSERT(len <= DUK_BW_GET_SIZE(thr, bw));
100439 DUK_ASSERT(off + len <= DUK_BW_GET_SIZE(thr, bw));
100440 DUK_UNREF(thr);
100441
100442 p_base = bw->p_base;
100443 p_dst = p_base + off;
100444 p_src = p_dst + len;
100445 move_sz = (duk_size_t) (bw->p - p_src);
100446 duk_memmove_unsafe((void *) p_dst, (const void *) p_src, (size_t) move_sz);
100447 bw->p -= len;
100448}
100449
100450/*
100451 * Assertion helpers
100452 */
100453
100454#if defined(DUK_USE_ASSERTIONS)
100455DUK_INTERNAL void duk_bw_assert_valid(duk_hthread *thr, duk_bufwriter_ctx *bw_ctx) {
100456 DUK_UNREF(thr);
100457 DUK_ASSERT(bw_ctx != NULL);
100458 DUK_ASSERT(bw_ctx->buf != NULL);
100459 DUK_ASSERT((DUK_HBUFFER_DYNAMIC_GET_SIZE(bw_ctx->buf) == 0) ||
100460 (bw_ctx->p != NULL && bw_ctx->p_base != NULL && bw_ctx->p_limit != NULL && bw_ctx->p_limit >= bw_ctx->p_base &&
100461 bw_ctx->p >= bw_ctx->p_base && bw_ctx->p <= bw_ctx->p_limit));
100462}
100463#endif
100464/*
100465 * Cast helpers.
100466 *
100467 * C99+ coercion is challenging portability-wise because out-of-range casts
100468 * may invoke implementation defined or even undefined behavior. See e.g.
100469 * http://blog.frama-c.com/index.php?post/2013/10/09/Overflow-float-integer.
100470 *
100471 * Provide explicit cast helpers which try to avoid implementation defined
100472 * or undefined behavior. These helpers can then be simplified in the vast
100473 * majority of cases where the implementation defined or undefined behavior
100474 * is not problematic.
100475 */
100476
100477/* #include duk_internal.h -> already included */
100478
100479/* Portable double-to-integer cast which avoids undefined behavior and avoids
100480 * relying on fmin(), fmax(), or other intrinsics. Out-of-range results are
100481 * not assumed by caller, but here value is clamped, NaN converts to minval.
100482 */
100483#define DUK__DOUBLE_INT_CAST1(tname, minval, maxval) \
100484 do { \
100485 if (DUK_LIKELY(x >= (duk_double_t) (minval))) { \
100486 DUK_ASSERT(!DUK_ISNAN(x)); \
100487 if (DUK_LIKELY(x <= (duk_double_t) (maxval))) { \
100488 return (tname) x; \
100489 } else { \
100490 return (tname) (maxval); \
100491 } \
100492 } else { \
100493 /* NaN or below minval. Since we don't care about the result \
100494 * for out-of-range values, just return the minimum value for \
100495 * both. \
100496 */ \
100497 return (tname) (minval); \
100498 } \
100499 } while (0)
100500
100501/* Rely on specific NaN behavior for duk_double_{fmin,fmax}(): if either
100502 * argument is a NaN, return the second argument. This avoids a
100503 * NaN-to-integer cast which is undefined behavior.
100504 */
100505#define DUK__DOUBLE_INT_CAST2(tname, minval, maxval) \
100506 do { \
100507 return (tname) duk_double_fmin(duk_double_fmax(x, (duk_double_t) (minval)), (duk_double_t) (maxval)); \
100508 } while (0)
100509
100510/* Another solution which doesn't need C99+ behavior for fmin() and fmax(). */
100511#define DUK__DOUBLE_INT_CAST3(tname, minval, maxval) \
100512 do { \
100513 if (DUK_ISNAN(x)) { \
100514 /* 0 or any other value is fine. */ \
100515 return (tname) 0; \
100516 } else \
100517 return (tname) DUK_FMIN(DUK_FMAX(x, (duk_double_t) (minval)), (duk_double_t) (maxval)); \
100518 } \
100519 } \
100520 while (0)
100521
100522/* C99+ solution: relies on specific fmin() and fmax() behavior in C99: if
100523 * one argument is NaN but the other isn't, the non-NaN argument is returned.
100524 * Because the limits are non-NaN values, explicit NaN check is not needed.
100525 * This may not work on all legacy platforms, and also doesn't seem to inline
100526 * the fmin() and fmax() calls (unless one uses -ffast-math which we don't
100527 * support).
100528 */
100529#define DUK__DOUBLE_INT_CAST4(tname, minval, maxval) \
100530 do { \
100531 return (tname) DUK_FMIN(DUK_FMAX(x, (duk_double_t) (minval)), (duk_double_t) (maxval)); \
100532 } while (0)
100533
100535#if defined(DUK_USE_ALLOW_UNDEFINED_BEHAVIOR)
100536 /* Real world solution: almost any practical platform will provide
100537 * an integer value without any guarantees what it is (which is fine).
100538 */
100539 return (duk_int_t) x;
100540#else
100542#endif
100543}
100544
100546#if defined(DUK_USE_ALLOW_UNDEFINED_BEHAVIOR)
100547 return (duk_uint_t) x;
100548#else
100550#endif
100551}
100552
100554#if defined(DUK_USE_ALLOW_UNDEFINED_BEHAVIOR)
100555 return (duk_int32_t) x;
100556#else
100558#endif
100559}
100560
100562#if defined(DUK_USE_ALLOW_UNDEFINED_BEHAVIOR)
100563 return (duk_uint32_t) x;
100564#else
100566#endif
100567}
100568
100569/* Largest IEEE double that doesn't round to infinity in the default rounding
100570 * mode. The exact midpoint between (1 - 2^(-24)) * 2^128 and 2^128 rounds to
100571 * infinity, at least on x64. This number is one double unit below that
100572 * midpoint. See misc/float_cast.c.
100573 */
100574#define DUK__FLOAT_ROUND_LIMIT 340282356779733623858607532500980858880.0
100575
100576/* Maximum IEEE float. Double-to-float conversion above this would be out of
100577 * range and thus technically undefined behavior.
100578 */
100579#define DUK__FLOAT_MAX 340282346638528859811704183484516925440.0
100580
100582 /* Even a double-to-float cast is technically undefined behavior if
100583 * the double is out-of-range. C99 Section 6.3.1.5:
100584 *
100585 * If the value being converted is in the range of values that can
100586 * be represented but cannot be represented exactly, the result is
100587 * either the nearest higher or nearest lower representable value,
100588 * chosen in an implementation-defined manner. If the value being
100589 * converted is outside the range of values that can be represented,
100590 * the behavior is undefined.
100591 */
100592#if defined(DUK_USE_ALLOW_UNDEFINED_BEHAVIOR)
100593 return (duk_float_t) x;
100594#else
100595 duk_double_t t;
100596
100597 t = DUK_FABS(x);
100598 DUK_ASSERT((DUK_ISNAN(x) && DUK_ISNAN(t)) || (!DUK_ISNAN(x) && !DUK_ISNAN(t)));
100599
100601 /* Standard in-range case, try to get here with a minimum
100602 * number of checks and branches.
100603 */
100604 DUK_ASSERT(!DUK_ISNAN(x));
100605 return (duk_float_t) x;
100606 } else if (t <= DUK__FLOAT_ROUND_LIMIT) {
100607 /* Out-of-range, but rounds to min/max float. */
100608 DUK_ASSERT(!DUK_ISNAN(x));
100609 if (x < 0.0) {
100610 return (duk_float_t) -DUK__FLOAT_MAX;
100611 } else {
100613 }
100614 } else if (DUK_ISNAN(x)) {
100615 /* Assumes double NaN -> float NaN considered "in range". */
100616 DUK_ASSERT(DUK_ISNAN(x));
100617 return (duk_float_t) x;
100618 } else {
100619 /* Out-of-range, rounds to +/- Infinity. */
100620 if (x < 0.0) {
100622 } else {
100624 }
100625 }
100626#endif
100627}
100629/* automatic undefs */
100630#undef DUK__DOUBLE_INT_CAST1
100631#undef DUK__DOUBLE_INT_CAST2
100632#undef DUK__DOUBLE_INT_CAST3
100633#undef DUK__DOUBLE_INT_CAST4
100634#undef DUK__FLOAT_MAX
100635#undef DUK__FLOAT_ROUND_LIMIT
100636/*
100637 * IEEE double helpers.
100639
100640/* #include duk_internal.h -> already included */
100641
100643 duk_double_union du;
100644 du.d = x;
100645 return DUK_DBLUNION_IS_ANYINF(&du);
100646}
100647
100649 duk_double_union du;
100650 du.d = x;
100651 return DUK_DBLUNION_IS_POSINF(&du);
100652}
100653
100656 du.d = x;
100657 return DUK_DBLUNION_IS_NEGINF(&du);
100658}
100659
100661 duk_double_union du;
100662 du.d = x;
100663 /* Assumes we're dealing with a Duktape internal NaN which is
100664 * NaN normalized if duk_tval requires it.
100665 */
100667 return DUK_DBLUNION_IS_NAN(&du);
100668}
100669
100671 duk_double_union du;
100672 du.d = x;
100673 /* Assumes we're dealing with a Duktape internal NaN which is
100674 * NaN normalized if duk_tval requires it.
100675 */
100677 return DUK_DBLUNION_IS_NAN(&du) || DUK_DBLUNION_IS_ANYZERO(&du);
100678}
100679
100681 duk_double_union du;
100682 du.d = x;
100683 /* If exponent is 0x7FF the argument is either a NaN or an
100684 * infinity. We don't need to check any other fields.
100685 */
100686#if defined(DUK_USE_64BIT_OPS)
100687#if defined(DUK_USE_DOUBLE_ME)
100688 return (du.ull[DUK_DBL_IDX_ULL0] & DUK_U64_CONSTANT(0x000000007ff00000)) == DUK_U64_CONSTANT(0x000000007ff00000);
100689#else
100690 return (du.ull[DUK_DBL_IDX_ULL0] & DUK_U64_CONSTANT(0x7ff0000000000000)) == DUK_U64_CONSTANT(0x7ff0000000000000);
100691#endif
100692#else
100693 return (du.ui[DUK_DBL_IDX_UI0] & 0x7ff00000UL) == 0x7ff00000UL;
100694#endif
100696
100698 duk_double_union du;
100699#if defined(DUK_USE_64BIT_OPS)
100700 duk_uint64_t t;
100701#else
100702 duk_uint32_t t;
100703#endif
100704 du.d = x;
100705#if defined(DUK_USE_64BIT_OPS)
100706#if defined(DUK_USE_DOUBLE_ME)
100707 t = du.ull[DUK_DBL_IDX_ULL0] & DUK_U64_CONSTANT(0x000000007ff00000);
100708 if (t == DUK_U64_CONSTANT(0x0000000000000000)) {
100709 t = du.ull[DUK_DBL_IDX_ULL0] & DUK_U64_CONSTANT(0x0000000080000000);
100710 return t == 0;
100712 if (t == DUK_U64_CONSTANT(0x000000007ff00000)) {
100713 return 1;
100714 }
100715#else
100716 t = du.ull[DUK_DBL_IDX_ULL0] & DUK_U64_CONSTANT(0x7ff0000000000000);
100717 if (t == DUK_U64_CONSTANT(0x0000000000000000)) {
100718 t = du.ull[DUK_DBL_IDX_ULL0] & DUK_U64_CONSTANT(0x8000000000000000);
100719 return t == 0;
100721 if (t == DUK_U64_CONSTANT(0x7ff0000000000000)) {
100722 return 1;
100723 }
100724#endif
100725#else
100726 t = du.ui[DUK_DBL_IDX_UI0] & 0x7ff00000UL;
100727 if (t == 0x00000000UL) {
100728 return DUK_DBLUNION_IS_ANYZERO(&du);
100730 if (t == 0x7ff00000UL) {
100731 return 1;
100732 }
100733#endif
100734 return 0;
100735}
100736
100739 du.d = x;
100741}
100744 /* XXX: optimize */
100746 x = DUK_FLOOR(DUK_FABS(x)); /* truncate towards zero */
100747 if (s) {
100748 x = -x;
100749 }
100750 return x;
100751}
100752
100754 duk_double_union du1;
100755 duk_double_union du2;
100756 du1.d = x;
100757 du2.d = y;
100758
100759 return (((du1.ui[DUK_DBL_IDX_UI0] ^ du2.ui[DUK_DBL_IDX_UI0]) & 0x80000000UL) == 0);
100760}
100761
100763 /* Doesn't replicate fmin() behavior exactly: for fmin() if one
100764 * argument is a NaN, the other argument should be returned.
100765 * Duktape doesn't rely on this behavior so the replacement can
100766 * be simplified.
100767 */
100768 return (x < y ? x : y);
100769}
100770
100772 /* Doesn't replicate fmax() behavior exactly: for fmax() if one
100773 * argument is a NaN, the other argument should be returned.
100774 * Duktape doesn't rely on this behavior so the replacement can
100775 * be simplified.
100776 */
100777 return (x > y ? x : y);
100778}
100779
100781 return !duk_double_is_nan_or_inf(x);
100782}
100785 if (duk_double_is_nan_or_inf(x)) {
100786 return 0;
100787 } else {
100789 }
100790}
100791
100793 /* >>> 2**53-1
100794 * 9007199254740991
100795 */
100796 return duk_double_is_integer(x) && DUK_FABS(x) <= 9007199254740991.0;
100797}
100799/* Check whether a duk_double_t is a whole number in the 32-bit range (reject
100800 * negative zero), and if so, return a duk_int32_t.
100801 * For compiler use: don't allow negative zero as it will cause trouble with
100802 * LDINT+LDINTX, positive zero is OK.
100803 */
100805 duk_int32_t t;
100806
100807 t = duk_double_to_int32_t(x);
100808 if (!duk_double_equals((duk_double_t) t, x)) {
100809 return 0;
100810 }
100811 if (t == 0) {
100812 duk_double_union du;
100813 du.d = x;
100814 if (DUK_DBLUNION_HAS_SIGNBIT(&du)) {
100815 return 0;
100816 }
100817 }
100818 *ival = t;
100819 return 1;
100820}
100821
100822/* Check whether a duk_double_t is a whole number in the 32-bit range, and if
100823 * so, return a duk_int32_t.
100824 */
100826 duk_int32_t t;
100827
100828 t = duk_double_to_int32_t(x);
100829 if (!duk_double_equals((duk_double_t) t, x)) {
100830 return 0;
100832 *ival = t;
100833 return 1;
100834}
100835
100836/* Division: division by zero is undefined behavior (and may in fact trap)
100837 * so it needs special handling for portability.
100838 */
100839
100841#if !defined(DUK_USE_ALLOW_UNDEFINED_BEHAVIOR)
100842 if (DUK_UNLIKELY(duk_double_equals(y, 0.0) != 0)) {
100843 /* In C99+ division by zero is undefined behavior so
100844 * avoid it entirely. Hopefully the compiler is
100845 * smart enough to avoid emitting any actual code
100846 * because almost all practical platforms behave as
100847 * expected.
100848 */
100849 if (x > 0.0) {
100850 if (DUK_SIGNBIT(y)) {
100851 return -DUK_DOUBLE_INFINITY;
100852 } else {
100853 return DUK_DOUBLE_INFINITY;
100854 }
100855 } else if (x < 0.0) {
100856 if (DUK_SIGNBIT(y)) {
100857 return DUK_DOUBLE_INFINITY;
100858 } else {
100859 return -DUK_DOUBLE_INFINITY;
100861 } else {
100862 /* +/- 0, NaN */
100863 return DUK_DOUBLE_NAN;
100865 }
100866#endif
100867
100868 return x / y;
100869}
100870
100871/* Double and float byteorder changes. */
100872
100874#if defined(DUK_USE_DOUBLE_LE)
100875 /* HGFEDCBA -> HGFEDCBA */
100876 DUK_UNREF(u);
100877#elif defined(DUK_USE_DOUBLE_ME)
100878 duk_uint32_t a, b;
100879
100880 /* DCBAHGFE -> HGFEDCBA */
100881 a = u->ui[0];
100882 b = u->ui[1];
100883 u->ui[0] = b;
100884 u->ui[1] = a;
100885#elif defined(DUK_USE_DOUBLE_BE)
100886 /* ABCDEFGH -> HGFEDCBA */
100887#if defined(DUK_USE_64BIT_OPS)
100888 u->ull[0] = DUK_BSWAP64(u->ull[0]);
100889#else
100890 duk_uint32_t a, b;
100891
100892 a = u->ui[0];
100893 b = u->ui[1];
100894 u->ui[0] = DUK_BSWAP32(b);
100895 u->ui[1] = DUK_BSWAP32(a);
100896#endif
100897#else
100898#error internal error
100899#endif
100900}
100901
100904}
100905
100907#if defined(DUK_USE_DOUBLE_LE)
100908 /* HGFEDCBA -> ABCDEFGH */
100909#if defined(DUK_USE_64BIT_OPS)
100910 u->ull[0] = DUK_BSWAP64(u->ull[0]);
100911#else
100912 duk_uint32_t a, b;
100913
100914 a = u->ui[0];
100915 b = u->ui[1];
100916 u->ui[0] = DUK_BSWAP32(b);
100917 u->ui[1] = DUK_BSWAP32(a);
100918#endif
100919#elif defined(DUK_USE_DOUBLE_ME)
100920 duk_uint32_t a, b;
100921
100922 /* DCBAHGFE -> ABCDEFGH */
100923 a = u->ui[0];
100924 b = u->ui[1];
100925 u->ui[0] = DUK_BSWAP32(a);
100926 u->ui[1] = DUK_BSWAP32(b);
100927#elif defined(DUK_USE_DOUBLE_BE)
100928 /* ABCDEFGH -> ABCDEFGH */
100930#else
100931#error internal error
100932#endif
100933}
100934
100937}
100938
100940#if defined(DUK_USE_DOUBLE_LE) || defined(DUK_USE_DOUBLE_ME)
100941 /* DCBA -> ABCD */
100942 u->ui[0] = DUK_BSWAP32(u->ui[0]);
100943#elif defined(DUK_USE_DOUBLE_BE)
100944 /* ABCD -> ABCD */
100945 DUK_UNREF(u);
100946#else
100947#error internal error
100948#endif
100949}
100950
100953}
100954
100955/* Comparison: ensures comparison operates on exactly correct types, avoiding
100956 * some floating point comparison pitfalls (e.g. atan2() assertions failed on
100957 * -m32 with direct comparison, even with explicit casts).
100958 */
100959#if defined(DUK_USE_GCC_PRAGMAS)
100960#pragma GCC diagnostic push
100961#pragma GCC diagnostic ignored "-Wfloat-equal"
100962#elif defined(DUK_USE_CLANG_PRAGMAS)
100963#pragma clang diagnostic push
100964#pragma clang diagnostic ignored "-Wfloat-equal"
100965#endif
100966
100968 return x == y;
100969}
100970
100972 return x == y;
100973}
100974#if defined(DUK_USE_GCC_PRAGMAS)
100975#pragma GCC diagnostic pop
100976#elif defined(DUK_USE_CLANG_PRAGMAS)
100977#pragma clang diagnostic pop
100978#endif
100979/*
100980 * Hash function duk_util_hashbytes().
100981 *
100982 * Currently, 32-bit MurmurHash2.
100983 *
100984 * Don't rely on specific hash values; hash function may be endianness
100985 * dependent, for instance.
100986 */
100987
100988/* #include duk_internal.h -> already included */
100989
100990#if defined(DUK_USE_STRHASH_DENSE)
100991/* 'magic' constants for Murmurhash2 */
100992#define DUK__MAGIC_M ((duk_uint32_t) 0x5bd1e995UL)
100993#define DUK__MAGIC_R 24
100994
100995DUK_INTERNAL duk_uint32_t duk_util_hashbytes(const duk_uint8_t *data, duk_size_t len, duk_uint32_t seed) {
100996 duk_uint32_t h = seed ^ ((duk_uint32_t) len);
100997
100998 while (len >= 4) {
100999 /* Portability workaround is required for platforms without
101000 * unaligned access. The replacement code emulates little
101001 * endian access even on big endian architectures, which is
101002 * OK as long as it is consistent for a build.
101003 */
101004#if defined(DUK_USE_HASHBYTES_UNALIGNED_U32_ACCESS)
101005 duk_uint32_t k = *((const duk_uint32_t *) (const void *) data);
101006#else
101007 duk_uint32_t k = ((duk_uint32_t) data[0]) | (((duk_uint32_t) data[1]) << 8) | (((duk_uint32_t) data[2]) << 16) |
101008 (((duk_uint32_t) data[3]) << 24);
101009#endif
101010
101011 k *= DUK__MAGIC_M;
101012 k ^= k >> DUK__MAGIC_R;
101013 k *= DUK__MAGIC_M;
101014 h *= DUK__MAGIC_M;
101015 h ^= k;
101016 data += 4;
101017 len -= 4;
101019
101020 switch (len) {
101021 case 3:
101022 h ^= data[2] << 16;
101023 case 2:
101024 h ^= data[1] << 8;
101025 case 1:
101026 h ^= data[0];
101027 h *= DUK__MAGIC_M;
101028 }
101030 h ^= h >> 13;
101031 h *= DUK__MAGIC_M;
101032 h ^= h >> 15;
101033
101034 return h;
101035}
101036#endif /* DUK_USE_STRHASH_DENSE */
101037
101038/* automatic undefs */
101039#undef DUK__MAGIC_M
101040#undef DUK__MAGIC_R
101041/*
101042 * Memory utils.
101043 */
101044
101045/* #include duk_internal.h -> already included */
101046
101047#if defined(DUK_USE_ALLOW_UNDEFINED_BEHAVIOR)
101048DUK_INTERNAL DUK_INLINE duk_small_int_t duk_memcmp_unsafe(const void *s1, const void *s2, duk_size_t len) {
101049 DUK_ASSERT(s1 != NULL || len == 0U);
101050 DUK_ASSERT(s2 != NULL || len == 0U);
101051 return DUK_MEMCMP(s1, s2, (size_t) len);
101053
101054DUK_INTERNAL DUK_INLINE duk_small_int_t duk_memcmp(const void *s1, const void *s2, duk_size_t len) {
101055 DUK_ASSERT(s1 != NULL);
101056 DUK_ASSERT(s2 != NULL);
101057 return DUK_MEMCMP(s1, s2, (size_t) len);
101059#else /* DUK_USE_ALLOW_UNDEFINED_BEHAVIOR */
101060DUK_INTERNAL DUK_INLINE duk_small_int_t duk_memcmp_unsafe(const void *s1, const void *s2, duk_size_t len) {
101061 DUK_ASSERT(s1 != NULL || len == 0U);
101062 DUK_ASSERT(s2 != NULL || len == 0U);
101063 if (DUK_UNLIKELY(len == 0U)) {
101064 return 0;
101065 }
101066 DUK_ASSERT(s1 != NULL);
101067 DUK_ASSERT(s2 != NULL);
101068 return duk_memcmp(s1, s2, len);
101069}
101071DUK_INTERNAL DUK_INLINE duk_small_int_t duk_memcmp(const void *s1, const void *s2, duk_size_t len) {
101072 DUK_ASSERT(s1 != NULL);
101073 DUK_ASSERT(s2 != NULL);
101074 return DUK_MEMCMP(s1, s2, (size_t) len);
101075}
101076#endif /* DUK_USE_ALLOW_UNDEFINED_BEHAVIOR */
101077/*
101078 * A tiny random number generator used for Math.random() and other internals.
101079 *
101080 * Default algorithm is xoroshiro128+: http://xoroshiro.di.unimi.it/xoroshiro128plus.c
101081 * with SplitMix64 seed preparation: http://xorshift.di.unimi.it/splitmix64.c.
101082 *
101083 * Low memory targets and targets without 64-bit types use a slightly smaller
101084 * (but slower) algorithm by Adi Shamir:
101085 * http://www.woodmann.com/forum/archive/index.php/t-3100.html.
101086 *
101087 */
101088
101089/* #include duk_internal.h -> already included */
101090
101091#if !defined(DUK_USE_GET_RANDOM_DOUBLE)
101092
101093#if defined(DUK_USE_PREFER_SIZE) || !defined(DUK_USE_64BIT_OPS)
101094#define DUK__RANDOM_SHAMIR3OP
101095#else
101096#define DUK__RANDOM_XOROSHIRO128PLUS
101097#endif
101098
101099#if defined(DUK__RANDOM_SHAMIR3OP)
101100#define DUK__UPDATE_RND(rnd) \
101101 do { \
101102 (rnd) += ((rnd) * (rnd)) | 0x05UL; \
101103 (rnd) = ((rnd) &0xffffffffUL); /* if duk_uint32_t is exactly 32 bits, this is a NOP */ \
101104 } while (0)
101105
101106#define DUK__RND_BIT(rnd) ((rnd) >> 31) /* only use the highest bit */
101107
101109 DUK_UNREF(thr); /* Nothing now. */
101110}
101111
101113 duk_double_t t;
101114 duk_small_int_t n;
101115 duk_uint32_t rnd;
101116
101117 rnd = thr->heap->rnd_state;
101118
101119 n = 53; /* enough to cover the whole mantissa */
101120 t = 0.0;
101121
101122 do {
101123 DUK__UPDATE_RND(rnd);
101124 t += DUK__RND_BIT(rnd);
101125 t /= 2.0;
101126 } while (--n);
101127
101128 thr->heap->rnd_state = rnd;
101129
101130 DUK_ASSERT(t >= (duk_double_t) 0.0);
101131 DUK_ASSERT(t < (duk_double_t) 1.0);
101132
101133 return t;
101134}
101135#endif /* DUK__RANDOM_SHAMIR3OP */
101136
101137#if defined(DUK__RANDOM_XOROSHIRO128PLUS)
101138DUK_LOCAL DUK_ALWAYS_INLINE duk_uint64_t duk__rnd_splitmix64(duk_uint64_t *x) {
101139 duk_uint64_t z;
101140 z = (*x += DUK_U64_CONSTANT(0x9E3779B97F4A7C15));
101141 z = (z ^ (z >> 30U)) * DUK_U64_CONSTANT(0xBF58476D1CE4E5B9);
101142 z = (z ^ (z >> 27U)) * DUK_U64_CONSTANT(0x94D049BB133111EB);
101143 return z ^ (z >> 31U);
101144}
101145
101146DUK_LOCAL DUK_ALWAYS_INLINE duk_uint64_t duk__rnd_rotl(const duk_uint64_t x, duk_small_uint_t k) {
101147 return (x << k) | (x >> (64U - k));
101148}
101149
101150DUK_LOCAL DUK_ALWAYS_INLINE duk_uint64_t duk__xoroshiro128plus(duk_uint64_t *s) {
101151 duk_uint64_t s0;
101152 duk_uint64_t s1;
101153 duk_uint64_t res;
101154
101155 s0 = s[0];
101156 s1 = s[1];
101157 res = s0 + s1;
101158 s1 ^= s0;
101159 s[0] = duk__rnd_rotl(s0, 55) ^ s1 ^ (s1 << 14U);
101160 s[1] = duk__rnd_rotl(s1, 36);
101161
101162 return res;
101163}
101164
101167 duk_uint64_t x;
101168
101169 /* Mix both halves of the initial seed with SplitMix64. The intent
101170 * is to ensure that very similar raw seeds (which is usually the case
101171 * because current seed is Date.now()) result in different xoroshiro128+
101172 * seeds.
101173 */
101174 x = thr->heap->rnd_state[0]; /* Only [0] is used as input here. */
101175 for (i = 0; i < 64; i++) {
101176 thr->heap->rnd_state[i & 0x01] = duk__rnd_splitmix64(&x); /* Keep last 2 values. */
101177 }
101178}
101179
101181 duk_uint64_t v;
101182 duk_double_union du;
101183
101184 /* For big and little endian the integer and IEEE double byte order
101185 * is the same so a direct assignment works. For mixed endian the
101186 * 32-bit parts must be swapped.
101187 */
101188 v = (DUK_U64_CONSTANT(0x3ff) << 52U) | (duk__xoroshiro128plus((duk_uint64_t *) thr->heap->rnd_state) >> 12U);
101189 du.ull[0] = v;
101190#if defined(DUK_USE_DOUBLE_ME)
101191 do {
101192 duk_uint32_t tmp;
101193 tmp = du.ui[0];
101194 du.ui[0] = du.ui[1];
101195 du.ui[1] = tmp;
101196 } while (0);
101197#endif
101198 return du.d - 1.0;
101199}
101200#endif /* DUK__RANDOM_XOROSHIRO128PLUS */
101201
101202#endif /* !DUK_USE_GET_RANDOM_DOUBLE */
101203
101204/* automatic undefs */
101205#undef DUK__RANDOM_SHAMIR3OP
101206#undef DUK__RANDOM_XOROSHIRO128PLUS
101207#undef DUK__RND_BIT
101208#undef DUK__UPDATE_RND
101209#endif
static const __attribute__((used))
Definition: gui.c:359
STATIC char result[100]
Definition: arexx.c:77
static struct bitmap snapshot
Definition: plot.c:206
static os_mode mode
The current sprite mode.
Definition: buffer.c:72
static osspriteop_area * buffer
The buffer characteristics.
Definition: buffer.c:55
static uint32_t count(const http_directive *list, lwc_string *key)
wimp_w parent
Definition: dialog.c:88
int duk_small_int_t
Definition: duk_config.h:2033
duk_uint16_t duk_uint_least16_t
Definition: duk_config.h:1849
#define DUK_UNREACHABLE()
Definition: duk_config.h:2687
#define DUK_USE_VALSTACK_GROW_SHIFT
Definition: duk_config.h:3082
#define DUK_U64_CONSTANT(x)
Definition: duk_config.h:2610
#define DUK_SIN
Definition: duk_config.h:2396
duk_int32_t duk_int_fast32_t
Definition: duk_config.h:1858
#define DUK_USE_CALLSTACK_LIMIT
Definition: duk_config.h:2916
#define DUK_SETJMP(jb)
Definition: duk_config.h:2151
#define DUK_FP_NAN
Definition: duk_config.h:2342
duk_int32_t duk_intmax_t
Definition: duk_config.h:1870
#define DUK_INTERNAL
Definition: duk_config.h:2743
#define DUK_ANSI_MALLOC
Definition: duk_config.h:2167
#define DUK_LOCAL_DECL
Definition: duk_config.h:2747
#define DUK_USE_STRTAB_MAXSIZE
Definition: duk_config.h:3071
#define DUK_COLD
Definition: duk_config.h:2723
#define DUK_ALWAYS_INLINE
Definition: duk_config.h:2824
#define DUK_USE_REGEXP_COMPILER_RECLIMIT
Definition: duk_config.h:3050
#define DUK_LOCAL
Definition: duk_config.h:2750
#define DUK_SSCANF
Definition: duk_config.h:2243
#define DUK_FP_NORMAL
Definition: duk_config.h:2346
#define DUK_USE_HOBJECT_ENTRY_MINGROW_ADD
Definition: duk_config.h:2996
#define DUK_INT_MIN
Definition: duk_config.h:2013
unsigned int duk_small_uint_t
Definition: duk_config.h:2034
duk_uint32_t duk_uint_least32_t
Definition: duk_config.h:1851
#define DUK_UINT32_MIN
Definition: duk_config.h:1901
duk_uint_t duk_uidx_t
Definition: duk_config.h:2061
#define DUK_CEIL
Definition: duk_config.h:2375
#define DUK_INLINE
Definition: duk_config.h:2823
#define DUK_USE_STRTAB_SHRINK_LIMIT
Definition: duk_config.h:3075
#define DUK_USE_COMPILER_RECLIMIT
Definition: duk_config.h:2921
#define DUK_USE_TRACEBACK_DEPTH
Definition: duk_config.h:3081
duk_uint_t duk_ucodepoint_t
Definition: duk_config.h:2095
#define DUK_USE_STRHASH_SKIP_SHIFT
Definition: duk_config.h:3065
#define DUK_USE_HOBJECT_HASH_PROP_LIMIT
Definition: duk_config.h:2999
duk_uint_fast32_t duk_uint_fast_t
Definition: duk_config.h:2024
#define DUK_USE_ALIGN_BY
Definition: duk_config.h:2595
#define DUK_ACOS
Definition: duk_config.h:2384
duk_small_int_t duk_ret_t
Definition: duk_config.h:2076
#define DUK_LOSE_CONST(src)
Definition: duk_config.h:2696
duk_int_t duk_idx_t
Definition: duk_config.h:2056
duk_int_fast32_t duk_int_fast_t
Definition: duk_config.h:2023
#define DUK_USE_JSON_ENC_RECLIMIT
Definition: duk_config.h:3015
#define DUK_ASIN
Definition: duk_config.h:2387
#define DUK_INT32_MIN
Definition: duk_config.h:1903
#define DUK_FP_ZERO
Definition: duk_config.h:2344
duk_int_t duk_errcode_t
Definition: duk_config.h:2083
#define DUK_USE_LITCACHE_SIZE
Definition: duk_config.h:3022
#define DUK_EXTERNAL
Definition: duk_config.h:2730
duk_int8_t duk_int_least8_t
Definition: duk_config.h:1848
#define DUK_INT_MAX
Definition: duk_config.h:2014
#define DUK_USE_DEBUG_LEVEL
Definition: duk_config.h:2941
#define DUK_USE_CBOR_DEC_RECLIMIT
Definition: duk_config.h:2918
#define DUK_SPRINTF
Definition: duk_config.h:2229
#define DUK_UINT_MAX
Definition: duk_config.h:2016
#define DUK_USE_ARCH_STRING
Definition: duk_config.h:1019
#define DUK_MEMCMP
Definition: duk_config.h:2214
duk_small_uint_t duk_bool_t
Definition: duk_config.h:2051
#define DUK_BSWAP16(x)
Definition: duk_config.h:2790
#define DUK_USE_JSON_DEC_RECLIMIT
Definition: duk_config.h:3013
#define DUK_USE_FATAL_MAXLEN
Definition: duk_config.h:2972
#define DUK_ATAN
Definition: duk_config.h:2390
#define DUK_LONGJMP(jb)
Definition: duk_config.h:2152
#define DUK_POW
Definition: duk_config.h:2381
duk_uint_fast16_t duk_small_uint_fast_t
Definition: duk_config.h:2044
#define DUK_SQRT
Definition: duk_config.h:2411
double duk_double_t
Definition: duk_config.h:2103
#define DUK_USE_OS_STRING
Definition: duk_config.h:867
#define DUK_UNLIKELY(x)
Definition: duk_config.h:2703
duk_uint_t duk_uarridx_t
Definition: duk_config.h:2068
#define DUK_USE_NATIVE_CALL_RECLIMIT
Definition: duk_config.h:3025
#define DUK_UINT16_MAX
Definition: duk_config.h:1890
#define DUK_USE_ESBC_MAX_BYTES
Definition: duk_config.h:2959
#define DUK_ISINF
Definition: duk_config.h:2341
#define DUK_USE_STRTAB_RESIZE_CHECK_MASK
Definition: duk_config.h:3074
#define DUK_STRNCMP
Definition: duk_config.h:2226
#define DUK_LOG
Definition: duk_config.h:2408
#define DUK_ATAN2
Definition: duk_config.h:2393
#define DUK_I64_CONSTANT(x)
Definition: duk_config.h:2613
#define DUK_NOINLINE
Definition: duk_config.h:2822
#define DUK_UARRIDX_MAX
Definition: duk_config.h:2070
duk_uint8_t duk_uint_fast8_t
Definition: duk_config.h:1853
#define DUK_USE_HOBJECT_LAYOUT_2
Definition: duk_config.h:2886
#define DUK_FPCLASSIFY
Definition: duk_config.h:2337
#define DUK_EXP
Definition: duk_config.h:2405
#define DUK_USE_HOBJECT_ARRAY_MINGROW_DIVISOR
Definition: duk_config.h:2995
duk_int_t duk_codepoint_t
Definition: duk_config.h:2094
#define DUK_USE_MARK_AND_SWEEP_RECLIMIT
Definition: duk_config.h:3023
#define DUK_USE_HOBJECT_ARRAY_ABANDON_LIMIT
Definition: duk_config.h:2991
#define DUK_VA_COPY(dest, src)
Definition: duk_config.h:2634
#define DUK_USE_HOBJECT_ARRAY_FAST_RESIZE_LIMIT
Definition: duk_config.h:2993
#define DUK_USE_VALSTACK_SHRINK_SLACK_SHIFT
Definition: duk_config.h:3085
#define DUK_UNREF(x)
Definition: duk_config.h:2660
#define DUK_TAN
Definition: duk_config.h:2402
#define DUK_INTERNAL_DECL
Definition: duk_config.h:2736
#define DUK_USE_COMPILER_STRING
Definition: duk_config.h:1546
#define DUK_UINT32_MAX
Definition: duk_config.h:1902
#define DUK_USE_HOBJECT_ARRAY_ABANDON_MINSIZE
Definition: duk_config.h:2992
#define DUK_USE_STRTAB_MINSIZE
Definition: duk_config.h:3072
duk_int_fast32_t duk_int_t
Definition: duk_config.h:2011
duk_int8_t duk_int_fast8_t
Definition: duk_config.h:1854
#define DUK_SIGNBIT
Definition: duk_config.h:2338
#define DUK_ISNAN
Definition: duk_config.h:2340
ptrdiff_t duk_ptrdiff_t
Definition: duk_config.h:1997
duk_int_fast16_t duk_small_int_fast_t
Definition: duk_config.h:2043
#define DUK_ANSI_REALLOC
Definition: duk_config.h:2170
duk_int32_t duk_int_least32_t
Definition: duk_config.h:1852
#define DUK_VSNPRINTF
Definition: duk_config.h:2240
#define DUK_USE_VALSTACK_SHRINK_CHECK_SHIFT
Definition: duk_config.h:3084
size_t duk_size_t
Definition: duk_config.h:1996
duk_int16_t duk_int_fast16_t
Definition: duk_config.h:1856
#define DUK_UINT_MIN
Definition: duk_config.h:2015
float duk_float_t
Definition: duk_config.h:2102
#define DUK_USE_ES6_PROXY
Definition: duk_config.h:2951
#define DUK_USE_HOBJECT_ARRAY_MINGROW_ADD
Definition: duk_config.h:2994
#define DUK_ISFINITE
Definition: duk_config.h:2339
#define DUK_BSWAP32(x)
Definition: duk_config.h:2783
#define DUK_STRLEN
Definition: duk_config.h:2220
duk_uint8_t duk_uint_least8_t
Definition: duk_config.h:1847
#define DUK_WO_NORETURN(stmt)
Definition: duk_config.h:2677
duk_uint_fast32_t duk_uint_t
Definition: duk_config.h:2012
duk_int16_t duk_int_least16_t
Definition: duk_config.h:1850
#define DUK_USE_REGEXP_EXECUTOR_RECLIMIT
Definition: duk_config.h:3051
duk_uint32_t duk_uintmax_t
Definition: duk_config.h:1869
#define DUK_STRCMP
Definition: duk_config.h:2223
#define DUK_USE_HOBJECT_ENTRY_MINGROW_DIVISOR
Definition: duk_config.h:2997
#define DUK_WO_UNREACHABLE(stmt)
Definition: duk_config.h:2688
#define DUK_FABS
Definition: duk_config.h:2369
#define DUK_USE_VALSTACK_LIMIT
Definition: duk_config.h:3083
#define DUK_HOT
Definition: duk_config.h:2720
#define DUK_USE_CBOR_ENC_RECLIMIT
Definition: duk_config.h:2919
#define DUK_ANSI_FREE
Definition: duk_config.h:2176
#define DUK_USE_ESBC_MAX_LINENUMBER
Definition: duk_config.h:2960
#define DUK_DOUBLE_NAN
Definition: duk_config.h:2278
#define DUK_INT32_MAX
Definition: duk_config.h:1904
#define DUK_FP_SUBNORMAL
Definition: duk_config.h:2345
#define DUK_USE_TARGET_INFO
Definition: duk_config.h:3079
#define DUK_SNPRINTF
Definition: duk_config.h:2233
#define DUK_DOUBLE_INFINITY
Definition: duk_config.h:2261
#define DUK_JMPBUF_TYPE
Definition: duk_config.h:2150
#define DUK_FMOD
Definition: duk_config.h:2378
#define DUK_COS
Definition: duk_config.h:2399
#define DUK_USE_STRTAB_GROW_LIMIT
Definition: duk_config.h:3070
#define DUK_SIZE_MAX
Definition: duk_config.h:1991
#define DUK_FLOOR
Definition: duk_config.h:2372
#define DUK_ABORT
Definition: duk_config.h:2146
#define DUK_FP_INFINITE
Definition: duk_config.h:2343
duk_uint32_t duk_uint_fast32_t
Definition: duk_config.h:1857
duk_uint16_t duk_uint_fast16_t
Definition: duk_config.h:1855
#define DUK_LIKELY(x)
Definition: duk_config.h:2700
#define DUK_USE_EXEC_TIMEOUT_CHECK
Definition: duk_custom.h:38
#define DUK_USE_FASTINT
Definition: duk_custom.h:31
#define DUK_HEAP_HAS_FINALIZER_NORESCUE(heap)
Definition: duktape.c:8976
DUK_INTERNAL_DECL duk_hnatfunc * duk_known_hnatfunc(duk_hthread *thr, duk_idx_t idx)
Definition: duktape.c:21377
#define DUK_HCOMPFUNC_GET_FUNCS_SIZE(heap, h)
Definition: duktape.c:7634
#define DUK_OP_POSTINCR
Definition: duktape.c:3629
#define DUK__ISHEXDIGIT(x)
Definition: duktape.c:85791
DUK_INTERNAL_DECL duk_small_int_t duk_raw_write_xutf8(duk_uint8_t *p, duk_ucodepoint_t val)
Definition: duktape.c:13977
DUK_INTERNAL_DECL void duk_heap_free(duk_heap *heap)
Definition: duktape.c:50595
#define DUK_HSTRING_HAS_SYMBOL(x)
Definition: duktape.c:6340
#define DUK_STR_INVALID_INSTANCEOF_RVAL
Definition: duktape.c:3231
#define DUK__ISREG_TEMP(comp_ctx, x)
Definition: duktape.c:69057
#define DUK_OP_LDINT
Definition: duktape.c:3484
#define DUK_HOBJECT_CLASS_BOOLEAN
Definition: duktape.c:6640
DUK_INTERNAL_DECL duk_catcher * duk_hthread_catcher_alloc(duk_hthread *thr)
Definition: duktape.c:65595
#define DUK__BI_MAX_PARTS
Definition: duktape.c:88228
DUK_INTERNAL_DECL duk_hobject * duk_to_hobject(duk_hthread *thr, duk_idx_t idx)
Definition: duktape.c:22464
DUK_INTERNAL_DECL duk_bool_t duk_double_is_neginf(duk_double_t x)
Definition: duktape.c:100612
#define DUK_HBUFFER_EXTERNAL_GET_DATA_PTR(heap, x)
Definition: duktape.c:8703
#define DUK_ASC_LC_M
Definition: duktape.c:10867
DUK_LOCAL_DECL void duk__twodigit_year_fixup(duk_hthread *thr, duk_idx_t idx_val)
Definition: duktape.c:33953
#define DUK_LJ_TYPE_THROW
Definition: duktape.c:8995
DUK_INTERNAL_DECL duk_double_t duk_double_fmin(duk_double_t x, duk_double_t y)
Definition: duktape.c:100720
#define DUK_HCOMPFUNC_GET_CONSTS_COUNT(heap, h)
Definition: duktape.c:7642
DUK_LOCAL duk_uint32_t duk__bc_get_u32(duk_re_matcher_ctx *re_ctx, const duk_uint8_t **pc)
Definition: duktape.c:91831
#define DUK_HCOMPFUNC_GET_VARENV(heap, h)
Definition: duktape.c:7601
#define DUK_MS_FLAG_EMERGENCY
Definition: duktape.c:9014
#define DUK_ERROR_TYPE_INVALID_ARGS(thr)
Definition: duktape.c:10353
DUK_INTERNAL_DECL duk_double_t duk_tval_get_number_unpacked_fastint(duk_tval *tv)
Definition: duktape.c:93728
DUK_EXTERNAL duk_uint_t duk_get_type_mask(duk_hthread *thr, duk_idx_t idx)
Definition: duktape.c:22636
DUK_INTERNAL_DECL void duk_fltunion_big_to_host(duk_float_union *u)
Definition: duktape.c:100909
DUK_LOCAL_DECL void duk__json_dec_objarr_entry(duk_json_dec_ctx *js_ctx)
Definition: duktape.c:38066
DUK_INTERNAL_DECL duk_small_int_t duk_unicode_is_identifier_part(duk_codepoint_t cp)
Definition: duktape.c:13368
DUK_EXTERNAL duk_idx_t duk_push_heapptr(duk_hthread *thr, void *ptr)
Definition: duktape.c:24438
DUK_EXTERNAL void duk_replace(duk_hthread *thr, duk_idx_t to_idx)
Definition: duktape.c:19937
DUK_LOCAL DUK_EXEC_ALWAYS_INLINE_PERF void duk__vm_bitwise_binary_op(duk_hthread *thr, duk_tval *tv_x, duk_tval *tv_y, duk_small_uint_fast_t idx_z, duk_small_uint_fast_t opcode)
Definition: duktape.c:77507
DUK_INTERNAL_DECL duk_ret_t duk_bi_uint8array_plainof(duk_context *ctx)
Definition: duktape.c:28937
#define DUK_ACT_FLAG_TAILCALLED
Definition: duktape.c:8058
DUK_INTERNAL_DECL duk_hthread * duk_get_hthread(duk_hthread *thr, duk_idx_t idx)
Definition: duktape.c:20913
#define DUK__EMIT_FLAG_NO_SHUFFLE_B
Definition: duktape.c:70140
#define DUK_DBG_CMD_APPREQUEST
Definition: duktape.c:9749
#define DUK_CAT_FLAG_CATCH_BINDING_ENABLED
Definition: duktape.c:8088
#define DUK_HEAPHDR_CLEAR_FINALIZED(h)
Definition: duktape.c:4795
DUK_EXTERNAL duk_bool_t duk_check_stack_top(duk_hthread *thr, duk_idx_t top)
Definition: duktape.c:19703
#define DUK_TVAL_DECREF(thr, tv)
Definition: duktape.c:5042
#define DUK_FASTINT_MAX
Definition: duktape.c:1548
#define DUK_ASC_SLASH
Definition: duktape.c:10805
DUK_INTERNAL_DECL duk_ret_t duk_bi_typedarray_byteoffset_getter(duk_context *ctx)
Definition: duktape.c:30663
#define DUK_MS_FLAG_NO_OBJECT_COMPACTION
Definition: duktape.c:9026
#define DUK_STRIDX_TO_LOCALE_STRING
Definition: duktape.c:1696
#define DUK_TOK_DEFAULT
Definition: duktape.c:3857
DUK_LOCAL_DECL void duk__ivalue_var_hstring(duk_compiler_ctx *comp_ctx, duk_ivalue *x, duk_hstring *h)
Definition: duktape.c:71002
#define DUK_TOK_SUB
Definition: duktape.c:3934
#define DUK__FUNCTION_BODY_REQUIRE_SLOTS
Definition: duktape.c:69107
#define DUK__BP_ASSIGNMENT
Definition: duktape.c:69325
#define DUK_ASC_LC_N
Definition: duktape.c:10868
#define DUK__SEQ_BODY(barg, carg)
#define DUK_RETOK_DISJUNCTION
Definition: duktape.c:4125
#define DUK_HSTRING_GET_ARRIDX_FAST(h)
Definition: duktape.c:6439
#define DUK_TOK_ARSHIFT_EQ
Definition: duktape.c:3961
#define DUK_HBUFFER_DYNAMIC_GET_DATA_PTR(heap, x)
Definition: duktape.c:8678
DUK_LOCAL_DECL void duk__ivalue_toplain(duk_compiler_ctx *comp_ctx, duk_ivalue *x)
Definition: duktape.c:71518
DUK_EXTERNAL duk_bool_t duk_get_prop_literal_raw(duk_hthread *thr, duk_idx_t obj_idx, const char *key, duk_size_t key_len)
Definition: duktape.c:17694
#define DUK_ASSERT_STRIDX_VALID(val)
Definition: duktape.c:8212
DUK_EXTERNAL void duk_push_buffer_object(duk_hthread *thr, duk_idx_t idx_buffer, duk_size_t byte_offset, duk_size_t byte_length, duk_uint_t flags)
Definition: duktape.c:23982
DUK_LOCAL duk_bool_t duk__js_samevalue_number(duk_double_t x, duk_double_t y)
Definition: duktape.c:82909
#define DUK_STR_STRING_TOO_LONG
Definition: duktape.c:3218
DUK_EXTERNAL void duk_swap(duk_hthread *thr, duk_idx_t idx1, duk_idx_t idx2)
Definition: duktape.c:19753
DUK_LOCAL duk_uint8_t duk__cbor_decode_peekbyte(duk_cbor_decode_context *dec_ctx)
Definition: duktape.c:31489
#define DUK__PM_SECOND
Definition: duktape.c:32803
DUK_INTERNAL_DECL duk_ret_t duk_bi_string_constructor_from_code_point(duk_context *ctx)
Definition: duktape.c:42901
#define DUK_OP_TRYCATCH
Definition: duktape.c:3678
#define DUK_BIDX_ARRAYBUFFER_PROTOTYPE
Definition: duktape.c:2325
#define DUK_STRIDX_FLAGS
Definition: duktape.c:1723
#define DUK_ASC_LC_U
Definition: duktape.c:10875
DUK_LOCAL void duk__bi_sub_copy(duk__bigint *x, duk__bigint *y, duk__bigint *t)
Definition: duktape.c:88551
DUK_LOCAL const duk_uint8_t * duk__cbor_decode_consume(duk_cbor_decode_context *dec_ctx, duk_size_t len)
Definition: duktape.c:31509
#define DUK_OP_UNUSED216
Definition: duktape.c:3731
#define DUK_LABEL_FLAG_ALLOW_CONTINUE
Definition: duktape.c:4322
DUK_EXTERNAL const char * duk_get_string_default(duk_hthread *thr, duk_idx_t idx, const char *def_value)
Definition: duktape.c:20507
DUK_INTERNAL_DECL duk_tval * duk_require_tval(duk_hthread *thr, duk_idx_t idx)
Definition: duktape.c:19020
DUK_EXTERNAL void duk_free(duk_hthread *thr, void *ptr)
Definition: duktape.c:17588
#define DUK_HEAPHDR_SET_REACHABLE(h)
Definition: duktape.c:4782
DUK_INTERNAL_DECL duk_bool_t duk_js_getvar_envrec(duk_hthread *thr, duk_hobject *env, duk_hstring *name, duk_bool_t throw_flag)
Definition: duktape.c:85164
#define DUK_STR_NOT_NATFUNC
Definition: duktape.c:3209
DUK_INTERNAL_DECL duk_ret_t duk_bi_typedarray_buffer_getter(duk_context *ctx)
Definition: duktape.c:30615
DUK_LOCAL void duk__transform_callback_encode_uri(duk__transform_context *tfm_ctx, const void *udata, duk_codepoint_t cp)
Definition: duktape.c:36779
#define DUK_OP_UNUSED246
Definition: duktape.c:3761
#define DUK_HBUFOBJ_CLAMP_BYTELENGTH(h, len)
Definition: duktape.c:7965
#define DUK__BP_BAND
Definition: duktape.c:69331
DUK_INTERNAL_DECL void duk_js_init_activation_environment_records_delayed(duk_hthread *thr, duk_activation *act)
Definition: duktape.c:84503
#define DUK_BIDX_UINT8ARRAY_PROTOTYPE
Definition: duktape.c:2328
#define DUK_HCOMPFUNC_SET_FUNCS(heap, h, v)
Definition: duktape.c:7587
#define DUK__LOCAL_TZOFFSET_MAXITER
Definition: duktape.c:33136
#define DUK_ACT_FLAG_PREVENT_YIELD
Definition: duktape.c:8060
#define DUK_ASC_UC_S
Definition: duktape.c:10841
DUK_LOCAL void duk__free_run_finalizers(duk_heap *heap)
Definition: duktape.c:50488
#define DUK__SM_PERIOD
Definition: duktape.c:32824
DUK_LOCAL void duk__init_lexer_window(duk_lexer_ctx *lex_ctx)
Definition: duktape.c:86052
#define DUK_TVAL_NEEDS_REFCOUNT_UPDATE(tv)
Definition: duktape.c:4895
const duk_uint8_t duk_unicode_ids_m_let_noa[42]
Definition: duktape.c:93880
#define DUK_DEC_OP(x)
Definition: duktape.c:3434
#define DUK_OP_JUMP
Definition: duktape.c:3482
#define DUK_ERROR_RANGE(thr, msg)
Definition: duktape.c:10337
#define DUK_HBUFFER_ASSERT_VALID(h)
Definition: duktape.c:8740
DUK_INTERNAL_DECL duk_ret_t duk_bi_symbol_constructor_shared(duk_context *ctx)
Definition: duktape.c:44309
#define DUK_HOBJECT_FLAG_NEWENV
Definition: duktape.c:6603
#define DUK_DBG_IB_EOM
Definition: duktape.c:9688
#define DUK_TOK_DO
Definition: duktape.c:3859
DUK_LOCAL duk__sort_key_t duk__hstring_sort_key(duk_hstring *x)
Definition: duktape.c:56941
DUK_INTERNAL_DECL void duk_dup_m3(duk_hthread *thr)
Definition: duktape.c:19831
DUK_INTERNAL_DECL void duk_insert_undefined_n(duk_hthread *thr, duk_idx_t idx, duk_idx_t count)
Definition: duktape.c:19885
#define DUK_HSTRING_HAS_ASCII(x)
Definition: duktape.c:6338
DUK_LOCAL duk_int_t duk__api_coerce_d2i(duk_hthread *thr, duk_idx_t idx, duk_int_t def_value, duk_bool_t require)
Definition: duktape.c:18789
DUK_INTERNAL_DECL void duk_hobject_resize_entrypart(duk_hthread *thr, duk_hobject *obj, duk_uint32_t new_e_size)
Definition: duktape.c:58998
#define DUK_LJ_TYPE_CONTINUE
Definition: duktape.c:8999
#define DUK_OP_IN
Definition: duktape.c:3607
#define DUK_UNICODE_MAX_CESU8_BMP_LENGTH
Definition: duktape.c:10733
#define DUK_TVAL_SET_NUMBER_UPDREF
Definition: duktape.c:5423
DUK_LOCAL_DECL void duk__parse_func_body(duk_compiler_ctx *comp_ctx, duk_bool_t expect_eof, duk_bool_t implicit_return_value, duk_bool_t regexp_after, duk_small_int_t expect_token)
Definition: duktape.c:76300
#define DUK_ENC_OP(op)
Definition: duktape.c:3441
DUK_INTERNAL_DECL duk_ret_t duk_bi_nodejs_buffer_tojson(duk_context *ctx)
Definition: duktape.c:29024
DUK_EXTERNAL const char * duk_get_string(duk_hthread *thr, duk_idx_t idx)
Definition: duktape.c:20443
struct duk_breakpoint duk_breakpoint
Definition: duktape.c:859
#define DUK__ISDIGIT(x)
Definition: duktape.c:85790
DUK_INTERNAL_DECL duk_ret_t duk_bi_duktape_object_enc(duk_context *ctx)
Definition: duktape.c:35163
#define DUK_COMPILER_MAX_BYTECODE_LENGTH
Definition: duktape.c:4252
#define DUK_TOK_INCREMENT
Definition: duktape.c:3939
DUK_LOCAL duk_uint32_t duk__append_jump_offset(duk_re_compiler_ctx *re_ctx, duk_int32_t skip)
Definition: duktape.c:90727
DUK_LOCAL duk_uint32_t duk__tval_fastint_to_arr_idx(duk_tval *tv)
Definition: duktape.c:58031
#define DUK_HOBJECT_A_GET_VALUE_PTR(heap, h, i)
Definition: duktape.c:7016
#define DUK_ASC_LPAREN
Definition: duktape.c:10798
DUK_LOCAL duk_uint8_t * duk__dump_string_prop(duk_hthread *thr, duk_uint8_t *p, duk_bufwriter_ctx *bw_ctx, duk_hobject *func, duk_small_uint_t stridx)
Definition: duktape.c:14495
#define duk_xdef_prop_stridx_short_wec(thr, obj_idx, stridx)
Definition: duktape.c:6209
#define DUK_OP_BXOR_CC
Definition: duktape.c:3586
DUK_LOCAL void duk__cbor_decode_string(duk_cbor_decode_context *dec_ctx, duk_uint8_t ib, duk_uint8_t ai)
Definition: duktape.c:31849
#define DUK_LJ_TYPE_YIELD
Definition: duktape.c:8996
#define DUK__AUGMENT_CALL_RELAX_COUNT
Definition: duktape.c:66122
DUK_INTERNAL_DECL duk_ret_t duk_bi_string_prototype_includes(duk_context *ctx)
Definition: duktape.c:44275
#define DUK_ASC_DOUBLEQUOTE
Definition: duktape.c:10792
DUK_LOCAL duk_small_uint_t duk__handle_return(duk_hthread *thr, duk_activation *entry_act)
Definition: duktape.c:78733
#define DUK_OP_TYPEOFID
Definition: duktape.c:3667
#define DUK_OP_SETALEN
Definition: duktape.c:3714
#define DUK_HOBJECT_DECREF_ALLOWNULL(thr, h)
Definition: duktape.c:5127
#define DUK_BW_WRITE_ENSURE_SLICE(thr, bw, dst_off, dst_len)
Definition: duktape.c:2871
#define DUK_STRIDX_UC_UNDEFINED
Definition: duktape.c:1579
DUK_INTERNAL_DECL duk_hobject * duk_require_hobject_accept_mask(duk_hthread *thr, duk_idx_t idx, duk_uint_t type_mask)
Definition: duktape.c:21213
DUK_INTERNAL_DECL duk_ret_t duk_bi_math_object_hypot(duk_context *ctx)
Definition: duktape.c:40932
#define DUK_HBUFFER_SET_EXTERNAL(x)
Definition: duktape.c:8591
DUK_INTERNAL_DECL duk_ret_t duk_bi_function_prototype_to_string(duk_context *ctx)
Definition: duktape.c:36283
DUK_INTERNAL_DECL duk_ret_t duk_bi_string_prototype_split(duk_context *ctx)
Definition: duktape.c:43592
DUK_INTERNAL_DECL duk_ret_t duk_bi_cbor_encode(duk_context *ctx)
Definition: duktape.c:32624
#define DUK_STR_NUMBER_OUTSIDE_RANGE
Definition: duktape.c:3214
#define DUK_HOBJECT_HAS_EXOTIC_ARRAY(h)
Definition: duktape.c:6764
DUK_INTERNAL_DECL duk_bool_t duk_to_boolean_top_pop(duk_hthread *thr)
Definition: duktape.c:21550
#define DUK_DEC_B(x)
Definition: duktape.c:3436
#define DUK_STR_INVALID_STATE
Definition: duktape.c:3186
#define DUK_DBG_IB_OBJECT
Definition: duktape.c:9706
DUK_LOCAL double duk__asin(double x)
Definition: duktape.c:40799
DUK_INTERNAL_DECL duk_ret_t duk_bi_nodejs_buffer_concat(duk_context *ctx)
Definition: duktape.c:29927
DUK_INTERNAL_DECL void duk_push_hobject(duk_hthread *thr, duk_hobject *h)
Definition: duktape.c:24561
#define DUK_HOBJECT_ALLOWS_FASTREFS(h)
Definition: duktape.c:6831
DUK_LOCAL_DECL void duk__emit_cstring(duk_json_enc_ctx *js_ctx, const char *p)
Definition: duktape.c:38437
DUK_LOCAL void duk__advance_chars(duk_lexer_ctx *lex_ctx, duk_small_uint_t count_chars)
Definition: duktape.c:86211
DUK_EXTERNAL void duk_push_current_thread(duk_hthread *thr)
Definition: duktape.c:23347
DUK_LOCAL void duk__safe_call_adjust_valstack(duk_hthread *thr, duk_idx_t idx_retbase, duk_idx_t num_stack_rets, duk_idx_t num_actual_rets)
Definition: duktape.c:67448
#define DUK_DBLUNION_IS_POSINF(u)
Definition: duktape.c:561
DUK_EXTERNAL void duk_set_global_object(duk_hthread *thr)
Definition: duktape.c:17230
#define DUK_OP_BASL_RC
Definition: duktape.c:3590
#define DUK_STRIDX_UINT8_CLAMPED_ARRAY
Definition: duktape.c:1639
DUK_EXTERNAL duk_bool_t duk_is_pointer(duk_hthread *thr, duk_idx_t idx)
Definition: duktape.c:22761
DUK_LOCAL duk_ret_t duk__js_compile_raw(duk_hthread *thr, void *udata)
Definition: duktape.c:76892
#define DUK_REOP_MATCH
Definition: duktape.c:4488
#define DUK_BW_ADD_PTR(thr, bw_ctx, delta)
Definition: duktape.c:2557
#define DUK_DBG_IB_NOTIFY
Definition: duktape.c:9692
#define DUK_HCOMPFUNC_GET_CONSTS_SIZE(heap, h)
Definition: duktape.c:7630
#define duk_push_i32(thr, val)
Definition: duktape.c:5994
DUK_INTERNAL_DECL void duk_default_free_function(void *udata, void *ptr)
Definition: duktape.c:14336
#define DUK_ERROR_REQUIRE_TYPE_INDEX(thr, idx, expectname, lowmemstr)
Definition: duktape.c:10270
#define DUK_OP_UNUSED233
Definition: duktape.c:3748
#define DUK_TVAL_SET_NULL(tv)
Definition: duktape.c:1295
#define DUK__PM_MINUTE
Definition: duktape.c:32802
DUK_LOCAL_DECL void duk__expr_toplain(duk_compiler_ctx *comp_ctx, duk_ivalue *res, duk_small_uint_t rbp_flags)
Definition: duktape.c:74055
#define DUK__ADVANCEBYTES(lex_ctx, count)
Definition: duktape.c:85799
#define DUK_ASC_PIPE
Definition: duktape.c:10882
#define DUK_HTHREAD_DECREF_NORZ_ALLOWNULL(thr, h)
Definition: duktape.c:5169
#define DUK_DBG_IB_NUMBER
Definition: duktape.c:9705
DUK_LOCAL DUK_ALWAYS_INLINE duk_bool_t duk__resolve_target_fastpath_check(duk_hthread *thr, duk_idx_t idx_func, duk_hobject **out_func, duk_small_uint_t call_flags)
Definition: duktape.c:67213
#define DUK_OP_PREDECP_CR
Definition: duktape.c:3642
#define DUK_S2N_FLAG_ALLOW_AUTO_LEGACY_OCT_INT
Definition: duktape.c:11305
#define DUK_TVAL_SET_BOOLEAN_TRUE(tv)
Definition: duktape.c:1523
#define DUK_OP_SNEQ_RR
Definition: duktape.c:3512
#define DUK_OP_EXP_CC
Definition: duktape.c:3571
DUK_INTERNAL const duk_uint16_t duk_unicode_re_ranges_not_white[24]
Definition: duktape.c:13855
DUK_LOCAL duk_bool_t duk__const_needs_refcount(duk_compiler_ctx *comp_ctx, duk_regconst_t rc)
Definition: duktape.c:71100
#define DUK_HOBJECT_ALIGN_TARGET
Definition: duktape.c:7242
DUK_LOCAL duk_codepoint_t duk__re_canon_next_discontinuity(duk_codepoint_t start, duk_codepoint_t end)
Definition: duktape.c:90820
#define DUK_TOK_RCURLY
Definition: duktape.c:3917
#define DUK_TVAL_SET_FASTINT(tv, i)
Definition: duktape.c:1390
#define DUK_OP_SNEQ
Definition: duktape.c:3511
#define DUK_OP_POSTINCP_RR
Definition: duktape.c:3646
DUK_LOCAL const duk_uint32_t duk__parse_iso8601_control[]
Definition: duktape.c:32852
#define DUK__PI_TZMINUTE
Definition: duktape.c:32795
DUK_LOCAL void duk__remove_slice(duk_re_compiler_ctx *re_ctx, duk_uint32_t data_offset, duk_uint32_t data_length)
Definition: duktape.c:90646
#define DUK_HEAPHDR_IS_STRING(h)
Definition: duktape.c:4840
#define DUK_OP_ENDLABEL
Definition: duktape.c:3675
#define DUK_OP_UNUSED254
Definition: duktape.c:3769
DUK_INTERNAL_DECL void duk_hbuffer_resize(duk_hthread *thr, duk_hbuffer_dynamic *buf, duk_size_t new_size)
Definition: duktape.c:50170
#define DUK__NO_ARRAY_INDEX
Definition: duktape.c:57943
DUK_LOCAL duk_int_t duk__year_from_day(duk_int_t day, duk_small_int_t *out_day_within_year)
Definition: duktape.c:33210
#define DUK_STRIDX_HAS
Definition: duktape.c:1801
#define DUK_STR_REGEXP_EXECUTOR_STEP_LIMIT
Definition: duktape.c:3324
DUK_INTERNAL_DECL duk_hthread * duk_require_hthread(duk_hthread *thr, duk_idx_t idx)
Definition: duktape.c:20925
DUK_EXTERNAL void * duk_get_buffer_data(duk_hthread *thr, duk_idx_t idx, duk_size_t *out_size)
Definition: duktape.c:20781
#define DUK_HCOMPFUNC_GET_FUNCS_COUNT(heap, h)
Definition: duktape.c:7644
#define DUK_STR_RESULT_TOO_LONG
Definition: duktape.c:3229
DUK_INTERNAL_DECL void duk_dblunion_big_to_host(duk_double_union *u)
Definition: duktape.c:100893
DUK_INTERNAL_DECL duk_ret_t duk_bi_array_prototype_concat(duk_context *ctx)
Definition: duktape.c:26307
#define DUK_TVAL_SET_FASTINT_UPDREF
Definition: duktape.c:5436
#define DUK_HSTRING_GET_DATA(x)
Definition: duktape.c:6428
DUK_INTERNAL_DECL duk_bool_t duk_bi_date_is_leap_year(duk_int_t year)
Definition: duktape.c:33146
#define DUK_OP_STREG
Definition: duktape.c:3481
DUK_LOCAL_DECL void duk__init_varmap_and_prologue_for_pass2(duk_compiler_ctx *comp_ctx, duk_regconst_t *out_stmt_value_reg)
Definition: duktape.c:75989
DUK_INTERNAL_DECL void duk_pop_unsafe(duk_hthread *thr)
Definition: duktape.c:24726
#define DUK_OP_DECLVAR_RC
Definition: duktape.c:3658
#define DUK_TAG_POINTER
Definition: duktape.c:1264
#define DUK_OP_GETPROP_RR
Definition: duktape.c:3613
DUK_INTERNAL_DECL duk_size_t duk_unicode_unvalidated_utf8_length(const duk_uint8_t *data, duk_size_t blen)
Definition: duktape.c:12974
#define DUK_REOP_RANGES
Definition: duktape.c:4491
DUK_INTERNAL_DECL duk_ret_t duk_bi_array_prototype_unshift(duk_context *ctx)
Definition: duktape.c:27352
DUK_INTERNAL_DECL duk_hboundfunc * duk_hboundfunc_alloc(duk_heap *heap, duk_uint_t hobject_flags)
Definition: duktape.c:56603
#define DUK_OP_INITENUM
Definition: duktape.c:3715
#define DUK_OP_UNUSED231
Definition: duktape.c:3746
DUK_INTERNAL_DECL duk_ret_t duk_bi_error_constructor_shared(duk_context *ctx)
Definition: duktape.c:35792
#define DUK_ASC_LC_Z
Definition: duktape.c:10880
#define DUK_HSTRING_IS_ASCII(x)
Definition: duktape.c:6373
DUK_INTERNAL_DECL void duk_refzero_check_fast(duk_hthread *thr)
Definition: duktape.c:54597
DUK_INTERNAL_DECL duk_ret_t duk_bi_boolean_constructor(duk_context *ctx)
Definition: duktape.c:27784
#define DUK_HEAPHDR_SET_TEMPROOT(h)
Definition: duktape.c:4786
#define DUK_ASC_2
Definition: duktape.c:10808
#define DUK_REOP_ASSERT_WORD_BOUNDARY
Definition: duktape.c:4505
DUK_INTERNAL_DECL duk_ret_t duk_bi_array_prototype_sort(duk_context *ctx)
Definition: duktape.c:26990
#define DUK_HOBJECT_CLASS_REGEXP
Definition: duktape.c:6646
#define DUK_HEAP_HAS_DEBUGGER_PAUSED(heap)
Definition: duktape.c:8977
DUK_INTERNAL_DECL duk_int32_t duk_double_to_int32_t(duk_double_t x)
Definition: duktape.c:100511
#define DUK_OP_NONE
Definition: duktape.c:3771
#define DUK_LABEL_FLAG_ALLOW_BREAK
Definition: duktape.c:4321
DUK_INTERNAL_DECL duk_uint16_t duk_js_touint16(duk_hthread *thr, duk_tval *tv)
Definition: duktape.c:82839
#define DUK_OP_LNOT
Definition: duktape.c:3493
DUK_LOCAL void duk__cbor_decode_objarr_exit(duk_cbor_decode_context *dec_ctx)
Definition: duktape.c:31452
DUK_INTERNAL_DECL duk_uint32_t duk_double_to_uint32_t(duk_double_t x)
Definition: duktape.c:100519
#define DUK_HEAP_HAS_MARKANDSWEEP_RECLIMIT_REACHED(heap)
Definition: duktape.c:8974
#define DUK_DECL_TYPE_VAR
Definition: duktape.c:4324
DUK_LOCAL void duk__bi_mul_small(duk__bigint *x, duk__bigint *y, duk_uint32_t z)
Definition: duktape.c:88685
DUK_EXTERNAL duk_idx_t duk_require_top_index(duk_hthread *thr)
Definition: duktape.c:19309
#define DUK__NARGS_VARARGS_MARKER
Definition: duktape.c:64542
DUK_INTERNAL_DECL void duk_hthread_activation_unwind_reuse_norz(duk_hthread *thr)
Definition: duktape.c:65859
#define DUK_OP_UNUSED244
Definition: duktape.c:3759
#define DUK_STR_NOT_CALLABLE
Definition: duktape.c:3191
#define DUK_STR_DEC_RECLIMIT
Definition: duktape.c:3240
#define DUK_STR_TOPRIMITIVE_FAILED
Definition: duktape.c:3213
DUK_INTERNAL_DECL duk_ret_t duk_bi_object_constructor_is_sealed_frozen_shared(duk_context *ctx)
Definition: duktape.c:41570
#define DUK_TAG_NUMBER
Definition: duktape.c:1257
DUK_EXTERNAL void duk_dump_function(duk_hthread *thr)
Definition: duktape.c:15102
#define DUK_STRIDX_BRACKETED_ELLIPSIS
Definition: duktape.c:1774
DUK_EXTERNAL duk_idx_t duk_get_top_index(duk_hthread *thr)
Definition: duktape.c:19281
#define DUK_STRIDX_ENUMERABLE
Definition: duktape.c:1690
#define DUK_TOK_MUL
Definition: duktape.c:3935
#define DUK_STR_REGEXP_SUPPORT_DISABLED
Definition: duktape.c:3263
#define DUK_HBUFFER_DYNAMIC_GET_SIZE(x)
Definition: duktape.c:8656
#define DUK_JSON_ENC_LOOPARRAY
Definition: duktape.c:11038
DUK_EXTERNAL void * duk_get_heapptr_default(duk_hthread *thr, duk_idx_t idx, void *def_value)
Definition: duktape.c:21128
#define DUK_HEAPHDR_GET_TYPE(h)
Definition: duktape.c:4752
#define DUK__SER_STRING
Definition: duktape.c:14432
#define DUK_OP_PREDECP
Definition: duktape.c:3640
DUK_INTERNAL_DECL duk_uint8_t * duk_bw_resize(duk_hthread *thr, duk_bufwriter_ctx *bw_ctx, duk_size_t sz)
Definition: duktape.c:100192
DUK_LOCAL void duk__to_primitive_helper(duk_hthread *thr, duk_idx_t idx, duk_int_t hint, duk_bool_t check_symbol)
Definition: duktape.c:21440
DUK_LOCAL_DECL void duk__json_enc_quote_string(duk_json_enc_ctx *js_ctx, duk_hstring *h_str)
Definition: duktape.c:38565
#define DUK_S2N_FLAG_ALLOW_FRAC
Definition: duktape.c:11283
#define DUK_BC_TRYCATCH_FLAG_HAVE_FINALLY
Definition: duktape.c:3778
DUK_INTERNAL_DECL void duk_dup_1(duk_hthread *thr)
Definition: duktape.c:19819
#define DUK_OP_LDTRUE
Definition: duktape.c:3489
#define DUK_BW_SET_PTR(thr, bw_ctx, ptr)
Definition: duktape.c:2553
#define DUK_HOBJECT_GET_PROTOTYPE(heap, h)
Definition: duktape.c:7188
DUK_INTERNAL_DECL duk_ret_t duk_bi_string_prototype_char_at(duk_context *ctx)
Definition: duktape.c:42945
DUK_EXTERNAL duk_bool_t duk_del_prop_literal_raw(duk_hthread *thr, duk_idx_t obj_idx, const char *key, duk_size_t key_len)
Definition: duktape.c:17941
DUK_LOCAL double duk__atan(double x)
Definition: duktape.c:40802
DUK_EXTERNAL duk_double_t duk_opt_number(duk_hthread *thr, duk_idx_t idx, duk_double_t def_value)
Definition: duktape.c:20331
#define DUK_TVAL_IS_NUMBER(tv)
Definition: duktape.c:1489
DUK_INTERNAL_DECL duk_ret_t duk_bi_object_prototype_defineaccessor(duk_context *ctx)
Definition: duktape.c:42064
DUK_LOCAL const duk_uint8_t duk__json_decstr_lookup[256]
Definition: duktape.c:37478
DUK_INTERNAL_DECL void duk_bw_insert_ensure_slice(duk_hthread *thr, duk_bufwriter_ctx *bw, duk_size_t dst_off, duk_size_t src_off, duk_size_t len)
Definition: duktape.c:100343
#define DUK_IVAL_VAR
Definition: duktape.c:4266
#define DUK_NOINLINE_PERF
Definition: duktape.c:5906
#define DUK_HOBJECT_E_GET_FLAGS_PTR(heap, h, i)
Definition: duktape.c:7014
#define DUK_STR_INVALID_ARG_NAME
Definition: duktape.c:3289
DUK_INTERNAL_DECL duk_ret_t duk_bi_regexp_prototype_tostring(duk_context *ctx)
Definition: duktape.c:42573
DUK_LOCAL void duk__reconfig_valstack_ecma_return(duk_hthread *thr)
Definition: duktape.c:77947
DUK_EXTERNAL duk_int_t duk_get_current_magic(duk_hthread *thr)
Definition: duktape.c:15613
DUK_INTERNAL_DECL duk_bool_t duk_get_prop_stridx_boolean(duk_hthread *thr, duk_idx_t obj_idx, duk_small_uint_t stridx, duk_bool_t *out_has_prop)
Definition: duktape.c:17734
DUK_LOCAL void duk__bw_update_ptrs(duk_hthread *thr, duk_bufwriter_ctx *bw_ctx, duk_size_t curr_offset, duk_size_t new_length)
Definition: duktape.c:100153
DUK_EXTERNAL void duk_debugger_detach(duk_hthread *thr)
Definition: duktape.c:17043
DUK_EXTERNAL duk_bool_t duk_del_prop_index(duk_hthread *thr, duk_idx_t obj_idx, duk_uarridx_t arr_idx)
Definition: duktape.c:17952
DUK_INTERNAL_DECL duk_ret_t duk_bi_date_constructor_utc(duk_context *ctx)
Definition: duktape.c:34222
#define DUK_OP_UNP
Definition: duktape.c:3495
#define DUK_HOBJECT_FLAG_CONSTRUCTABLE
Definition: duktape.c:6592
#define DUK_DBG_CMD_GETOBJPROPDESC
Definition: duktape.c:9751
DUK_INTERNAL_DECL duk_uarridx_t duk_js_to_arrayindex_string(const duk_uint8_t *str, duk_uint32_t blen)
Definition: duktape.c:83816
DUK_INTERNAL_DECL const char * duk_push_string_tval_readable_error(duk_hthread *thr, duk_tval *tv)
Definition: duktape.c:25510
#define DUK_ERROR_TYPE(thr, msg)
Definition: duktape.c:10379
DUK_LOCAL duk_bool_t duk__defaultvalue_coerce_attempt(duk_hthread *thr, duk_idx_t idx, duk_small_uint_t func_stridx)
Definition: duktape.c:21401
#define DUK_TOK_EQUALSIGN
Definition: duktape.c:3953
DUK_INTERNAL_DECL duk_ret_t duk_bi_nodejs_buffer_fill(duk_context *ctx)
Definition: duktape.c:29121
DUK_LOCAL_DECL void duk__update_label_flags(duk_compiler_ctx *comp_ctx, duk_int_t label_id, duk_small_uint_t flags)
Definition: duktape.c:71789
DUK_LOCAL void duk__call_prop_prep_stack(duk_hthread *thr, duk_idx_t normalized_obj_idx, duk_idx_t nargs)
Definition: duktape.c:15276
DUK_LOCAL void duk__cbor_decode_join_buffers(duk_cbor_decode_context *dec_ctx, duk_idx_t count)
Definition: duktape.c:31711
DUK_EXTERNAL duk_ret_t duk_uri_error_stash(duk_hthread *thr, const char *fmt,...)
Definition: duktape.c:25184
DUK_LOCAL duk_hstring * duk__auto_unbox_symbol(duk_hthread *thr, duk_tval *tv_arg)
Definition: duktape.c:44372
#define DUK_OP_PREINCP_RR
Definition: duktape.c:3636
#define DUK_OP_INSTOF_CC
Definition: duktape.c:3606
DUK_INTERNAL_DECL duk_hstring * duk_push_uint_to_hstring(duk_hthread *thr, duk_uint_t i)
Definition: duktape.c:23207
#define DUK_HEAP_CLEAR_MARKANDSWEEP_RECLIMIT_REACHED(heap)
Definition: duktape.c:8984
#define duk_push_i64(thr, val)
Definition: duktape.c:5990
#define DUK_OP_UNM
Definition: duktape.c:3494
DUK_LOCAL const duk_uint8_t * duk__utf8_backtrack(duk_hthread *thr, const duk_uint8_t **ptr, const duk_uint8_t *ptr_start, const duk_uint8_t *ptr_end, duk_uint_fast32_t count)
Definition: duktape.c:91847
DUK_INTERNAL_DECL duk_hthread * duk_hthread_alloc_unchecked(duk_heap *heap, duk_uint_t hobject_flags)
Definition: duktape.c:56645
#define DUK_STR_NOT_WRITABLE
Definition: duktape.c:3193
DUK_LOCAL double duk__fmax_fixed(double x, double y)
Definition: duktape.c:40680
#define DUK_ERROR_RAW_FMT1(thr, file, line, err, fmt, arg1)
Definition: duktape.c:10115
#define DUK_CAT_LABEL_SHIFT
Definition: duktape.c:8084
#define DUK_OP_MUL_RR
Definition: duktape.c:3553
#define DUK_HBOUNDFUNC_MAX_ARGS
Definition: duktape.c:7853
DUK_INTERNAL void duk_err_longjmp(duk_hthread *thr)
Definition: duktape.c:49620
#define DUK_PC2LINE_MAX_DIFF_LENGTH
Definition: duktape.c:7256
#define DUK_OP_INITSET
Definition: duktape.c:3710
#define DUK_BIDX_EVAL_ERROR_PROTOTYPE
Definition: duktape.c:2308
#define DUK_RAW_WRITEINC_DOUBLE_BE(ptr, val)
Definition: duktape.c:2446
#define DUK_OP_NEXTENUM
Definition: duktape.c:3716
DUK_INTERNAL_DECL void duk_heap_mark_and_sweep(duk_heap *heap, duk_small_uint_t flags)
Definition: duktape.c:53270
#define DUK_STR_INVALID_LABEL
Definition: duktape.c:3270
DUK_EXTERNAL duk_bool_t duk_del_prop(duk_hthread *thr, duk_idx_t obj_idx)
Definition: duktape.c:17899
#define DUK_RETOK_ATOM_PERIOD
Definition: duktape.c:4133
DUK_LOCAL_DECL duk_bool_t duk__get_own_propdesc_raw(duk_hthread *thr, duk_hobject *obj, duk_hstring *key, duk_uint32_t arr_idx, duk_propdesc *out_desc, duk_small_uint_t flags)
Definition: duktape.c:59769
#define DUK_HOBJECT_POSTINC_ENEXT(h)
Definition: duktape.c:7137
#define DUK_DBG_CMD_GETBYTECODE
Definition: duktape.c:9748
#define DUK_STRIDX_LC_BUFFER
Definition: duktape.c:1837
#define DUK_OP_DELPROP
Definition: duktape.c:3622
#define DUK_DEC_A(x)
Definition: duktape.c:3435
#define DUK_HBUFFER_INCREF(thr, h)
Definition: duktape.c:5054
#define DUK_STRIDX_UC_ARGUMENTS
Definition: duktape.c:1588
#define DUK__FLD_FLOAT
Definition: duktape.c:30046
DUK_LOCAL void duk__cbor_decode_rewind(duk_cbor_decode_context *dec_ctx, duk_size_t len)
Definition: duktape.c:31496
DUK_INTERNAL_DECL duk_double_t duk_to_number_m1(duk_hthread *thr)
Definition: duktape.c:21586
#define DUK__IEEE_DOUBLE_EXP_BIAS
Definition: duktape.c:88173
#define DUK_STRIDX_LC_POINTER
Definition: duktape.c:1864
#define DUK_FASTINT_MIN
Definition: duktape.c:1547
DUK_EXTERNAL duk_bool_t duk_get_boolean(duk_hthread *thr, duk_idx_t idx)
Definition: duktape.c:20231
DUK_LOCAL duk_ret_t duk__decode_helper(duk_hthread *thr, duk__decode_context *dec_ctx)
Definition: duktape.c:35455
#define DUK_STR_FMT_PTR
Definition: duktape.c:3235
DUK_EXTERNAL void duk_fatal_raw(duk_hthread *thr, const char *err_msg)
Definition: duktape.c:25067
DUK_LOCAL void duk__handle_finally(duk_hthread *thr, duk_tval *tv_val_unstable, duk_small_uint_t lj_type)
Definition: duktape.c:78165
DUK_EXTERNAL void duk_inspect_value(duk_hthread *thr, duk_idx_t idx)
Definition: duktape.c:17343
#define DUK_OP_DIV_CR
Definition: duktape.c:3559
#define DUK_HOBJECT_P_COMPUTE_SIZE(n_ent, n_arr, n_hash)
Definition: duktape.c:6956
DUK_LOCAL double duk__log(double x)
Definition: duktape.c:40817
#define DUK__ERRFMT_BUFSIZE
Definition: duktape.c:12462
#define DUK__ITER_SOME
Definition: duktape.c:27508
DUK_LOCAL duk_bool_t duk__getprop_fastpath_bufobj_tval(duk_hthread *thr, duk_hobject *obj, duk_tval *tv_key)
Definition: duktape.c:60347
#define DUK_BIDX_SYMBOL_PROTOTYPE
Definition: duktape.c:2324
#define DUK__PROP_FLAGS_BITS
Definition: duktape.c:64537
DUK_INTERNAL_DECL duk_ret_t duk_bi_math_object_imul(duk_context *ctx)
Definition: duktape.c:41076
#define DUK_ALLOC(heap, size)
Definition: duktape.c:9168
DUK_INTERNAL_DECL duk_ret_t duk_bi_array_prototype_to_string(duk_context *ctx)
Definition: duktape.c:26269
DUK_INTERNAL_DECL duk_uint16_t duk_raw_read_u16_be(const duk_uint8_t *p)
Definition: duktape.c:13899
DUK_LOCAL void * duk__get_buffer_helper(duk_hthread *thr, duk_idx_t idx, duk_size_t *out_size, void *def_ptr, duk_size_t def_size, duk_bool_t throw_flag)
Definition: duktape.c:20635
DUK_LOCAL duk_int_t duk__try_push_vsprintf(duk_hthread *thr, void *buf, duk_size_t sz, const char *fmt, va_list ap)
Definition: duktape.c:23404
DUK_LOCAL void duk__activation_unwind_nofree_norz(duk_hthread *thr)
Definition: duktape.c:65675
DUK_LOCAL void duk__cbor_decode_skip_aival_int(duk_cbor_decode_context *dec_ctx, duk_uint8_t ib)
Definition: duktape.c:31646
#define DUK_DBLUNION_SET_NAN(u)
Definition: duktape.c:553
#define DUK__EXPR_FLAG_REQUIRE_INIT
Definition: duktape.c:73929
DUK_EXTERNAL duk_bool_t duk_is_c_function(duk_hthread *thr, duk_idx_t idx)
Definition: duktape.c:22851
DUK_INTERNAL const duk_uint16_t duk_unicode_re_ranges_not_digit[4]
Definition: duktape.c:13849
DUK_LOCAL void duk__cbor_encode_value(duk_cbor_encode_context *enc_ctx)
Definition: duktape.c:31354
#define DUK_OP_INITGET
Definition: duktape.c:3711
#define DUK_OP_MUL_CC
Definition: duktape.c:3556
#define DUK_STRIDX_INT_FORMALS
Definition: duktape.c:1876
DUK_EXTERNAL void duk_pop_3(duk_hthread *thr)
Definition: duktape.c:24833
#define DUK_ASC_AMP
Definition: duktape.c:10796
#define DUK_OP_LDFALSE
Definition: duktape.c:3490
#define DUK_STR_INVALID_EXPRESSION
Definition: duktape.c:3275
#define DUK_STR_INVALID_ARRAY_LENGTH
Definition: duktape.c:3247
#define DUK_ASC_NUL
Definition: duktape.c:10758
#define DUK_TAG_NULL
Definition: duktape.c:1262
DUK_LOCAL void duk__grow_props_for_new_entry_item(duk_hthread *thr, duk_hobject *obj)
Definition: duktape.c:59021
#define DUK_STR_INVALID_FUNC_NAME
Definition: duktape.c:3290
#define DUK_TVAL_SET_U32(tv, val)
Definition: duktape.c:1328
#define DUK_HARRAY_LENGTH_NONWRITABLE(h)
Definition: duktape.c:8470
#define DUK_RETOK_EOF
Definition: duktape.c:4124
#define DUK_FREE_CHECKED(thr, ptr)
Definition: duktape.c:9183
DUK_INTERNAL_DECL void duk_pop_2_nodecref_unsafe(duk_hthread *thr)
Definition: duktape.c:24819
#define DUK_DBLUNION_GET_LOW32(u)
Definition: duktape.c:393
#define DUK_RE_EXECUTE_STEPS_LIMIT
Definition: duktape.c:4485
#define DUK_DBG_IB_NULL
Definition: duktape.c:9702
DUK_INTERNAL_DECL void duk_xdef_prop_stridx_short_raw(duk_hthread *thr, duk_uint_t packed_args)
Definition: duktape.c:18118
DUK_LOCAL duk_codepoint_t duk__lexer_parse_escape(duk_lexer_ctx *lex_ctx, duk_bool_t allow_es6)
Definition: duktape.c:86354
DUK_INTERNAL_DECL void duk_dup_2(duk_hthread *thr)
Definition: duktape.c:19823
DUK_LOCAL_DECL void duk__emit_a_bc(duk_compiler_ctx *comp_ctx, duk_small_uint_t op_flags, duk_regconst_t a, duk_regconst_t bc)
Definition: duktape.c:70567
#define DUK_HOBJECT_FLAG_NAMEBINDING
Definition: duktape.c:6604
#define DUK_TOK_THIS
Definition: duktape.c:3870
DUK_EXTERNAL duk_idx_t duk_push_error_object_va_raw(duk_hthread *thr, duk_errcode_t err_code, const char *filename, duk_int_t line, const char *fmt, va_list ap)
Definition: duktape.c:24105
#define DUK__CONSTP_C(ins)
Definition: duktape.c:79961
DUK_INTERNAL_DECL double duk_js_arith_mod(double x, double y)
Definition: duktape.c:65938
#define DUK_OP_PUTPROP_RC
Definition: duktape.c:3620
#define DUK_HOBJECT_CMASK_BOOLEAN
Definition: duktape.c:6674
DUK_LOCAL duk_hstring * duk__strtable_alloc_hstring(duk_heap *heap, const duk_uint8_t *str, duk_uint32_t blen, duk_uint32_t strhash, const duk_uint8_t *extdata)
Definition: duktape.c:55472
DUK_EXTERNAL void duk_map_string(duk_hthread *thr, duk_idx_t idx, duk_map_char_function callback, void *udata)
Definition: duktape.c:25785
DUK_INTERNAL_DECL duk_ret_t duk_bi_buffer_writefield(duk_context *ctx)
Definition: duktape.c:30317
#define DUK_OP_INVLHS
Definition: duktape.c:3683
#define DUK__SETTEMP_CHECKMAX(comp_ctx, x)
Definition: duktape.c:69065
#define DUK_OP_UNUSED213
Definition: duktape.c:3728
DUK_EXTERNAL const char * duk_buffer_to_string(duk_hthread *thr, duk_idx_t idx)
Definition: duktape.c:22192
#define DUK_ASC_EXCLAMATION
Definition: duktape.c:10791
#define DUK_TOK_LNOT
Definition: duktape.c:3947
DUK_LOCAL duk_small_int_t duk__decode_hex_escape(const duk_uint8_t *p, duk_small_int_t n)
Definition: duktape.c:36735
#define DUK__MAX_OUTPUT_DIGITS
Definition: duktape.c:88801
#define DUK_CAT_GET_TYPE(c)
Definition: duktape.c:8095
#define DUK_LEXER_BUFFER_SIZE
Definition: duktape.c:3839
#define DUK_OP_UNUSED214
Definition: duktape.c:3729
#define DUK_BC_TRYCATCH_FLAG_CATCH_BINDING
Definition: duktape.c:3779
#define DUK_OP_UNUSED224
Definition: duktape.c:3739
DUK_INTERNAL_DECL duk_double_t duk_time_get_ecmascript_time(duk_hthread *thr)
Definition: duktape.c:25978
#define DUK_HEAPHDR_SET_NEXT(heap, h, val)
Definition: duktape.c:4701
#define DUK__EQ_BODY(barg, carg)
#define DUK_OP_SUB
Definition: duktape.c:3547
#define DUK_STRIDX_TO_UTC_STRING
Definition: duktape.c:1702
#define DUK_LFUNC_NARGS_MAX
Definition: duktape.c:1539
#define DUK_N2S_FLAG_FIXED_FORMAT
Definition: duktape.c:11232
DUK_LOCAL void duk__bi_add_small(duk__bigint *x, duk__bigint *y, duk_uint32_t z)
Definition: duktape.c:88439
DUK_INTERNAL_DECL duk_bool_t duk_double_equals(duk_double_t x, duk_double_t y)
Definition: duktape.c:100925
#define DUK_HEAP_SET_FINALIZER_NORESCUE(heap)
Definition: duktape.c:8981
#define DUK_OP_CALL7
Definition: duktape.c:3697
#define DUK__PM_TZHOUR
Definition: duktape.c:32805
DUK_INTERNAL_DECL void duk_push_hbuffer(duk_hthread *thr, duk_hbuffer *h)
Definition: duktape.c:24571
#define DUK_STR_NO_SOURCECODE
Definition: duktape.c:3228
#define DUK__REPLACE_TO_TVPTR(thr, tv_ptr)
Definition: duktape.c:77176
#define DUK__MAX_RE_QUANT_DIGITS
Definition: duktape.c:85787
DUK_INTERNAL_DECL void * duk_default_alloc_function(void *udata, duk_size_t size)
Definition: duktape.c:14320
#define DUK_MS_FLAG_POSTPONE_RESCUE
Definition: duktape.c:9020
#define DUK__ISREG(x)
Definition: duktape.c:69055
#define DUK_HEAPHDR_STRING_INIT_NULLS(h)
Definition: duktape.c:4824
DUK_INTERNAL_DECL void duk_js_putvar_envrec(duk_hthread *thr, duk_hobject *env, duk_hstring *name, duk_tval *val, duk_bool_t strict)
Definition: duktape.c:85298
#define DUK_STR_INVALID_TRY
Definition: duktape.c:3284
#define DUK__PM_DAY
Definition: duktape.c:32800
DUK_INTERNAL_DECL void duk_native_stack_check(duk_hthread *thr)
Definition: duktape.c:66107
DUK_LOCAL void duk__handle_catch_part1(duk_hthread *thr, duk_tval *tv_val_unstable, duk_small_uint_t lj_type, volatile duk_bool_t *out_delayed_catch_setup)
Definition: duktape.c:78026
#define duk_put_prop_stridx_short(thr, obj_idx, stridx)
Definition: duktape.c:6158
DUK_INTERNAL_DECL void duk_proxy_ownkeys_postprocess(duk_hthread *thr, duk_hobject *h_proxy_target, duk_uint_t flags)
Definition: duktape.c:42272
#define DUK__BP_SHIFT
Definition: duktape.c:69334
DUK_INTERNAL_DECL duk_ret_t duk_bi_textencoder_prototype_encoding_getter(duk_context *ctx)
Definition: duktape.c:35599
#define DUK_HOBJECT_CLASS_INT32ARRAY
Definition: duktape.c:6662
DUK_INTERNAL_DECL duk_hbuffer * duk_get_hbuffer(duk_hthread *thr, duk_idx_t idx)
Definition: duktape.c:20895
#define DUK__PUTPROP_BODY(aarg, barg, carg)
DUK_INTERNAL_DECL void duk_hbufobj_validated_write(duk_hthread *thr, duk_hbufobj *h_bufobj, duk_uint8_t *p, duk_small_uint_t elem_size)
Definition: duktape.c:28260
DUK_LOCAL DUK_ALWAYS_INLINE void duk__pop_unsafe_raw(duk_hthread *thr)
Definition: duktape.c:24697
#define DUK_TOK_ADD
Definition: duktape.c:3933
DUK_LOCAL_DECL void duk__json_dec_buffer(duk_json_dec_ctx *js_ctx)
Definition: duktape.c:37945
DUK_LOCAL DUK_EXEC_NOINLINE_PERF duk_instr_t * duk__handle_op_endtry(duk_hthread *thr, duk_uint_fast32_t ins)
Definition: duktape.c:79565
DUK_LOCAL void duk__handle_oldenv_for_call(duk_hthread *thr, duk_hobject *func, duk_activation *act)
Definition: duktape.c:67033
#define DUK_BW_WRITE_ENSURE_U8(thr, bw_ctx, val)
Definition: duktape.c:2770
DUK_INTERNAL_DECL void duk_pop_nodecref_unsafe(duk_hthread *thr)
Definition: duktape.c:24730
DUK_INTERNAL_DECL duk_small_int_t duk_unicode_encode_xutf8(duk_ucodepoint_t cp, duk_uint8_t *out)
Definition: duktape.c:12729
DUK_EXTERNAL void duk_push_global_object(duk_hthread *thr)
Definition: duktape.c:23357
#define DUK_OP_UNUSED225
Definition: duktape.c:3740
DUK_EXTERNAL duk_ret_t duk_reference_error_stash(duk_hthread *thr, const char *fmt,...)
Definition: duktape.c:25172
#define DUK_HBUFOBJ_VALID_SLICE(h)
Definition: duktape.c:7941
#define DUK_BW_WRITE_RAW_U8_3(thr, bw_ctx, val1, val2, val3)
Definition: duktape.c:2629
#define duk_push_hthread(thr, h)
Definition: duktape.c:6089
DUK_INTERNAL_DECL duk_ret_t duk_bi_array_prototype_join_shared(duk_context *ctx)
Definition: duktape.c:26443
#define DUK_TVAL_INCREF_FAST(thr, tv)
Definition: duktape.c:4904
#define DUK_STRIDX_LC_ARGUMENTS
Definition: duktape.c:1780
#define DUK_STRIDX_GLOBAL
Definition: duktape.c:1660
#define DUK__IDX_HSIZE
Definition: duktape.c:17337
DUK_INTERNAL_DECL duk_size_t duk_hstring_get_charlen(duk_hstring *h)
Definition: duktape.c:64427
DUK_INTERNAL_DECL duk_ret_t duk_bi_reflect_object_get(duk_context *ctx)
Definition: duktape.c:42389
DUK_INTERNAL_DECL void duk_push_c_function_builtin_noconstruct(duk_hthread *thr, duk_c_function func, duk_int_t nargs)
Definition: duktape.c:23834
DUK_LOCAL const duk_uint8_t duk__token_lbp[]
Definition: duktape.c:69352
#define DUK_EXEC_NOINLINE_PERF
Definition: duktape.c:5917
DUK_LOCAL duk_small_uint_t duk__get_symbol_type(duk_hstring *h)
Definition: duktape.c:18753
DUK_LOCAL double duk__sin(double x)
Definition: duktape.c:40820
DUK_LOCAL_DECL void duk__emit_bc(duk_compiler_ctx *comp_ctx, duk_small_uint_t op, duk_regconst_t bc)
Definition: duktape.c:70625
DUK_LOCAL void duk__add_enum_key_stridx(duk_hthread *thr, duk_small_uint_t stridx)
Definition: duktape.c:57067
#define DUK_HTHREAD_ASSERT_VALID(thr)
Definition: duktape.c:8190
DUK_LOCAL void duk__clamp_startend_negidx_shifted(duk_hthread *thr, duk_int_t buffer_length, duk_uint8_t buffer_shift, duk_idx_t idx_start, duk_idx_t idx_end, duk_int_t *out_start_offset, duk_int_t *out_end_offset)
Definition: duktape.c:28114
DUK_INTERNAL_DECL duk_bool_t duk_hstring_equals_ascii_cstring(duk_hstring *h, const char *cstr)
Definition: duktape.c:64451
DUK_LOCAL DUK_EXEC_NOINLINE_PERF void duk__handle_break_or_continue(duk_hthread *thr, duk_uint_t label_id, duk_small_uint_t lj_type)
Definition: duktape.c:78669
DUK_INTERNAL_DECL duk_ret_t duk_bi_function_prototype_apply(duk_context *ctx)
Definition: duktape.c:36362
DUK_INTERNAL_DECL duk_bool_t duk_xget_owndataprop_stridx_short_raw(duk_hthread *thr, duk_uint_t packed_args)
Definition: duktape.c:17796
#define DUK_HSTRING_NO_ARRAY_INDEX
Definition: duktape.c:6436
DUK_INTERNAL void duk_heap_strtable_free(duk_heap *heap)
Definition: duktape.c:56354
DUK_INTERNAL_DECL duk_ret_t duk_bi_reflect_object_set(duk_context *ctx)
Definition: duktape.c:42431
#define DUK_ASC_UC_T
Definition: duktape.c:10842
DUK_LOCAL DUK_NOINLINE void duk__call_callstack_limit_check_slowpath(duk_hthread *thr)
Definition: duktape.c:66161
#define DUK_GETDESC_FLAG_PUSH_VALUE
Definition: duktape.c:6861
DUK_EXTERNAL duk_bool_t duk_is_lightfunc(duk_hthread *thr, duk_idx_t idx)
Definition: duktape.c:22766
#define DUK_COMPARE_FLAG_NEGATE
Definition: duktape.c:11109
#define DUK_TOK_IDENTIFIER
Definition: duktape.c:3848
DUK_INTERNAL_DECL duk_uint_t duk_get_type_mask_tval(duk_tval *tv)
Definition: duktape.c:22597
DUK_INTERNAL_DECL void duk_xdef_prop_index(duk_hthread *thr, duk_idx_t obj_idx, duk_uarridx_t arr_idx, duk_small_uint_t desc_flags)
Definition: duktape.c:18089
#define DUK_STR_INVALID_INSTANCEOF_RVAL_NOPROTO
Definition: duktape.c:3232
#define DUK_HOBJECT_E_SLOT_IS_ENUMERABLE(heap, h, i)
Definition: duktape.c:7065
#define DUK__ADVTOK(advbytes, tok)
Definition: duktape.c:85813
DUK_INTERNAL_DECL const char * duk_push_string_readable(duk_hthread *thr, duk_idx_t idx)
Definition: duktape.c:25505
#define DUK_OP_MPUTOBJ
Definition: duktape.c:3708
DUK_LOCAL int duk__bi_is_even(duk__bigint *x)
Definition: duktape.c:88709
DUK_LOCAL_DECL duk_bool_t duk__get_propdesc(duk_hthread *thr, duk_hobject *obj, duk_hstring *key, duk_propdesc *out_desc, duk_small_uint_t flags)
Definition: duktape.c:60137
DUK_INTERNAL_DECL duk_ret_t duk_bi_duktape_object_act(duk_context *ctx)
Definition: duktape.c:35119
DUK_INTERNAL_DECL duk_ret_t duk_bi_buffer_slice_shared(duk_context *ctx)
Definition: duktape.c:29698
DUK_INTERNAL_DECL void duk_push_tval(duk_hthread *thr, duk_tval *tv)
Definition: duktape.c:22971
#define DUK_TOK_BXOR
Definition: duktape.c:3946
DUK_INTERNAL_DECL duk_size_t duk_hobject_get_length(duk_hthread *thr, duk_hobject *obj)
Definition: duktape.c:62916
#define DUK_HTHREAD_STRING_BASE64(thr)
Definition: duktape.c:1920
#define DUK_TOK_GT
Definition: duktape.c:3926
#define DUK_DELPROP_FLAG_THROW
Definition: duktape.c:7452
DUK_INTERNAL_DECL duk_ret_t duk_bi_json_object_parse(duk_context *ctx)
Definition: duktape.c:40575
#define DUK_BC_CALL_FLAG_INDIRECT
Definition: duktape.c:3793
#define DUK_OP_CALL0
Definition: duktape.c:3690
DUK_INTERNAL_DECL void duk_pop_n_nodecref_unsafe(duk_hthread *thr, duk_idx_t count)
Definition: duktape.c:24654
#define DUK__EMIT_2(js_ctx, ch1, ch2)
Definition: duktape.c:38416
DUK_INTERNAL_DECL void * duk_heap_mem_alloc_checked_zeroed(duk_hthread *thr, duk_size_t size)
Definition: duktape.c:53708
#define DUK_TOK_IF
Definition: duktape.c:3864
DUK_INTERNAL_DECL void duk_bi_json_parse_helper(duk_hthread *thr, duk_idx_t idx_value, duk_idx_t idx_reviver, duk_small_uint_t flags)
Definition: duktape.c:40144
DUK_LOCAL void duk__handle_safe_call_error(duk_hthread *thr, duk_activation *entry_act, duk_hthread *entry_curr_thread, duk_uint_fast8_t entry_thread_state, duk_idx_t idx_retbase, duk_idx_t num_stack_rets, duk_size_t entry_valstack_bottom_byteoff, duk_jmpbuf *old_jmpbuf_ptr)
Definition: duktape.c:68567
DUK_EXTERNAL const char * duk_push_vsprintf(duk_hthread *thr, const char *fmt, va_list ap)
Definition: duktape.c:23421
#define DUK_ASC_8
Definition: duktape.c:10814
DUK_EXTERNAL void duk_throw_raw(duk_hthread *thr)
Definition: duktape.c:25022
DUK_INTERNAL_DECL void duk_call_setup_propcall_error(duk_hthread *thr, duk_tval *tv_base, duk_tval *tv_key)
Definition: duktape.c:68945
#define DUK_OP_UNUSED229
Definition: duktape.c:3744
#define DUK_HOBJECT_FLAG_HAVE_FINALIZER
Definition: duktape.c:6608
DUK_INTERNAL_DECL duk_ret_t duk_bi_buffer_readfield(duk_context *ctx)
Definition: duktape.c:30054
#define DUK_ASC_5
Definition: duktape.c:10811
#define DUK__ITER_MAP
Definition: duktape.c:27510
#define DUK_OP_MOD
Definition: duktape.c:3562
DUK_EXTERNAL duk_c_function duk_get_c_function_default(duk_hthread *thr, duk_idx_t idx, duk_c_function def_value)
Definition: duktape.c:21021
DUK_INTERNAL_DECL duk_bool_t duk_js_delvar_activation(duk_hthread *thr, duk_activation *act, duk_hstring *name)
Definition: duktape.c:85384
#define DUK_OP_GT_RR
Definition: duktape.c:3517
#define DUK_OP_SUB_RC
Definition: duktape.c:3550
DUK_INTERNAL_DECL void duk_raw_writeinc_u16_be(duk_uint8_t **p, duk_uint16_t val)
Definition: duktape.c:13987
#define DUK_OP_UNUSED249
Definition: duktape.c:3764
#define DUK_STRIDX_UC_BOOLEAN
Definition: duktape.c:1603
DUK_EXTERNAL void * duk_get_buffer_data_default(duk_hthread *thr, duk_idx_t idx, duk_size_t *out_size, void *def_ptr, duk_size_t def_size)
Definition: duktape.c:20786
#define DUK__FLD_DOUBLE
Definition: duktape.c:30047
#define DUK_TVAL_SET_OBJECT(tv, hptr)
Definition: duktape.c:1417
DUK_LOCAL duk_bool_t duk__getid_open_decl_env_regs(duk_hthread *thr, duk_hstring *name, duk_hdecenv *env, duk__id_lookup_result *out)
Definition: duktape.c:84683
DUK_INTERNAL_DECL duk_ret_t duk_bi_textdecoder_prototype_shared_getter(duk_context *ctx)
Definition: duktape.c:35731
#define DUK__MAX_OBJECT_INIT_PAIRS
Definition: duktape.c:69071
DUK_LOCAL void duk__cbor_encode_objarr_entry(duk_cbor_encode_context *enc_ctx)
Definition: duktape.c:30805
#define DUK_STRDATA_MAX_STRLEN
Definition: duktape.c:2092
DUK_EXTERNAL duk_bool_t duk_has_prop_literal_raw(duk_hthread *thr, duk_idx_t obj_idx, const char *key, duk_size_t key_len)
Definition: duktape.c:18024
#define DUK_STR_INVALID_SWITCH
Definition: duktape.c:3281
DUK_LOCAL_DECL duk_double_t duk__push_this_get_timeval(duk_hthread *thr, duk_small_uint_t flags)
Definition: duktape.c:33654
#define DUK__CF_ACCEPT_NUL
Definition: duktape.c:32831
DUK_INTERNAL_DECL duk_ret_t duk_bi_type_error_thrower(duk_context *ctx)
Definition: duktape.c:44799
DUK_INTERNAL_DECL duk_ret_t duk_bi_regexp_constructor(duk_context *ctx)
Definition: duktape.c:42477
#define DUK_HOBJECT_CLASS_POINTER
Definition: duktape.c:6652
#define DUK_HOBJECT_GET_ENEXT(h)
Definition: duktape.c:7132
DUK_LOCAL duk_hstring * duk__str_tostring_notregexp(duk_hthread *thr, duk_idx_t idx)
Definition: duktape.c:42707
#define DUK_ACT_FLAG_BREAKPOINT_ACTIVE
Definition: duktape.c:8063
#define DUK_HOBJECT_SET_EXOTIC_STRINGOBJ(h)
Definition: duktape.c:6792
DUK_INTERNAL_DECL duk_bool_t duk_xget_owndataprop(duk_hthread *thr, duk_idx_t obj_idx)
Definition: duktape.c:17759
#define DUK_HOBJECT_CLASS_BUFOBJ_MIN
Definition: duktape.c:6654
#define DUK_STRIDX_DATA_VIEW
Definition: duktape.c:1630
DUK_INTERNAL_DECL void duk_js_putvar_activation(duk_hthread *thr, duk_activation *act, duk_hstring *name, duk_tval *val, duk_bool_t strict)
Definition: duktape.c:85303
DUK_INTERNAL_DECL void * duk_heap_mem_realloc_indirect(duk_heap *heap, duk_mem_getptr cb, void *ud, duk_size_t newsize)
Definition: duktape.c:53909
#define DUK__GETPROP_BODY(barg, carg)
#define DUK_HBUFFER_EXTERNAL_SET_SIZE(x, v)
Definition: duktape.c:8662
#define DUK__FUNC_FLAG_PUSHNAME_PASS1
Definition: duktape.c:69302
#define DUK_STR_CANNOT_STRING_COERCE_SYMBOL
Definition: duktape.c:3217
#define DUK__MAX_ARRAY_INIT_VALUES
Definition: duktape.c:69070
#define DUK_UNICODE_CP_ZWNJ
Definition: duktape.c:10742
#define DUK__JSON_DECSTR_CHUNKSIZE
Definition: duktape.c:37384
#define DUK_HBUFOBJ_ELEM_UINT8CLAMPED
Definition: duktape.c:7897
#define DUK_OP_SNEQ_RC
Definition: duktape.c:3514
#define DUK_OP_UNUSED237
Definition: duktape.c:3752
#define DUK__MAX_FORMATTED_LENGTH
Definition: duktape.c:88804
DUK_LOCAL duk_heaphdr * duk__getrequire_bufobj_this(duk_hthread *thr, duk_small_uint_t flags)
Definition: duktape.c:27917
DUK_INTERNAL_DECL void duk_hobject_refcount_finalize_norz(duk_heap *heap, duk_hobject *h)
Definition: duktape.c:54203
#define DUK_ASSERT_REFCOUNT_NONZERO_HEAPHDR(h)
Definition: duktape.c:10576
DUK_INTERNAL_DECL duk_ret_t duk_bi_object_constructor_prevent_extensions(duk_context *ctx)
Definition: duktape.c:42016
#define DUK__BP_BXOR
Definition: duktape.c:69330
DUK_LOCAL_DECL void duk__emit_hstring(duk_json_enc_ctx *js_ctx, duk_hstring *h)
Definition: duktape.c:38432
#define DUK_STRIDX_MINUS_INFINITY
Definition: duktape.c:1762
#define DUK_HSTRING_HAS_RESERVED_WORD(x)
Definition: duktape.c:6342
DUK_INTERNAL_DECL duk_ret_t duk_bi_arraybuffer_isview(duk_context *ctx)
Definition: duktape.c:28900
DUK_LOCAL void duk__set_bufobj_buffer(duk_hthread *thr, duk_hbufobj *h_bufobj, duk_hbuffer *h_val)
Definition: duktape.c:27999
#define DUK_DBLUNION_SET_DOUBLE(u, v)
Definition: duktape.c:356
#define DUK_ERROR_REFERENCE(thr, msg)
Definition: duktape.c:10345
#define DUK_BW_SET_SIZE(thr, bw_ctx, sz)
Definition: duktape.c:2564
DUK_LOCAL_DECL duk_int_t duk__stmt_label_site(duk_compiler_ctx *comp_ctx, duk_int_t label_id)
Definition: duktape.c:75357
DUK_LOCAL duk_bool_t duk__lookup_arguments_map(duk_hthread *thr, duk_hobject *obj, duk_hstring *key, duk_propdesc *temp_desc, duk_hobject **out_map, duk_hobject **out_varenv)
Definition: duktape.c:59560
#define DUK_TVAL_GET_OBJECT(tv)
Definition: duktape.c:1474
DUK_EXTERNAL void duk_push_this(duk_hthread *thr)
Definition: duktape.c:23253
#define DUK_HOBJECT_CLASS_NUMBER_TO_STRIDX(n)
Definition: duktape.c:7172
#define DUK_STRIDX_WELLKNOWN_SYMBOL_HAS_INSTANCE
Definition: duktape.c:1810
DUK_INTERNAL_DECL duk_bool_t duk_js_instanceof(duk_hthread *thr, duk_tval *tv_x, duk_tval *tv_y)
Definition: duktape.c:83653
#define DUK_OP_PREDECP_RR
Definition: duktape.c:3641
DUK_LOCAL_DECL void duk__init_func_valstack_slots(duk_compiler_ctx *comp_ctx)
Definition: duktape.c:69570
#define DUK__PI_HOUR
Definition: duktape.c:32790
DUK_EXTERNAL const char * duk_opt_string(duk_hthread *thr, duk_idx_t idx, const char *def_ptr)
Definition: duktape.c:20472
#define DUK__IDX_ENEXT
Definition: duktape.c:17335
DUK_LOCAL void duk__bi_mul(duk__bigint *x, duk__bigint *y, duk__bigint *z)
Definition: duktape.c:88557
#define DUK_HOBJECT_GET_PROPS(heap, h)
Definition: duktape.c:6893
#define DUK_STR_INVALID_VAR_DECLARATION
Definition: duktape.c:3273
DUK_EXTERNAL duk_bool_t duk_del_prop_heapptr(duk_hthread *thr, duk_idx_t obj_idx, void *ptr)
Definition: duktape.c:17960
#define DUK_STRIDX_JSON_EXT_UNDEFINED
Definition: duktape.c:1927
DUK_INTERNAL_DECL duk_ret_t duk_bi_error_prototype_linenumber_getter(duk_context *ctx)
Definition: duktape.c:36107
#define DUK_HEAPHDR_CHECK_FLAG_BITS(h, bits)
Definition: duktape.c:4780
DUK_INTERNAL_DECL void duk_err_augment_error_create(duk_hthread *thr, duk_hthread *thr_callstack, const char *filename, duk_int_t line, duk_small_uint_t flags)
Definition: duktape.c:49511
#define DUK__IVAL_FLAG_ALLOW_CONST
Definition: duktape.c:70944
#define DUK_DBG_CMD_GETCALLSTACK
Definition: duktape.c:9743
DUK_EXTERNAL duk_idx_t duk_get_top(duk_hthread *thr)
Definition: duktape.c:19072
#define DUK_OP_PREINCP_CC
Definition: duktape.c:3639
DUK_LOCAL duk_uint_t duk__strtable_litcache_key(const duk_uint8_t *str, duk_uint32_t blen)
Definition: duktape.c:56157
DUK_INTERNAL_DECL void duk_regexp_match(duk_hthread *thr)
Definition: duktape.c:92843
#define DUK_LOWERCASE_CHAR_ASCII(x)
Definition: duktape.c:10894
#define DUK_OP_BAND_RC
Definition: duktape.c:3575
DUK_EXTERNAL duk_bool_t duk_is_external_buffer(duk_hthread *thr, duk_idx_t idx)
Definition: duktape.c:22908
DUK_LOCAL DUK_EXEC_ALWAYS_INLINE_PERF void duk__prepost_incdec_reg_helper(duk_hthread *thr, duk_tval *tv_dst, duk_tval *tv_src, duk_small_uint_t op)
Definition: duktape.c:77779
DUK_INTERNAL_DECL duk_hstring * duk_hobject_get_internal_value_string(duk_heap *heap, duk_hobject *obj)
Definition: duktape.c:59505
#define DUK_HOBJECT_E_GET_KEY_BASE(heap, h)
Definition: duktape.c:6939
DUK_LOCAL duk_uint32_t duk__get_min_grow_a(duk_uint32_t a_size)
Definition: duktape.c:58161
#define DUK_TOK_BNOT
Definition: duktape.c:3948
#define DUK__SER_MARKER
Definition: duktape.c:14431
DUK_INTERNAL_DECL duk_hobject * duk_require_hobject_with_class(duk_hthread *thr, duk_idx_t idx, duk_small_uint_t classnum)
Definition: duktape.c:21232
DUK_LOCAL_DECL void duk__emit(duk_compiler_ctx *comp_ctx, duk_instr_t ins)
Definition: duktape.c:70165
DUK_EXTERNAL duk_bool_t duk_check_stack(duk_hthread *thr, duk_idx_t extra)
Definition: duktape.c:19657
#define DUK_HOBJECT_FLAG_NOTAIL
Definition: duktape.c:6602
DUK_LOCAL void duk__clamp_startend_nonegidx_noshift(duk_hthread *thr, duk_int_t buffer_length, duk_idx_t idx_start, duk_idx_t idx_end, duk_int_t *out_start_offset, duk_int_t *out_end_offset)
Definition: duktape.c:28077
DUK_EXTERNAL void * duk_opt_buffer_data(duk_hthread *thr, duk_idx_t idx, duk_size_t *out_size, void *def_ptr, duk_size_t def_size)
Definition: duktape.c:20795
#define DUK_OP_NEWARR
Definition: duktape.c:3707
#define DUK_OP_POSTDECP_RR
Definition: duktape.c:3651
DUK_EXTERNAL duk_hthread * duk_get_context_default(duk_hthread *thr, duk_idx_t idx, duk_hthread *def_value)
Definition: duktape.c:21089
DUK_INTERNAL_DECL duk_ret_t duk_bi_duktape_object_fin(duk_context *ctx)
Definition: duktape.c:35141
#define DUK_HOBJECT_E_GET_FLAGS_BASE(heap, h)
Definition: duktape.c:6942
#define DUK_HEAP_NUM_STRINGS
Definition: duktape.c:2081
DUK_LOCAL void duk__cbor_encode_pointer(duk_cbor_encode_context *enc_ctx)
Definition: duktape.c:31319
DUK_EXTERNAL duk_bool_t duk_is_constructable(duk_hthread *thr, duk_idx_t idx)
Definition: duktape.c:22833
#define DUK_STRIDX_TRUE
Definition: duktape.c:2047
#define DUK_DBG_ERR_UNKNOWN
Definition: duktape.c:9715
#define DUK_STR_INVALID_REGEXP_CHARACTER
Definition: duktape.c:3305
#define DUK_OP_EXP_CR
Definition: duktape.c:3569
#define DUK__ISCONST(x)
Definition: duktape.c:69056
#define DUK_DDD(x)
Definition: duktape.c:9962
#define DUK_OP_BASR_CR
Definition: duktape.c:3599
#define DUK__STRPTIME_BUF_SIZE
Definition: duktape.c:34569
#define DUK_LEXER_WINDOW_SIZE
Definition: duktape.c:3837
#define DUK_BIDX_INT8ARRAY_PROTOTYPE
Definition: duktape.c:2327
#define DUK_STR_INVALID_TRAP_RESULT
Definition: duktape.c:3253
DUK_EXTERNAL duk_c_function duk_require_c_function(duk_hthread *thr, duk_idx_t idx)
Definition: duktape.c:21034
#define DUK_HEAPHDR_FLAG_READONLY
Definition: duktape.c:4685
DUK_INTERNAL_DECL void duk_remove_unsafe(duk_hthread *thr, duk_idx_t idx)
Definition: duktape.c:20013
#define DUK_RETOK_ATOM_WORD_CHAR
Definition: duktape.c:4139
DUK_LOCAL double duk__trunc(double x)
Definition: duktape.c:40735
DUK_LOCAL void duk__bi_normalize(duk__bigint *x)
Definition: duktape.c:88269
DUK_INTERNAL_DECL duk_ret_t duk_bi_date_constructor(duk_context *ctx)
Definition: duktape.c:34169
#define DUK__SETTEMP(comp_ctx, x)
Definition: duktape.c:69064
#define DUK_RETOK_ATOM_START_CHARCLASS
Definition: duktape.c:4144
#define DUK_ASC_RANGLE
Definition: duktape.c:10820
#define DUK__GETTEMP(comp_ctx)
Definition: duktape.c:69063
DUK_LOCAL duk_uint_fast32_t duk__hobject_pc2line_query_raw(duk_hthread *thr, duk_hbuffer_fixed *buf, duk_uint_fast32_t pc)
Definition: duktape.c:57773
#define DUK_HBUFFER_FIXED_GET_SIZE(x)
Definition: duktape.c:8653
#define DUK_HOBJECT_CLEAR_HAVE_FINALIZER(h)
Definition: duktape.c:6815
#define DUK_HOBJECT_CLASS_OBJECT
Definition: duktape.c:6636
#define DUK_HOBJECT_E_GET_VALUE_TVAL_PTR(heap, h, i)
Definition: duktape.c:7008
#define DUK_REFZERO_CHECK_FAST(thr)
Definition: duktape.c:5182
#define DUK_STRIDX_SOURCE
Definition: duktape.c:1711
#define DUK_HOBJENV_ASSERT_VALID(h)
Definition: duktape.c:8528
DUK_LOCAL duk_hstring * duk__strtable_do_intern(duk_heap *heap, const duk_uint8_t *str, duk_uint32_t blen, duk_uint32_t strhash)
Definition: duktape.c:55893
#define DUK_HCOMPFUNC_SET_VARENV(heap, h, v)
Definition: duktape.c:7602
DUK_LOCAL void duk__refcount_free_pending(duk_heap *heap)
Definition: duktape.c:54444
#define DUK__L3()
Definition: duktape.c:85808
DUK_LOCAL duk_uint8_t * duk__dump_formals(duk_hthread *thr, duk_uint8_t *p, duk_bufwriter_ctx *bw_ctx, duk_hobject *func)
Definition: duktape.c:14602
DUK_EXTERNAL duk_int_t duk_api_global_line
Definition: duktape.c:18712
#define DUK_ASC_9
Definition: duktape.c:10815
#define DUK_STR_SETTER_UNDEFINED
Definition: duktape.c:3248
#define DUK_OP_LDREG
Definition: duktape.c:3480
#define DUK_OP_INSTOF
Definition: duktape.c:3602
DUK_INTERNAL DUK_COLD void duk_err_handle_error_fmt(duk_hthread *thr, const char *filename, duk_uint_t line_and_code, const char *fmt,...)
Definition: duktape.c:12466
#define DUK_STRIDX_MATH
Definition: duktape.c:1618
#define DUK_ASC_LC_X
Definition: duktape.c:10878
DUK_INTERNAL_DECL duk_float_t duk_raw_readinc_float_be(const duk_uint8_t **p)
Definition: duktape.c:13939
DUK_LOCAL DUK__RZ_INLINE void duk__hobject_refzero_helper(duk_hthread *thr, duk_hobject *h, duk_bool_t skip_free_pending)
Definition: duktape.c:54757
#define DUK_OP_PUTVAR
Definition: duktape.c:3668
struct duk_hbuffer_dynamic duk_hbuffer_dynamic
Definition: duktape.c:851
#define DUK_OP_BOR_RC
Definition: duktape.c:3580
#define DUK_OP_BASL_CC
Definition: duktape.c:3591
#define DUK_OP_BLSR_RR
Definition: duktape.c:3593
DUK_INTERNAL_DECL void duk_hobject_refzero_norz(duk_hthread *thr, duk_hobject *h)
Definition: duktape.c:54831
#define DUK_BIDX_OBJECT_PROTOTYPE
Definition: duktape.c:2289
#define DUK_STR_STRICT_CALLER_READ
Definition: duktape.c:3245
DUK_LOCAL duk_harray * duk__arraypart_fastpath_this(duk_hthread *thr)
Definition: duktape.c:26173
#define DUK_OP_UNUSED242
Definition: duktape.c:3757
DUK_LOCAL DUK_INLINE void duk__cbor_encode_ensure(duk_cbor_encode_context *enc_ctx, duk_size_t len)
Definition: duktape.c:30882
DUK_LOCAL_DECL void duk__emit_stridx(duk_json_enc_ctx *js_ctx, duk_small_uint_t stridx)
Definition: duktape.c:38442
#define DUK_COMPILER_TOKEN_LIMIT
Definition: duktape.c:4246
#define DUK_STRIDX_INT_NEXT
Definition: duktape.c:1870
DUK_LOCAL duk_hbufobj * duk__require_bufobj_this(duk_hthread *thr)
Definition: duktape.c:27967
#define DUK_HARRAY_SET_LENGTH_NONWRITABLE(h)
Definition: duktape.c:8475
DUK_INTERNAL_DECL void duk_js_close_environment_record(duk_hthread *thr, duk_hobject *env)
Definition: duktape.c:84553
#define DUK_HOBJECT_A_GET_BASE(heap, h)
Definition: duktape.c:6945
DUK_INTERNAL_DECL duk_hobject * duk_create_activation_environment_record(duk_hthread *thr, duk_hobject *func, duk_size_t bottom_byteoff)
Definition: duktape.c:84447
#define DUK__READABLE_ERRMSG_MAXCHARS
Definition: duktape.c:25359
#define duk_xget_owndataprop_stridx_short(thr, obj_idx, stridx)
Definition: duktape.c:6151
DUK_LOCAL void duk__err_augment_builtin_create(duk_hthread *thr, duk_hthread *thr_callstack, const char *c_filename, duk_int_t c_line, duk_hobject *obj, duk_small_uint_t flags)
Definition: duktape.c:49453
DUK_INTERNAL_DECL duk_harray * duk_push_harray(duk_hthread *thr)
Definition: duktape.c:23605
#define DUK_CAT_CLEAR_CATCH_ENABLED(c)
Definition: duktape.c:8120
#define DUK_OP_RETCONSTN
Definition: duktape.c:3673
DUK_INTERNAL_DECL duk_ret_t duk_bi_object_constructor_is(duk_context *ctx)
Definition: duktape.c:41443
#define DUK_STRIDX_TYPE
Definition: duktape.c:1831
DUK_EXTERNAL void duk_require_undefined(duk_hthread *thr, duk_idx_t idx)
Definition: duktape.c:20186
DUK_INTERNAL_DECL void duk_hobject_pc2line_pack(duk_hthread *thr, duk_compiler_instr *instrs, duk_uint_fast32_t length)
Definition: duktape.c:57663
#define DUK_STRIDX_FLOAT32_ARRAY
Definition: duktape.c:1654
#define DUK_ASC_6
Definition: duktape.c:10812
DUK_INTERNAL_DECL void duk_fltunion_host_to_big(duk_float_union *u)
Definition: duktape.c:100897
#define DUK_OP_LDTHIS
Definition: duktape.c:3486
DUK_EXTERNAL void duk_free_raw(duk_hthread *thr, void *ptr)
Definition: duktape.c:17570
#define DUK_BIDX_TYPE_ERROR_PROTOTYPE
Definition: duktape.c:2316
#define DUK_TOK_LT
Definition: duktape.c:3925
#define DUK_OP_UNUSED238
Definition: duktape.c:3753
DUK_LOCAL duk_uint32_t duk__uni_decode_value(duk_bitdecoder_ctx *bd_ctx)
Definition: duktape.c:13139
DUK_INTERNAL_DECL duk_ret_t duk_bi_function_prototype(duk_context *ctx)
Definition: duktape.c:36193
DUK_INTERNAL_DECL int duk_repl_isinf(double x)
Definition: duktape.c:11496
DUK_LOCAL_DECL duk_int_t duk__emit_jump_empty(duk_compiler_ctx *comp_ctx)
Definition: duktape.c:70723
#define DUK_TVAL_IS_NULL(tv)
Definition: duktape.c:1482
#define DUK_HOBJECT_IS_COMPFUNC(h)
Definition: duktape.c:6712
#define DUK_STRIDX_LINE_NUMBER
Definition: duktape.c:1852
#define DUK_S2N_FLAG_ALLOW_MINUS
Definition: duktape.c:11277
DUK_INTERNAL_DECL duk_double_t duk_time_get_monotonic_time(duk_hthread *thr)
Definition: duktape.c:25994
#define DUK_HBUFFER_MAX_BYTELEN
Definition: duktape.c:8612
#define DUK_OP_POSTINCP_RC
Definition: duktape.c:3648
#define DUK_REOP_ASSERT_END
Definition: duktape.c:4504
DUK_LOCAL_DECL void duk__parse_func_like_raw(duk_compiler_ctx *comp_ctx, duk_small_uint_t flags)
Definition: duktape.c:76628
DUK_LOCAL void duk__mark_temproots_by_heap_scan(duk_heap *heap)
Definition: duktape.c:52491
DUK_LOCAL const duk_uint_t duk__type_mask_from_tag[]
Definition: duktape.c:18727
DUK_LOCAL_DECL void duk__parse_try_stmt(duk_compiler_ctx *comp_ctx, duk_ivalue *res)
Definition: duktape.c:75093
#define DUK_STRIDX_WELLKNOWN_SYMBOL_TO_PRIMITIVE
Definition: duktape.c:1807
DUK_INTERNAL_DECL duk_hobject * duk_get_hobject_with_class(duk_hthread *thr, duk_idx_t idx, duk_small_uint_t classnum)
Definition: duktape.c:21218
DUK_LOCAL DUK_COLD DUK_NOINLINE duk_bool_t duk__resize_valstack(duk_hthread *thr, duk_size_t new_size)
Definition: duktape.c:19346
#define DUK__ENUM_START_INDEX
Definition: duktape.c:56899
#define DUK__RZ_STRING()
Definition: duktape.c:54715
#define DUK__EMIT_CSTR(js_ctx, p)
Definition: duktape.c:38419
DUK_INTERNAL_DECL void duk_compact_m1(duk_hthread *thr)
Definition: duktape.c:18260
#define DUK_HOBJECT_SET_EXOTIC_ARGUMENTS(h)
Definition: duktape.c:6793
DUK_LOCAL duk_tval * duk__getprop_shallow_fastpath_array_tval(duk_hthread *thr, duk_hobject *obj, duk_tval *tv_key)
Definition: duktape.c:60216
#define DUK_STRIDX_ERR_CREATE
Definition: duktape.c:1906
#define DUK__STILL_PROLOGUE
Definition: duktape.c:74113
DUK_EXTERNAL void duk_set_magic(duk_hthread *thr, duk_idx_t idx, duk_int_t magic)
Definition: duktape.c:15663
DUK_LOCAL void duk__lexer_skip_to_endofline(duk_lexer_ctx *lex_ctx)
Definition: duktape.c:86655
#define DUK_TOK_BAND
Definition: duktape.c:3944
DUK_LOCAL int duk__cbor_decode_checkbreak(duk_cbor_decode_context *dec_ctx)
Definition: duktape.c:31521
#define DUK__INITBUFFER(lex_ctx)
Definition: duktape.c:85800
#define DUK_HNATFUNC_NARGS_VARARGS
Definition: duktape.c:7817
DUK_INTERNAL_DECL duk_small_int_t duk_memcmp(const void *s1, const void *s2, duk_size_t len)
Definition: duktape.c:101029
#define DUK_OP_REGEXP_RR
Definition: duktape.c:3661
#define DUK_HEAP_REMOVE_FROM_FINALIZE_LIST(heap, hdr)
Definition: duktape.c:9109
DUK_LOCAL_DECL duk_regconst_t duk__ivalue_toreg(duk_compiler_ctx *comp_ctx, duk_ivalue *x)
Definition: duktape.c:71576
DUK_EXTERNAL duk_bool_t duk_is_dynamic_buffer(duk_hthread *thr, duk_idx_t idx)
Definition: duktape.c:22893
DUK_EXTERNAL const char * duk_require_lstring(duk_hthread *thr, duk_idx_t idx, duk_size_t *out_len)
Definition: duktape.c:20417
DUK_INTERNAL_DECL duk_idx_t duk_get_top_index_unsafe(duk_hthread *thr)
Definition: duktape.c:19300
#define DUK_OP_DIV_RR
Definition: duktape.c:3558
#define DUK__BP_EXPONENTIATION
Definition: duktape.c:69337
DUK_LOCAL duk_ret_t duk__finalize_helper(duk_hthread *thr, void *udata)
Definition: duktape.c:51825
DUK_LOCAL_DECL void duk__expr_nud(duk_compiler_ctx *comp_ctx, duk_ivalue *res)
Definition: duktape.c:72417
#define DUK_TVAL_IS_BUFFER(tv)
Definition: duktape.c:1498
#define DUK_S2N_FLAG_ALLOW_EMPTY_FRAC
Definition: duktape.c:11289
DUK_EXTERNAL duk_hthread * duk_opt_context(duk_hthread *thr, duk_idx_t idx, duk_hthread *def_value)
Definition: duktape.c:21080
DUK_INTERNAL_DECL duk_ret_t duk_bi_duktape_object_compact(duk_context *ctx)
Definition: duktape.c:35242
#define DUK_STRIDX_UC_NUMBER
Definition: duktape.c:1606
#define DUK_TVAL_IS_DOUBLE(tv)
Definition: duktape.c:1487
#define DUK_RAW_READINC_U32_BE(ptr)
Definition: duktape.c:2457
#define DUK_HEAPHDR_GET_PREV(heap, h)
Definition: duktape.c:4715
DUK_EXTERNAL void duk_hex_decode(duk_hthread *thr, duk_idx_t idx)
Definition: duktape.c:16485
DUK_LOCAL void duk__handle_temproot(duk_heap *heap, duk_heaphdr *hdr)
Definition: duktape.c:52469
DUK_EXTERNAL duk_idx_t duk_require_normalize_index(duk_hthread *thr, duk_idx_t idx)
Definition: duktape.c:18945
#define DUK_TVAL_SET_BOOLEAN_FALSE(tv)
Definition: duktape.c:1524
DUK_EXTERNAL duk_bool_t duk_samevalue(duk_hthread *thr, duk_idx_t idx1, duk_idx_t idx2)
Definition: duktape.c:25226
#define DUK__MK_LBP(bp)
Definition: duktape.c:69349
DUK_EXTERNAL void duk_require_object(duk_hthread *thr, duk_idx_t idx)
Definition: duktape.c:20549
DUK_INTERNAL_DECL duk_ret_t duk_bi_nodejs_buffer_write(duk_context *ctx)
Definition: duktape.c:29198
#define DUK__REMOVECONST(x)
Definition: duktape.c:69054
DUK_INTERNAL_DECL duk_small_uint_t duk_bd_decode_flag(duk_bitdecoder_ctx *ctx)
Definition: duktape.c:99987
DUK_INTERNAL_DECL duk_ret_t duk_bi_native_function_name(duk_context *ctx)
Definition: duktape.c:36601
DUK_INTERNAL_DECL void duk_hthread_activation_free(duk_hthread *thr, duk_activation *act)
Definition: duktape.c:65659
#define DUK_HOBJECT_GET_CLASS_MASK(h)
Definition: duktape.c:6624
#define DUK_OP_BOR
Definition: duktape.c:3577
#define DUK_PUSH_SPRINTF_SANITY_LIMIT
Definition: duktape.c:5922
#define DUK_ASC_7
Definition: duktape.c:10813
DUK_INTERNAL_DECL void duk_to_primitive_ordinary(duk_hthread *thr, duk_idx_t idx, duk_int_t hint)
Definition: duktape.c:21525
DUK_LOCAL double duk__atan2_fixed(double x, double y)
Definition: duktape.c:40829
DUK_INTERNAL_DECL duk_ret_t duk_bi_regexp_prototype_test(duk_context *ctx)
Definition: duktape.c:42558
DUK_LOCAL void * duk__hobject_alloc_init(duk_hthread *thr, duk_uint_t hobject_flags, duk_size_t size)
Definition: duktape.c:56524
DUK_INTERNAL_DECL void duk_push_string_funcptr(duk_hthread *thr, duk_uint8_t *ptr, duk_size_t sz)
Definition: duktape.c:25321
#define DUK__NUMCONV_CTX_BIGINTS_SIZE
Definition: duktape.c:88808
static const duk_uint8_t duk__buffer_class_from_elemtype[9]
Definition: duktape.c:27829
#define DUK_STRIDX_START_RESERVED
Definition: duktape.c:2082
#define DUK_OP_PREDECR
Definition: duktape.c:3628
#define DUK__MAX_TEMPS
Definition: duktape.c:69081
#define DUK_BIDX_DOUBLE_ERROR
Definition: duktape.c:2323
#define DUK_HEAPHDR_GET_FLAGS_RAW(h)
Definition: duktape.c:4741
#define DUK_OP_SUB_CR
Definition: duktape.c:3549
DUK_INTERNAL_DECL void duk_be_encode(duk_bitencoder_ctx *ctx, duk_uint32_t data, duk_small_int_t bits)
Definition: duktape.c:100102
DUK_LOCAL void duk__array_qsort(duk_hthread *thr, duk_int_t lo, duk_int_t hi)
Definition: duktape.c:26897
DUK_INTERNAL_DECL void duk_heap_switch_thread(duk_heap *heap, duk_hthread *new_thr)
Definition: duktape.c:54121
#define DUK_STR_INVALID_REGEXP_ESCAPE
Definition: duktape.c:3303
#define DUK_TOK_FINALLY
Definition: duktape.c:3861
DUK_INTERNAL_DECL duk_ret_t duk_textdecoder_decode_utf8_nodejs(duk_hthread *thr)
Definition: duktape.c:35772
#define DUK_OP_PREINCP
Definition: duktape.c:3635
#define DUK_LFUNC_LENGTH_MAX
Definition: duktape.c:1541
DUK_EXTERNAL void duk_gc(duk_hthread *thr, duk_uint_t flags)
Definition: duktape.c:17625
#define DUK_TVAL_SET_UNUSED_UPDREF
Definition: duktape.c:5420
#define DUK_STR_VALSTACK_LIMIT
Definition: duktape.c:3311
DUK_LOCAL_DECL void duk__json_dec_req_stridx(duk_json_dec_ctx *js_ctx, duk_small_uint_t stridx)
Definition: duktape.c:37642
#define DUK__JSON_DECSTR_BUFSIZE
Definition: duktape.c:37383
DUK_LOCAL_DECL void duk__mark_heaphdr(duk_heap *heap, duk_heaphdr *h)
Definition: duktape.c:52225
#define DUK_BW_COMPACT(thr, bw_ctx)
Definition: duktape.c:2521
DUK_INTERNAL_DECL duk_int32_t duk_bd_decode_flagged_signed(duk_bitdecoder_ctx *ctx, duk_small_int_t bits, duk_int32_t def_value)
Definition: duktape.c:100003
#define DUK__APPENDBUFFER_ASCII(lex_ctx, x)
Definition: duktape.c:85802
DUK_INTERNAL_DECL duk_bool_t duk_double_is_nan_or_inf(duk_double_t x)
Definition: duktape.c:100638
#define DUK_OP_SEQ_CC
Definition: duktape.c:3510
#define DUK_HEAPHDR_SET_PREV(heap, h, val)
Definition: duktape.c:4716
#define DUK_HEAPHDR_SET_FINALIZABLE(h)
Definition: duktape.c:4790
#define DUK_HOBJECT_HAS_EXOTIC_STRINGOBJ(h)
Definition: duktape.c:6765
struct duk_hthread duk_hthread
Definition: duktape.c:844
DUK_LOCAL_DECL void duk__json_dec_reviver_walk(duk_json_dec_ctx *js_ctx)
Definition: duktape.c:38314
#define DUK_OP_IN_RR
Definition: duktape.c:3608
#define DUK_DECL_TYPE_FUNC
Definition: duktape.c:4325
DUK_LOCAL void duk__bi_add(duk__bigint *x, duk__bigint *y, duk__bigint *z)
Definition: duktape.c:88383
#define DUK_STRIDX_MESSAGE
Definition: duktape.c:1735
DUK_LOCAL DUK_ALWAYS_INLINE void duk__pop_n_unsafe_raw(duk_hthread *thr, duk_idx_t count)
Definition: duktape.c:24593
#define DUK_STR_INVALID_QUANTIFIER_NO_ATOM
Definition: duktape.c:3296
DUK_LOCAL DUK_NOINLINE_PERF DUK_COLD void * duk__heap_mem_alloc_slowpath(duk_heap *heap, duk_size_t size)
Definition: duktape.c:53572
DUK_INTERNAL_DECL void duk_hobject_refzero(duk_hthread *thr, duk_hobject *h)
Definition: duktape.c:54827
#define DUK_STR_INVALID_QUANTIFIER
Definition: duktape.c:3295
DUK_INTERNAL_DECL duk_bool_t duk_is_string_notsymbol(duk_hthread *thr, duk_idx_t idx)
Definition: duktape.c:22718
DUK_LOCAL void duk__inc_data_inner_refcounts(duk_hthread *thr, duk_hcompfunc *f)
Definition: duktape.c:83989
#define DUK__IDX_ITAG
Definition: duktape.c:17329
#define DUK_STR_UNEXPECTED_REGEXP_TOKEN
Definition: duktape.c:3301
#define DUK_OP_LE_RR
Definition: duktape.c:3532
DUK_INTERNAL_DECL duk_ret_t duk_bi_dataview_constructor(duk_context *ctx)
Definition: duktape.c:28849
#define DUK_STRIDX_FILE_NAME
Definition: duktape.c:1861
DUK_LOCAL void duk__cbor_encode_objarr_exit(duk_cbor_encode_context *enc_ctx)
Definition: duktape.c:30824
#define DUK_TVAL_IS_UNDEFINED(tv)
Definition: duktape.c:1480
DUK_LOCAL duk_hobject * duk__hobject_get_entry_object_stridx(duk_heap *heap, duk_hobject *obj, duk_small_uint_t stridx)
Definition: duktape.c:59515
DUK_INTERNAL_DECL duk_bool_t duk_is_callable_tval(duk_hthread *thr, duk_tval *tv)
Definition: duktape.c:22816
#define DUK__EXPR_FLAG_REJECT_IN
Definition: duktape.c:73927
DUK_LOCAL_DECL void duk__parse_if_stmt(duk_compiler_ctx *comp_ctx, duk_ivalue *res)
Definition: duktape.c:74793
#define DUK__EXPR_FLAG_ALLOW_EMPTY
Definition: duktape.c:73928
#define DUK_STRIDX_TO_GMT_STRING
Definition: duktape.c:1708
#define DUK_BW_SETPTR_AND_COMPACT(thr, bw_ctx, ptr)
Definition: duktape.c:2603
DUK_LOCAL duk_uint32_t duk__parse_regexp_flags(duk_hthread *thr, duk_hstring *h)
Definition: duktape.c:91513
#define DUK_TVAL_SET_UNUSED(tv)
Definition: duktape.c:1288
DUK_EXTERNAL duk_bool_t duk_has_prop_lstring(duk_hthread *thr, duk_idx_t obj_idx, const char *key, duk_size_t key_len)
Definition: duktape.c:18014
#define DUK_STR_UNTERMINATED_CHARCLASS
Definition: duktape.c:3307
#define DUK_EQUALS_FLAG_SAMEVALUE
Definition: duktape.c:11105
#define DUK_STRIDX_SET
Definition: duktape.c:1843
#define DUK_RE_FLAG_MULTILINE
Definition: duktape.c:4511
#define DUK_TVAL_GET_LIGHTFUNC_FUNCPTR(tv)
Definition: duktape.c:1471
DUK_EXTERNAL void duk_swap_top(duk_hthread *thr, duk_idx_t idx)
Definition: duktape.c:19771
#define DUK_GC_TORTURE(heap)
Definition: duktape.c:9091
DUK_EXTERNAL void duk_require_stack_top(duk_hthread *thr, duk_idx_t top)
Definition: duktape.c:19726
DUK_INTERNAL_DECL duk_ret_t duk_bi_array_prototype_shift(duk_context *ctx)
Definition: duktape.c:27310
DUK_INTERNAL_DECL void duk_bi_date_timeval_to_parts(duk_double_t d, duk_int_t *parts, duk_double_t *dparts, duk_small_uint_t flags)
Definition: duktape.c:33308
DUK_LOCAL void duk__comp_recursion_increase(duk_compiler_ctx *comp_ctx)
Definition: duktape.c:69461
DUK_INTERNAL_DECL void duk_refzero_check_slow(duk_hthread *thr)
Definition: duktape.c:54607
const duk_uint8_t duk_unicode_caseconv_uc[1411]
Definition: duktape.c:93973
DUK_LOCAL_DECL void duk__nud_array_literal(duk_compiler_ctx *comp_ctx, duk_ivalue *res)
Definition: duktape.c:71934
#define DUK__FLD_16BIT
Definition: duktape.c:30044
DUK_INTERNAL_DECL duk_activation * duk_hthread_activation_alloc(duk_hthread *thr)
Definition: duktape.c:65640
#define DUK_TOK_DIV_EQ
Definition: duktape.c:3957
DUK_LOCAL_DECL duk_regconst_t duk__exprtop_toregconst(duk_compiler_ctx *comp_ctx, duk_ivalue *res, duk_small_uint_t rbp_flags)
Definition: duktape.c:74086
#define DUK_ASC_LC_C
Definition: duktape.c:10857
DUK_INTERNAL_DECL duk_hobject * duk_require_hobject_promote_mask(duk_hthread *thr, duk_idx_t idx, duk_uint_t type_mask)
Definition: duktape.c:21205
#define DUK_HEAP_MAX_BREAKPOINTS
Definition: duktape.c:9202
DUK_LOCAL_DECL void duk__unemit_1(duk_json_enc_ctx *js_ctx)
Definition: duktape.c:38452
#define DUK__MKBITS(a, b, c, d, e, f, g, h)
Definition: duktape.c:36657
#define DUK_TOK_EQ
Definition: duktape.c:3929
#define DUK_HTHREAD_INTCTR_DEFAULT
Definition: duktape.c:8164
#define DUK_LEXER_GETPOINT(ctx, pt)
Definition: duktape.c:3834
#define DUK_BIDX_POINTER_PROTOTYPE
Definition: duktape.c:2322
#define DUK_SYMBOL_TYPE_WELLKNOWN
Definition: duktape.c:6456
DUK_INTERNAL_DECL duk_ret_t duk_bi_string_prototype_startswith_endswith(duk_context *ctx)
Definition: duktape.c:44187
DUK_EXTERNAL duk_bool_t duk_put_global_string(duk_hthread *thr, const char *key)
Definition: duktape.c:18451
#define DUK_HEAPHDR_CLEAR_FINALIZABLE(h)
Definition: duktape.c:4791
#define DUK_OP_UNUSED251
Definition: duktape.c:3766
DUK_INTERNAL_DECL duk_ret_t duk_bi_array_prototype_pop(duk_context *ctx)
Definition: duktape.c:26564
DUK_INTERNAL_DECL duk_ret_t duk_bi_number_prototype_to_exponential(duk_context *ctx)
Definition: duktape.c:41248
DUK_LOCAL void duk__dragon4_double_to_ctx(duk__numconv_stringify_ctx *nc_ctx, duk_double_t x)
Definition: duktape.c:89544
#define DUK_STRIDX_COMMA
Definition: duktape.c:1768
#define DUK_BW_SLACK_SHIFT
Definition: duktape.c:2508
DUK_INTERNAL_DECL duk_ret_t duk_bi_object_constructor(duk_context *ctx)
Definition: duktape.c:41374
DUK_LOCAL_DECL void duk__emit_b_c(duk_compiler_ctx *comp_ctx, duk_small_uint_t op_flags, duk_regconst_t b, duk_regconst_t c)
Definition: duktape.c:70542
DUK_LOCAL duk_double_t duk__cbor_decode_half_float(duk_cbor_decode_context *dec_ctx)
Definition: duktape.c:31773
#define DUK_TVAL_SET_BUFFER(tv, hptr)
Definition: duktape.c:1425
DUK_EXTERNAL duk_bool_t duk_is_fixed_buffer(duk_hthread *thr, duk_idx_t idx)
Definition: duktape.c:22878
DUK_LOCAL DUK_ALWAYS_INLINE duk_double_t duk__get_number_raw(duk_hthread *thr, duk_idx_t idx, duk_double_t def_value)
Definition: duktape.c:20270
#define DUK_TVAL_SET_U32_UPDREF_NORZ(thr, tv_dst, val)
Definition: duktape.c:5840
DUK_INTERNAL_DECL duk_ret_t duk_bi_nodejs_buffer_is_encoding(duk_context *ctx)
Definition: duktape.c:29852
DUK_INTERNAL_DECL void duk_copy_tvals_incref(duk_hthread *thr, duk_tval *tv_dst, duk_tval *tv_src, duk_size_t count)
Definition: duktape.c:25569
#define DUK_ASC_1
Definition: duktape.c:10807
#define DUK_TVAL_IS_OBJECT(tv)
Definition: duktape.c:1497
#define DUK_STR_UNTERMINATED_STRING
Definition: duktape.c:3259
#define DUK_HOBJECT_IS_OBJENV(h)
Definition: duktape.c:6707
#define DUK_TOK_NUMBER
Definition: duktape.c:3970
#define DUK_HOBJECT_CLASS_INT16ARRAY
Definition: duktape.c:6660
DUK_EXTERNAL duk_double_t duk_to_number(duk_hthread *thr, duk_idx_t idx)
Definition: duktape.c:21566
DUK_INTERNAL DUK_COLD void duk_err_require_type_index(duk_hthread *thr, const char *filename, duk_int_t linenumber, duk_idx_t idx, const char *expect_name)
Definition: duktape.c:12521
#define DUK_OP_UNUSED252
Definition: duktape.c:3767
#define DUK_ASC_RBRACKET
Definition: duktape.c:10851
#define DUK_HSTRING_FLAG_EVAL_OR_ARGUMENTS
Definition: duktape.c:6334
#define DUK_HEAPHDR_FLAG_TEMPROOT
Definition: duktape.c:4682
#define DUK_JSON_FLAG_AVOID_KEY_QUOTES
Definition: duktape.c:11027
#define DUK_HBUFOBJ_ELEM_INT16
Definition: duktape.c:7900
DUK_EXTERNAL void duk_config_buffer(duk_hthread *thr, duk_idx_t idx, void *ptr, duk_size_t len)
Definition: duktape.c:14398
DUK_LOCAL_DECL void duk__expr_led(duk_compiler_ctx *comp_ctx, duk_ivalue *left, duk_ivalue *res)
Definition: duktape.c:72923
#define DUK_REFZERO_CHECK_SLOW(thr)
Definition: duktape.c:5186
#define DUK_HBUFFER_DECREF_NORZ_ALLOWNULL(thr, h)
Definition: duktape.c:5151
#define DUK_TOK_MAXVAL
Definition: duktape.c:3974
DUK_EXTERNAL const char * duk_to_stacktrace(duk_hthread *thr, duk_idx_t idx)
Definition: duktape.c:21814
#define DUK_HOBJECT_CLASS_BUFOBJ_MAX
Definition: duktape.c:6666
#define DUK_HOBJECT_SET_CREATEARGS(h)
Definition: duktape.c:6789
DUK_INTERNAL_DECL duk_small_int_t duk_unicode_encode_cesu8(duk_ucodepoint_t cp, duk_uint8_t *out)
Definition: duktape.c:12763
DUK_LOCAL const duk_int8_t duk__base64_decode_nequal_step[5]
Definition: duktape.c:15765
#define DUK_OP_GE_RR
Definition: duktape.c:3522
#define DUK_OP_BOR_CR
Definition: duktape.c:3579
#define DUK__CONSTP_B(ins)
Definition: duktape.c:79960
#define DUK_DBG_IB_UNUSED
Definition: duktape.c:9700
DUK_INTERNAL_DECL void duk_hthread_activation_unwind_norz(duk_hthread *thr)
Definition: duktape.c:65834
#define DUK_HOBJECT_HAS_CREATEARGS(h)
Definition: duktape.c:6762
#define DUK_BW_ENSURE(thr, bw_ctx, sz)
Definition: duktape.c:2578
#define DUK_JSON_ENC_REQSTACK
Definition: duktape.c:11032
DUK_LOCAL const duk__two_arg_func duk__two_arg_funcs[]
Definition: duktape.c:40880
DUK_INTERNAL_DECL duk_bool_t duk_get_method_stridx(duk_hthread *thr, duk_idx_t idx, duk_small_uint_t stridx)
Definition: duktape.c:18518
#define DUK_STRIDX_CONSTRUCT
Definition: duktape.c:1792
#define DUK_ERROR_SYNTAX(thr, msg)
Definition: duktape.c:10349
#define DUK_BIDX_FUNCTION_PROTOTYPE
Definition: duktape.c:2291
#define DUK__L0()
Definition: duktape.c:85805
#define DUK_OP_UNUSED217
Definition: duktape.c:3732
DUK_INTERNAL_DECL duk_ret_t duk_bi_string_prototype_char_code_at(duk_context *ctx)
Definition: duktape.c:42981
DUK_EXTERNAL duk_bool_t duk_put_global_literal_raw(duk_hthread *thr, const char *key, duk_size_t key_len)
Definition: duktape.c:18482
DUK_INTERNAL_DECL duk_hobject * duk_known_hobject(duk_hthread *thr, duk_idx_t idx)
Definition: duktape.c:21359
#define DUK_PROPDESC_FLAGS_NONE
Definition: duktape.c:6851
#define DUK__JSON_STRINGIFY_BUFSIZE
Definition: duktape.c:37386
DUK_EXTERNAL duk_int_t duk_safe_call(duk_hthread *thr, duk_safe_call_function func, void *udata, duk_idx_t nargs, duk_idx_t nrets)
Definition: duktape.c:15481
#define DUK_HBUFOBJ_HAS_VIRTUAL_INDICES(h)
Definition: duktape.c:7968
#define DUK_HOBJECT_CMASK_STRING
Definition: duktape.c:6683
#define DUK_TVAL_GET_BUFFER(tv)
Definition: duktape.c:1475
#define DUK_PROPDESC_FLAG_VIRTUAL
Definition: duktape.c:6840
#define DUK_OP_LT_CR
Definition: duktape.c:3528
DUK_INTERNAL_DECL void * duk_heap_mem_realloc(duk_heap *heap, void *ptr, duk_size_t newsize)
Definition: duktape.c:53785
DUK_LOCAL void duk__bi_set_small(duk__bigint *x, duk_uint32_t v)
Definition: duktape.c:88293
#define DUK_HEAP_INSERT_INTO_HEAP_ALLOCATED(heap, hdr)
Definition: duktape.c:9103
#define DUK_OP_CSVAR_RR
Definition: duktape.c:3686
#define DUK_OP_INVALID
Definition: duktape.c:3720
double(* duk__two_arg_func)(double, double)
Definition: duktape.c:40620
DUK_INTERNAL_DECL duk_bool_t duk_js_in(duk_hthread *thr, duk_tval *tv_x, duk_tval *tv_y)
Definition: duktape.c:83667
DUK_EXTERNAL duk_bool_t duk_has_prop_heapptr(duk_hthread *thr, duk_idx_t obj_idx, void *ptr)
Definition: duktape.c:18043
#define DUK_BI_DATE_ISO8601_BUFSIZE
Definition: duktape.c:11343
#define DUK_ASSERT_API_ENTRY(thr)
Definition: duktape.c:8201
#define DUK_STR_CANNOT_NUMBER_COERCE_SYMBOL
Definition: duktape.c:3216
#define DUK_TVAL_SET_TVAL_UPDREF_FAST
Definition: duktape.c:5446
DUK_LOCAL_DECL void duk__parse_with_stmt(duk_compiler_ctx *comp_ctx, duk_ivalue *res)
Definition: duktape.c:75316
#define DUK_STR_BUFFER_TOO_LONG
Definition: duktape.c:3219
DUK_EXTERNAL void duk_push_null(duk_hthread *thr)
Definition: duktape.c:22995
#define DUK__BP_RELATIONAL
Definition: duktape.c:69333
#define DUK__INSTOF_BODY(barg, carg)
#define DUK__BP_BOR
Definition: duktape.c:69329
#define DUK__IDX_HBYTES
Definition: duktape.c:17331
DUK_LOCAL duk_bool_t duk__handle_specialfuncs_for_call(duk_hthread *thr, duk_idx_t idx_func, duk_hobject *func, duk_small_uint_t *call_flags, duk_bool_t first)
Definition: duktape.c:66707
#define DUK_OP_BXOR_RR
Definition: duktape.c:3583
DUK_EXTERNAL duk_bool_t duk_strict_equals(duk_hthread *thr, duk_idx_t idx1, duk_idx_t idx2)
Definition: duktape.c:25211
#define DUK_TVAL_SET_NULL_UPDREF
Definition: duktape.c:5421
DUK_EXTERNAL void duk_freeze(duk_hthread *thr, duk_idx_t obj_idx)
Definition: duktape.c:18345
DUK_LOCAL duk_uint32_t duk__push_tval_to_property_key(duk_hthread *thr, duk_tval *tv_key, duk_hstring **out_h)
Definition: duktape.c:58092
DUK_INTERNAL_DECL duk_bool_t duk_js_instanceof_ordinary(duk_hthread *thr, duk_tval *tv_x, duk_tval *tv_y)
Definition: duktape.c:83648
#define DUK_OP_BNOT
Definition: duktape.c:3492
#define DUK_ASC_UC_C
Definition: duktape.c:10825
#define DUK_TVAL_SET_OBJECT_UPDREF
Definition: duktape.c:5439
DUK_LOCAL DUK_ALWAYS_INLINE void duk__base64_encode_fast_2(const duk_uint8_t *src, duk_uint8_t *dst)
Definition: duktape.c:15834
#define DUK_STRIDX_WRITABLE
Definition: duktape.c:1684
DUK_EXTERNAL const char * duk_to_string(duk_hthread *thr, duk_idx_t idx)
Definition: duktape.c:22059
#define DUK_BIDX_DATAVIEW_PROTOTYPE
Definition: duktape.c:2326
struct duk_hnatfunc duk_hnatfunc
Definition: duktape.c:842
#define DUK__HAS_TERM
Definition: duktape.c:74111
#define DUK_STRIDX_DEC_ENV
Definition: duktape.c:1666
DUK_LOCAL duk_uint32_t duk__get_min_grow_e(duk_uint32_t e_size)
Definition: duktape.c:58152
DUK_EXTERNAL void duk_require_constructable(duk_hthread *thr, duk_idx_t idx)
Definition: duktape.c:21055
DUK_INTERNAL_DECL duk_ret_t duk_bi_number_check_shared(duk_context *ctx)
Definition: duktape.c:41326
DUK_LOCAL DUK_NOINLINE void duk__numconv_parse_raw(duk_hthread *thr, duk_small_int_t radix, duk_small_uint_t flags)
Definition: duktape.c:89949
void(* duk__transform_callback)(duk__transform_context *tfm_ctx, const void *udata, duk_codepoint_t cp)
Definition: duktape.c:36732
DUK_INTERNAL const duk_uint8_t duk_uc_nybbles[16]
Definition: duktape.c:14035
DUK_LOCAL DUK_NOINLINE duk_activation * duk__hthread_activation_alloc_slow(duk_hthread *thr)
Definition: duktape.c:65631
DUK_INTERNAL_DECL void duk_tval_set_number_chkfast_fast(duk_tval *tv, duk_double_t x)
Definition: duktape.c:93626
DUK_LOCAL void duk__add_traceback(duk_hthread *thr, duk_hthread *thr_callstack, const char *c_filename, duk_int_t c_line, duk_small_uint_t flags)
Definition: duktape.c:49112
DUK_INTERNAL_DECL duk_ret_t duk_bi_math_object_sign(duk_context *ctx)
Definition: duktape.c:41000
DUK_INTERNAL_DECL duk_double_t duk_js_tointeger(duk_hthread *thr, duk_tval *tv)
Definition: duktape.c:82753
#define DUK_DBLUNION_GET_DOUBLE(u)
Definition: duktape.c:391
DUK_INTERNAL_DECL void duk_bw_init(duk_hthread *thr, duk_bufwriter_ctx *bw_ctx, duk_hbuffer_dynamic *h_buf)
Definition: duktape.c:100170
#define DUK_HTHREAD_STRING___PROTO__(thr)
Definition: duktape.c:1824
#define DUK_STRIDX_LC_FUNCTION
Definition: duktape.c:1978
#define DUK_OP_UNUSED236
Definition: duktape.c:3751
DUK_INTERNAL_DECL duk_bool_t duk_put_prop_stridx(duk_hthread *thr, duk_idx_t obj_idx, duk_small_uint_t stridx)
Definition: duktape.c:17886
DUK_INTERNAL_DECL duk_small_int_t duk_unicode_is_whitespace(duk_codepoint_t cp)
Definition: duktape.c:13198
#define DUK_STR_INVALID_ESCAPE
Definition: duktape.c:3258
#define DUK_HOBJECT_CLASS_FUNCTION
Definition: duktape.c:6638
DUK_LOCAL duk_small_int_t duk__bi_is_2to52(duk__bigint *x)
Definition: duktape.c:88725
#define DUK_ASC_LC_B
Definition: duktape.c:10856
DUK_EXTERNAL void duk_call(duk_hthread *thr, duk_idx_t nargs)
Definition: duktape.c:15320
#define DUK_DBLUNION_IS_NORMALIZED(u)
Definition: duktape.c:552
DUK_LOCAL void duk__cbor_encode_object(duk_cbor_encode_context *enc_ctx)
Definition: duktape.c:31220
DUK_INTERNAL_DECL void duk_heap_strtable_unlink(duk_heap *heap, duk_hstring *h)
Definition: duktape.c:56237
#define DUK_HOBJECT_HASHIDX_UNUSED
Definition: duktape.c:7089
#define DUK_HOBJECT_SET_PROPS(heap, h, x)
Definition: duktape.c:6894
#define DUK_ASC_BACKSLASH
Definition: duktape.c:10850
#define DUK_ENC_OP_A_B_C(op, a, b, c)
Definition: duktape.c:3445
DUK_LOCAL DUK_EXEC_ALWAYS_INLINE_PERF void duk__vm_logical_not(duk_hthread *thr, duk_uint_fast_t idx_src, duk_uint_fast_t idx_dst)
Definition: duktape.c:77751
DUK_LOCAL void duk__append_reop(duk_re_compiler_ctx *re_ctx, duk_uint32_t reop)
Definition: duktape.c:90616
#define DUK_HEAPHDR_SET_FINALIZED(h)
Definition: duktape.c:4794
DUK_LOCAL void duk__cbor_decode_buffer(duk_cbor_decode_context *dec_ctx, duk_uint8_t expected_base)
Definition: duktape.c:31693
#define DUK__SM_PLUS
Definition: duktape.c:32819
#define DUK_CALL_FLAG_ALLOW_ECMATOECMA
Definition: duktape.c:11098
#define DUK_TVAL_SET_TVAL_UPDREF_NORZ(thr, tv_dst, tv_src)
Definition: duktape.c:5829
DUK_INTERNAL_DECL duk_ret_t duk_bi_math_object_clz32(duk_context *ctx)
Definition: duktape.c:41018
#define DUK_HOBJECT_HAS_VIRTUAL_PROPERTIES(h)
Definition: duktape.c:6743
#define DUK_TOK_WITH
Definition: duktape.c:3878
#define DUK_DBLUNION_SET_HIGH32(u, v)
Definition: duktape.c:361
#define DUK_STRDATA_DATA_LENGTH
Definition: duktape.c:2093
#define DUK_PROPDESC_FLAGS_EC
Definition: duktape.c:6857
#define DUK_OP_MOD_RR
Definition: duktape.c:3563
struct duk_compiler_instr duk_compiler_instr
Definition: duktape.c:882
#define DUK_STRIDX_OWN_KEYS
Definition: duktape.c:1804
#define DUK_HEAP_DBG_RATELIMIT_OPCODES
Definition: duktape.c:9209
#define DUK_OP_BASR_RR
Definition: duktape.c:3598
DUK_LOCAL duk_double_t duk__push_this_number_plain(duk_hthread *thr)
Definition: duktape.c:41101
#define DUK__BP_COMMA
Definition: duktape.c:69324
#define DUK_OP_UNUSED230
Definition: duktape.c:3745
DUK_INTERNAL_DECL duk_tval * duk_get_borrowed_this_tval(duk_hthread *thr)
Definition: duktape.c:23283
DUK_EXTERNAL void duk_require_valid_index(duk_hthread *thr, duk_idx_t idx)
Definition: duktape.c:19058
#define DUK_HEAPHDR_PREDEC_REFCOUNT(h)
Definition: duktape.c:4731
#define DUK_TB_FLAG_NOBLAME_FILELINE
Definition: duktape.c:8071
DUK_LOCAL_DECL void duk__json_dec_number(duk_json_dec_ctx *js_ctx)
Definition: duktape.c:38003
DUK_LOCAL duk_idx_t duk__call_get_idx_func(duk_hthread *thr, duk_idx_t nargs, duk_idx_t other)
Definition: duktape.c:15239
DUK_LOCAL int duk__bi_is_zero(duk__bigint *x)
Definition: duktape.c:88714
DUK_LOCAL DUK_INLINE void duk__coerce_nonstrict_this_binding(duk_hthread *thr, duk_idx_t idx_this)
Definition: duktape.c:67173
DUK_INTERNAL_DECL void duk_push_hstring_empty(duk_hthread *thr)
Definition: duktape.c:24556
#define DUK_HSTRING_GET_CHARLEN(x)
Definition: duktape.c:6415
DUK_INTERNAL_DECL duk_ret_t duk_bi_function_prototype_hasinstance(duk_context *ctx)
Definition: duktape.c:36630
DUK_LOCAL const duk_uint8_t duk__json_eatwhite_lookup[256]
Definition: duktape.c:37499
#define DUK_OP_POSTINCP_CC
Definition: duktape.c:3649
#define DUK_OP_BXOR
Definition: duktape.c:3582
DUK_INTERNAL_DECL void duk_xdef_prop(duk_hthread *thr, duk_idx_t obj_idx, duk_small_uint_t desc_flags)
Definition: duktape.c:18072
DUK_LOCAL_DECL void duk__copy_ispec(duk_compiler_ctx *comp_ctx, duk_ispec *src, duk_ispec *dst)
Definition: duktape.c:71008
DUK_LOCAL const duk_uint8_t duk__decode_uri_component_reserved_table[16]
Definition: duktape.c:36698
DUK_INTERNAL_DECL duk_uint32_t duk_js_touint32(duk_hthread *thr, duk_tval *tv)
Definition: duktape.c:82822
DUK_LOCAL void duk__appendbuffer_ascii(duk_lexer_ctx *lex_ctx, duk_codepoint_t x)
Definition: duktape.c:86252
#define DUK_PAUSE_FLAG_ONE_OPCODE_ACTIVE
Definition: duktape.c:9216
#define DUK_STRIDX_INDEX
Definition: duktape.c:1726
DUK_INTERNAL_DECL void * duk_heap_mem_alloc_checked(duk_hthread *thr, duk_size_t size)
Definition: duktape.c:53690
#define duk_js_samevalue(tv_x, tv_y)
Definition: duktape.c:11150
#define DUK_DBG_CMD_STATUS
Definition: duktape.c:9722
#define DUK__NO_FORMALS
Definition: duktape.c:14435
DUK_EXTERNAL const char * duk_push_lstring(duk_hthread *thr, const char *str, duk_size_t len)
Definition: duktape.c:23117
#define DUK__GETCONST_MAX_CONSTS_CHECK
Definition: duktape.c:69074
#define DUK_OP_UNUSED226
Definition: duktape.c:3741
DUK_LOCAL_DECL duk_uint8_t duk__json_dec_get(duk_json_dec_ctx *js_ctx)
Definition: duktape.c:37599
#define DUK_STRIDX_INT_FINALIZER
Definition: duktape.c:1894
DUK_INTERNAL_DECL void duk_hbufobj_push_uint8array_from_plain(duk_hthread *thr, duk_hbuffer *h_buf)
Definition: duktape.c:28178
DUK_LOCAL duk_uint8_t * duk__json_enc_buffer_data_hex(const duk_uint8_t *src, duk_size_t src_len, duk_uint8_t *dst)
Definition: duktape.c:38788
#define DUK_HOBJECT_CLASS_ARRAY
Definition: duktape.c:6637
#define DUK_STRIDX_CONSTRUCTOR
Definition: duktape.c:1732
#define DUK_OP_GETPROPC_RR
Definition: duktape.c:3723
#define DUK_ERROR_INTERNAL(thr)
Definition: duktape.c:10276
#define DUK__EMIT_STRIDX(js_ctx, i)
Definition: duktape.c:38421
DUK_LOCAL void duk__cbor_decode_and_join_strbuf(duk_cbor_decode_context *dec_ctx, duk_uint8_t expected_base)
Definition: duktape.c:31753
DUK_INTERNAL_DECL duk_ret_t duk_bi_number_prototype_value_of(duk_context *ctx)
Definition: duktape.c:41180
DUK_EXTERNAL void duk_load_function(duk_hthread *thr)
Definition: duktape.c:15133
DUK_EXTERNAL duk_idx_t duk_push_bare_array(duk_hthread *thr)
Definition: duktape.c:23581
DUK_LOCAL duk_small_int_t duk__array_sort_compare(duk_hthread *thr, duk_int_t idx1, duk_int_t idx2)
Definition: duktape.c:26714
DUK_INTERNAL_DECL duk_ret_t duk_bi_string_prototype_substring(duk_context *ctx)
Definition: duktape.c:43030
#define DUK_HOBJECT_CLASS_DATE
Definition: duktape.c:6641
DUK_INTERNAL_DECL duk_bool_t duk_bi_date_timeval_in_leeway_range(duk_double_t x)
Definition: duktape.c:33163
#define DUK__LENGTH_PROP_BITS
Definition: duktape.c:64538
DUK_EXTERNAL duk_bool_t duk_get_boolean_default(duk_hthread *thr, duk_idx_t idx, duk_bool_t def_value)
Definition: duktape.c:20237
DUK_LOCAL_DECL duk_compiler_instr * duk__get_instr_ptr(duk_compiler_ctx *comp_ctx, duk_int_t pc)
Definition: duktape.c:70155
DUK_INTERNAL DUK_COLD void duk_err_type_invalid_state(duk_hthread *thr, const char *filename, duk_int_t linenumber)
Definition: duktape.c:12557
#define DUK_STR_BASE64_ENCODE_FAILED
Definition: duktape.c:3222
DUK_LOCAL_DECL void duk__emit_2(duk_json_enc_ctx *js_ctx, duk_uint_fast8_t ch1, duk_uint_fast8_t ch2)
Definition: duktape.c:38428
#define DUK_DBLUNION_IS_ANYZERO(u)
Definition: duktape.c:564
#define DUK_TVAL_INCREF(thr, tv)
Definition: duktape.c:5041
#define DUK_TOK_GE
Definition: duktape.c:3928
DUK_LOCAL void duk__objlit_flush_keys(duk_compiler_ctx *comp_ctx, duk__objlit_state *st)
Definition: duktape.c:72095
#define DUK_TVAL_GET_FASTINT_U32(tv)
Definition: duktape.c:1452
DUK_LOCAL void duk__inspect_multiple_uint(duk_hthread *thr, const char *fmt, duk_int_t *vals)
Definition: duktape.c:17296
#define DUK_HCOMPFUNC_GET_DATA(heap, h)
Definition: duktape.c:7581
DUK_LOCAL DUK_EXEC_ALWAYS_INLINE_PERF duk_double_t duk__compute_mod(duk_double_t d1, duk_double_t d2)
Definition: duktape.c:77225
DUK_EXTERNAL void duk_xcopymove_raw(duk_hthread *to_thr, duk_hthread *from_thr, duk_idx_t count, duk_bool_t is_copy)
Definition: duktape.c:20080
#define DUK_DBG_CMD_GETOBJPROPDESCRANGE
Definition: duktape.c:9752
#define DUK_CAT_HAS_FINALLY_ENABLED(c)
Definition: duktape.c:8099
#define duk_require_hobject_promote_lfunc(thr, idx)
Definition: duktape.c:6029
DUK_LOCAL duk_bool_t duk__declvar_helper(duk_hthread *thr, duk_hobject *env, duk_hstring *name, duk_tval *val, duk_small_uint_t prop_flags, duk_bool_t is_func_decl)
Definition: duktape.c:85440
#define DUK__IVAL_FLAG_REQUIRE_TEMP
Definition: duktape.c:70945
#define DUK__CALL_HANDLING_REQUIRE_STACK
Definition: duktape.c:66125
#define DUK_HOBJECT_E_GET_VALUE_SETTER(heap, h, i)
Definition: duktape.c:7011
DUK_INTERNAL_DECL duk_bool_t duk_get_prop_stridx(duk_hthread *thr, duk_idx_t obj_idx, duk_small_uint_t stridx)
Definition: duktape.c:17721
#define DUK__SM_NUL
Definition: duktape.c:32826
#define DUK_HOBJECT_FLAG_NATFUNC
Definition: duktape.c:6596
DUK_LOCAL duk_small_int_t duk__json_dec_string_escape(duk_json_dec_ctx *js_ctx, duk_uint8_t **ext_p)
Definition: duktape.c:37679
DUK_INTERNAL const duk_uint8_t duk_lc_digits[36]
Definition: duktape.c:14027
#define DUK_REALLOC_INDIRECT(heap, cb, ud, newsize)
Definition: duktape.c:9171
#define DUK_PROPDESC_FLAG_ACCESSOR
Definition: duktape.c:6839
#define DUK_HOBJECT_HAS_CONSTRUCTABLE(h)
Definition: duktape.c:6746
DUK_INTERNAL_DECL void duk_hthread_create_builtin_objects(duk_hthread *thr)
Definition: duktape.c:64721
#define DUK_OP_NOP
Definition: duktape.c:3719
DUK_LOCAL duk_bool_t duk__getid_activation_regs(duk_hthread *thr, duk_hstring *name, duk_activation *act, duk__id_lookup_result *out)
Definition: duktape.c:84729
DUK_INTERNAL_DECL duk_ret_t duk_bi_object_constructor_define_property(duk_context *ctx)
Definition: duktape.c:41809
#define DUK__RZ_OBJECT()
Definition: duktape.c:54723
DUK_LOCAL void duk__set_catcher_regs_norz(duk_hthread *thr, duk_catcher *cat, duk_tval *tv_val_unstable, duk_small_uint_t lj_type)
Definition: duktape.c:78010
DUK_LOCAL void duk__free_stringtable(duk_heap *heap)
Definition: duktape.c:50482
#define DUK_OP_INSTOF_CR
Definition: duktape.c:3604
#define DUK_REOP_INVRANGES
Definition: duktape.c:4492
#define DUK__PROP_TYPE_ACCESSOR
Definition: duktape.c:64551
#define DUK_BW_RESET_SIZE(thr, bw_ctx)
Definition: duktape.c:2569
DUK_INTERNAL_DECL void duk_numconv_parse(duk_hthread *thr, duk_small_int_t radix, duk_small_uint_t flags)
Definition: duktape.c:90484
#define DUK_ASC_LC_L
Definition: duktape.c:10866
DUK_LOCAL_DECL void duk__advance(duk_compiler_ctx *ctx)
Definition: duktape.c:69561
#define DUK_OP_SNEQ_CR
Definition: duktape.c:3513
#define DUK_HOBJECT_E_GET_KEY(heap, h, i)
Definition: duktape.c:7003
DUK_EXTERNAL duk_bool_t duk_is_undefined(duk_hthread *thr, duk_idx_t idx)
Definition: duktape.c:22660
#define DUK_HSTRING_HAS_PINNED_LITERAL(x)
Definition: duktape.c:6346
#define DUK__FUNCTION_INIT_REQUIRE_SLOTS
Definition: duktape.c:69106
#define DUK_HOBJECT_CLASS_ARGUMENTS
Definition: duktape.c:6639
#define DUK_HOBJECT_FLAG_BOUNDFUNC
Definition: duktape.c:6594
#define DUK__RZ_SUPPRESS_CHECK()
Definition: duktape.c:54703
DUK_LOCAL duk_idx_t duk__call_get_idx_func_unvalidated(duk_hthread *thr, duk_idx_t nargs, duk_idx_t other)
Definition: duktape.c:15259
#define DUK_OP_EQ_CR
Definition: duktape.c:3498
#define DUK_OP_LE_CR
Definition: duktape.c:3533
#define DUK_DPRINT
Definition: duktape.c:9974
DUK_INTERNAL_DECL duk_ret_t duk_bi_string_prototype_slice(duk_context *ctx)
Definition: duktape.c:43107
#define DUK_OP_UNUSED239
Definition: duktape.c:3754
#define DUK_STR_CANNOT_DELETE_IDENTIFIER
Definition: duktape.c:3274
DUK_INTERNAL_DECL duk_ret_t duk_bi_function_constructor(duk_context *ctx)
Definition: duktape.c:36200
DUK_EXTERNAL void duk_push_heap_stash(duk_hthread *thr)
Definition: duktape.c:23378
DUK_LOCAL duk_int_t duk__str_search_shared(duk_hthread *thr, duk_hstring *h_this, duk_hstring *h_search, duk_int_t start_cpos, duk_bool_t backwards)
Definition: duktape.c:42721
#define DUK_OP_ADD_CC
Definition: duktape.c:3546
#define DUK_STRIDX_APPLY
Definition: duktape.c:1789
#define DUK__LT_BODY(barg, carg)
DUK_LOCAL void duk__handle_bound_chain_for_call(duk_hthread *thr, duk_idx_t idx_func, duk_bool_t is_constructor_call)
Definition: duktape.c:66617
DUK_LOCAL duk_bool_t duk__key_is_plain_buf_ownprop(duk_hthread *thr, duk_hbuffer *buf, duk_hstring *key, duk_uint32_t arr_idx)
Definition: duktape.c:58098
#define DUK_PROPDESC_FLAGS_E
Definition: duktape.c:6853
#define DUK_TVAL_GET_TAG(tv)
Definition: duktape.c:1479
#define DUK_OP_LT_RC
Definition: duktape.c:3529
DUK_EXTERNAL void * duk_alloc(duk_hthread *thr, duk_size_t size)
Definition: duktape.c:17582
DUK_INTERNAL_DECL duk_double_t duk_raw_readinc_double_be(const duk_uint8_t **p)
Definition: duktape.c:13945
#define DUK_HOBJECT_FLAG_EXOTIC_ARGUMENTS
Definition: duktape.c:6611
DUK_INTERNAL_DECL duk_ret_t duk_bi_string_constructor(duk_context *ctx)
Definition: duktape.c:42799
#define DUK_STR_INVALID_INPUT
Definition: duktape.c:3187
DUK_INTERNAL_DECL duk_int_t duk_handle_call_unprotected(duk_hthread *thr, duk_idx_t idx_func, duk_small_uint_t call_flags)
Definition: duktape.c:68483
DUK_INTERNAL_DECL duk_ret_t duk_bi_error_prototype_stack_getter(duk_context *ctx)
Definition: duktape.c:36099
#define DUK_PROPDESC_FLAGS_WE
Definition: duktape.c:6855
#define DUK_HBUFOBJ_ELEM_INT8
Definition: duktape.c:7898
DUK_LOCAL void duk__concat_and_join_helper(duk_hthread *thr, duk_idx_t count_in, duk_bool_t is_join)
Definition: duktape.c:25599
#define DUK_TOK_ALSHIFT_EQ
Definition: duktape.c:3960
#define DUK_HOBJECT_IS_NONBOUND_FUNCTION(h)
Definition: duktape.c:6726
#define DUK_OP_EXP_RC
Definition: duktape.c:3570
#define DUK_ASC_UC_X
Definition: duktape.c:10846
#define DUK_ASSERT(x)
Definition: duktape.c:10545
DUK_INTERNAL_DECL duk_ret_t duk_bi_array_prototype_slice(duk_context *ctx)
Definition: duktape.c:27244
DUK_LOCAL const duk_uint8_t duk__json_quotestr_lookup[256]
Definition: duktape.c:37450
DUK_LOCAL_DECL void duk__json_dec_plain_string(duk_json_dec_ctx *js_ctx)
Definition: duktape.c:37850
#define DUK__EXPR_RBP_MASK
Definition: duktape.c:73926
DUK_INTERNAL_DECL duk_hstring * duk_get_hstring_notsymbol(duk_hthread *thr, duk_idx_t idx)
Definition: duktape.c:20839
DUK_LOCAL duk_uint32_t duk__insert_jump_offset(duk_re_compiler_ctx *re_ctx, duk_uint32_t offset, duk_int32_t skip)
Definition: duktape.c:90663
DUK_EXTERNAL void duk_put_function_list(duk_hthread *thr, duk_idx_t obj_idx, const duk_function_list_entry *funcs)
Definition: duktape.c:18355
DUK_EXTERNAL void * duk_get_pointer_default(duk_hthread *thr, duk_idx_t idx, void *def_value)
Definition: duktape.c:20592
#define DUK_TVAL_SET_UNDEFINED_UPDREF_NORZ
Definition: duktape.c:5419
#define DUK_STR_NOT_NULL
Definition: duktape.c:3199
#define DUK__ASSERT_LEFT(n)
Definition: duktape.c:14794
DUK_LOCAL void duk__mark_hstring(duk_heap *heap, duk_hstring *h)
Definition: duktape.c:52068
#define DUK_HBUFOBJ_INCREF(thr, h)
Definition: duktape.c:5064
#define DUK_DBG_CMD_RESUME
Definition: duktape.c:9734
#define DUK_OP_UNUSED241
Definition: duktape.c:3756
DUK_LOCAL double duk__ceil(double x)
Definition: duktape.c:40805
#define DUK_HOBJECT_SET_PROTOTYPE_UPDREF(thr, h, p)
Definition: duktape.c:7196
#define DUK_TOK_MUL_EQ
Definition: duktape.c:3956
DUK_INTERNAL_DECL duk_hstring * duk_known_hstring(duk_hthread *thr, duk_idx_t idx)
Definition: duktape.c:21353
#define DUK__BP_CALL
Definition: duktape.c:69339
#define DUK_STRIDX_REG_EXP
Definition: duktape.c:1612
#define DUK_STRIDX_UC_STRING
Definition: duktape.c:1600
#define DUK_STR_EMPTY_EXPR_NOT_ALLOWED
Definition: duktape.c:3279
DUK_INTERNAL_DECL duk_ret_t duk_bi_textdecoder_constructor(duk_context *ctx)
Definition: duktape.c:35687
DUK_EXTERNAL void duk_destroy_heap(duk_hthread *thr)
Definition: duktape.c:17145
DUK_LOCAL duk_codepoint_t duk__hexval_validate(duk_codepoint_t x)
Definition: duktape.c:86316
DUK_INTERNAL_DECL duk_ret_t duk_bi_error_prototype_filename_setter(duk_context *ctx)
Definition: duktape.c:36174
#define DUK_ASC_MINUS
Definition: duktape.c:10803
#define DUK_BIDX_STRING_PROTOTYPE
Definition: duktape.c:2296
DUK_INTERNAL_DECL duk_ret_t duk_bi_date_constructor_parse(duk_context *ctx)
Definition: duktape.c:34218
DUK_LOCAL void duk__cbor_encode_string_top(duk_cbor_encode_context *enc_ctx)
Definition: duktape.c:31160
DUK_INTERNAL_DECL duk_ret_t duk_bi_string_prototype_caseconv_shared(duk_context *ctx)
Definition: duktape.c:43147
#define DUK_BW_WRITE_RAW_U8_6(thr, bw_ctx, val1, val2, val3, val4, val5, val6)
Definition: duktape.c:2662
#define DUK_DBG_CMD_TRIGGERSTATUS
Definition: duktape.c:9732
#define DUK_HBUFOBJ_ELEM_UINT32
Definition: duktape.c:7901
#define DUK_HOBJECT_CLASS_UINT8CLAMPEDARRAY
Definition: duktape.c:6659
#define DUK_TVAL_IS_POINTER(tv)
Definition: duktape.c:1494
#define DUK_STRIDX_LC_UNDEFINED
Definition: duktape.c:1753
#define DUK_TOK_TRUE
Definition: duktape.c:3892
#define DUK_HOBJECT_GET_ASIZE(h)
Definition: duktape.c:7138
#define DUK_HOBJECT_CMASK_ALL
Definition: duktape.c:6670
#define DUK_OP_EQ_RR
Definition: duktape.c:3497
DUK_LOCAL void duk__handle_executor_error(duk_heap *heap, duk_activation *entry_act, duk_int_t entry_call_recursion_depth, duk_jmpbuf *entry_jmpbuf_ptr, volatile duk_bool_t *out_delayed_catch_setup)
Definition: duktape.c:80032
#define DUK__ADVANCECHARS(lex_ctx, count)
Definition: duktape.c:85798
#define DUK_DBG_CMD_THROW
Definition: duktape.c:9726
DUK_EXTERNAL duk_bool_t duk_put_prop_index(duk_hthread *thr, duk_idx_t obj_idx, duk_uarridx_t arr_idx)
Definition: duktape.c:17870
#define duk_memzero(dst, len)
Definition: duktape.c:3091
DUK_LOCAL void duk__append_u32(duk_re_compiler_ctx *re_ctx, duk_uint32_t x)
Definition: duktape.c:90593
DUK_INTERNAL_DECL void duk_hobject_compact_props(duk_hthread *thr, duk_hobject *obj)
Definition: duktape.c:59184
DUK_INTERNAL_DECL duk_ret_t duk_bi_performance_now(duk_context *ctx)
Definition: duktape.c:42121
DUK_INTERNAL_DECL duk_ret_t duk_bi_global_object_is_finite(duk_context *ctx)
Definition: duktape.c:37313
DUK_LOCAL void duk__finalize_refcounts(duk_heap *heap)
Definition: duktape.c:52545
#define DUK_REOP_SAVE
Definition: duktape.c:4498
#define DUK__ASSERT_SPACE()
Definition: duktape.c:18735
#define DUK_TVAL_IS_UNUSED(tv)
Definition: duktape.c:1481
#define DUK_ACT_FLAG_STRICT
Definition: duktape.c:8057
DUK_EXTERNAL duk_int_t duk_pcall_method(duk_hthread *thr, duk_idx_t nargs)
Definition: duktape.c:15440
#define DUK_DOUBLE_2TO32
Definition: duktape.c:2373
#define DUK_HSTRING_GET_HASH(x)
Definition: duktape.c:6383
DUK_EXTERNAL void duk_to_null(duk_hthread *thr, duk_idx_t idx)
Definition: duktape.c:21428
#define DUK_TOK_LE
Definition: duktape.c:3927
#define DUK_FREE(heap, ptr)
Definition: duktape.c:9172
DUK_LOCAL duk_heaphdr * duk__known_heaphdr(duk_hthread *thr, duk_idx_t idx)
Definition: duktape.c:21336
#define DUK_HEAPHDR_HAS_TEMPROOT(h)
Definition: duktape.c:4788
#define DUK_ASC_UC_B
Definition: duktape.c:10824
DUK_EXTERNAL duk_bool_t duk_get_prop_heapptr(duk_hthread *thr, duk_idx_t obj_idx, void *ptr)
Definition: duktape.c:17713
DUK_LOCAL duk_double_t duk__tonumber_string_raw(duk_hthread *thr)
Definition: duktape.c:82615
#define DUK_LJ_TYPE_RETURN
Definition: duktape.c:9000
DUK_EXTERNAL void duk_seal(duk_hthread *thr, duk_idx_t obj_idx)
Definition: duktape.c:18339
#define DUK_TOK_LAND
Definition: duktape.c:3949
DUK_INTERNAL_DECL duk_ret_t duk_bi_duktape_object_gc(duk_context *ctx)
Definition: duktape.c:35127
#define DUK_STRIDX_WELLKNOWN_SYMBOL_IS_CONCAT_SPREADABLE
Definition: duktape.c:1816
#define DUK_BW_ENSURE_RAW(thr, bw_ctx, sz, ptr)
Definition: duktape.c:2590
DUK_INTERNAL_DECL duk_ret_t duk_bi_symbol_key_for(duk_context *ctx)
Definition: duktape.c:44428
#define DUK_HOBJECT_E_SET_KEY(heap, h, i, k)
Definition: duktape.c:7020
DUK_LOCAL void * duk__get_pointer_raw(duk_hthread *thr, duk_idx_t idx, void *def_value)
Definition: duktape.c:20562
DUK_LOCAL_DECL duk_regconst_t duk__ivalue_toregconst_raw(duk_compiler_ctx *comp_ctx, duk_ivalue *x, duk_regconst_t forced_reg, duk_small_uint_t flags)
Definition: duktape.c:71541
#define DUK_HOBJECT_FLAG_CREATEARGS
Definition: duktape.c:6607
DUK_LOCAL const duk_uint8_t duk__decode_uri_reserved_table[16]
Definition: duktape.c:36686
#define DUK_TVAL_SET_NUMBER_CHKFAST_SLOW(tv, d)
Definition: duktape.c:1343
DUK_LOCAL void duk__uncaught_error_aware(duk_hthread *thr)
Definition: duktape.c:49607
#define DUK_HOBJECT_E_SLOT_CLEAR_ACCESSOR(heap, h, i)
Definition: duktape.c:7082
DUK_INTERNAL_DECL duk_uint32_t duk_raw_read_u32_be(const duk_uint8_t *p)
Definition: duktape.c:13906
DUK_INTERNAL_DECL void duk_lexer_setpoint(duk_lexer_ctx *lex_ctx, duk_lexer_point *pt)
Definition: duktape.c:86301
DUK_INTERNAL_DECL duk_ret_t duk_bi_array_prototype_indexof_shared(duk_context *ctx)
Definition: duktape.c:27420
#define DUK_TVAL_SET_STRING_UPDREF
Definition: duktape.c:5438
#define DUK_HOBJECT_GET_CLASS_STRING(heap, h)
Definition: duktape.c:7174
#define DUK_HEAPHDR_HTYPE_VALID(h)
Definition: duktape.c:4761
DUK_EXTERNAL duk_uint_t duk_require_uint(duk_hthread *thr, duk_idx_t idx)
Definition: duktape.c:20371
#define DUK_BIDX_UINT8CLAMPEDARRAY_PROTOTYPE
Definition: duktape.c:2329
DUK_LOCAL void duk__push_stridx_or_string(duk_hthread *thr, duk_bitdecoder_ctx *bd)
Definition: duktape.c:64695
const duk_uint8_t duk_unicode_ids_noa[1116]
Definition: duktape.c:93782
#define DUK_PROPDESC_FLAGS_C
Definition: duktape.c:6854
#define DUK_TOK_BXOR_EQ
Definition: duktape.c:3965
#define DUK_HOBJECT_CLASS_NONE
Definition: duktape.c:6635
#define DUK_OP_MUL_RC
Definition: duktape.c:3555
#define DUK_HTHREAD_STRING_INT_VARENV(thr)
Definition: duktape.c:1893
#define DUK_ERROR_URI(thr, msg)
Definition: duktape.c:10383
#define DUK_STRIDX_UC_DATE
Definition: duktape.c:1609
#define DUK_BIDX_INT32ARRAY_PROTOTYPE
Definition: duktape.c:2332
#define DUK__RETURN_SHARED()
#define DUK_HSTRING_FLAG_RESERVED_WORD
Definition: duktape.c:6332
#define DUK_BW_GET_BASEPTR(thr, bw_ctx)
Definition: duktape.c:2561
#define DUK_COMPARE_FLAG_EVAL_LEFT_FIRST
Definition: duktape.c:11110
#define DUK__OUTPUT_TYPE_LINENUMBER
Definition: duktape.c:35897
#define DUK__ITER_FOREACH
Definition: duktape.c:27509
#define DUK_STR_NOT_OBJECT_COERCIBLE
Definition: duktape.c:3215
#define DUK_STRIDX_LC_BOOLEAN
Definition: duktape.c:1738
#define DUK__REGP(x)
Definition: duktape.c:79923
#define DUK_DBLUNION_NORMALIZE_NAN_CHECK(u)
Definition: duktape.c:549
DUK_LOCAL void duk__handle_safe_call_inner(duk_hthread *thr, duk_safe_call_function func, void *udata, duk_hthread *entry_curr_thread, duk_uint_fast8_t entry_thread_state, duk_idx_t idx_retbase, duk_idx_t num_stack_rets)
Definition: duktape.c:68506
#define DUK_OP_SEQ_CR
Definition: duktape.c:3508
DUK_INTERNAL_DECL duk_ret_t duk_bi_string_prototype_repeat(duk_context *ctx)
Definition: duktape.c:44028
#define DUK_DBLUNION_HAS_SIGNBIT(u)
Definition: duktape.c:623
#define DUK_ASSERT_DISABLE(x)
Definition: duktape.c:10556
#define DUK__UNPACK_RULE(rule, var_nextidx, var_flags)
Definition: duktape.c:32837
#define duk_memcpy_unsafe(dst, src, len)
Definition: duktape.c:3037
DUK_INTERNAL_DECL duk_ret_t duk_bi_math_object_random(duk_context *ctx)
Definition: duktape.c:40926
#define DUK_OP_PUTPROP
Definition: duktape.c:3617
DUK_LOCAL DUK_EXEC_NOINLINE_PERF void duk__handle_op_initset_initget(duk_hthread *thr, duk_uint_fast32_t ins)
Definition: duktape.c:79371
DUK_LOCAL duk_hbufobj * duk__require_bufobj_value(duk_hthread *thr, duk_idx_t idx)
Definition: duktape.c:27972
DUK_INTERNAL const duk_uint16_t duk_unicode_re_ranges_digit[2]
Definition: duktape.c:13834
#define DUK_HOBJECT_FLAG_COMPFUNC
Definition: duktape.c:6595
DUK_LOCAL DUK_ALWAYS_INLINE void duk__base64_encode_fast_1(const duk_uint8_t *src, duk_uint8_t *dst)
Definition: duktape.c:15845
DUK_EXTERNAL void duk_debugger_pause(duk_hthread *thr)
Definition: duktape.c:17071
DUK_EXTERNAL const char * duk_api_global_filename
Definition: duktape.c:18711
struct duk_hcompfunc duk_hcompfunc
Definition: duktape.c:841
#define DUK__BITPACK_LOOKUP2
Definition: duktape.c:100037
#define DUK_ASSERT_REFCOUNT_NONZERO_TVAL(tv)
Definition: duktape.c:10577
DUK_LOCAL duk_bool_t duk__init_heap_thread(duk_heap *heap)
Definition: duktape.c:50787
DUK_EXTERNAL void * duk_opt_pointer(duk_hthread *thr, duk_idx_t idx, void *def_value)
Definition: duktape.c:20583
DUK_EXTERNAL duk_bool_t duk_equals(duk_hthread *thr, duk_idx_t idx1, duk_idx_t idx2)
Definition: duktape.c:25194
#define DUK_STR_NOT_OBJECT
Definition: duktape.c:3203
#define DUK_HEAPHDR_PREINC_REFCOUNT(h)
Definition: duktape.c:4730
DUK_LOCAL const duk_uint8_t * duk__match_regexp(duk_re_matcher_ctx *re_ctx, const duk_uint8_t *pc, const duk_uint8_t *sp)
Definition: duktape.c:91959
#define DUK_HOBJECT_IS_CALLABLE(h)
Definition: duktape.c:6732
#define DUK_HOBJECT_SET_NOTAIL(h)
Definition: duktape.c:6786
DUK_INTERNAL_DECL void duk_hobject_prepare_property_descriptor(duk_hthread *thr, duk_idx_t idx_in, duk_uint_t *out_defprop_flags, duk_idx_t *out_idx_value, duk_hobject **out_getter, duk_hobject **out_setter)
Definition: duktape.c:63058
DUK_EXTERNAL void duk_push_false(duk_hthread *thr)
Definition: duktape.c:23024
DUK_INTERNAL_DECL void duk_hthread_terminate(duk_hthread *thr)
Definition: duktape.c:65432
DUK_LOCAL duk_ret_t duk__safe_to_stacktrace_raw(duk_hthread *thr, void *udata)
Definition: duktape.c:21835
#define DUK__IDX_VARIANT
Definition: duktape.c:17341
DUK_LOCAL duk_ret_t duk__pnew_helper(duk_hthread *thr, void *udata)
Definition: duktape.c:15536
#define DUK_HBUFOBJ_ELEM_FLOAT64
Definition: duktape.c:7904
#define DUK_OP_UNUSED250
Definition: duktape.c:3765
#define DUK_STRIDX_ERR_THROW
Definition: duktape.c:1909
DUK_INTERNAL_DECL void duk_heap_run_finalizer(duk_heap *heap, duk_hobject *obj)
Definition: duktape.c:51857
#define DUK_TOK_VAR
Definition: duktape.c:3874
DUK_EXTERNAL duk_double_t duk_require_number(duk_hthread *thr, duk_idx_t idx)
Definition: duktape.c:20308
#define DUK__EMIT_FLAG_BC_REGCONST
Definition: duktape.c:70145
#define DUK_STR_REG_LIMIT
Definition: duktape.c:3318
DUK_INTERNAL_DECL duk_ret_t duk_bi_thread_current(duk_context *ctx)
Definition: duktape.c:44788
DUK_EXTERNAL void duk_def_prop(duk_hthread *thr, duk_idx_t obj_idx, duk_uint_t flags)
Definition: duktape.c:18169
DUK_LOCAL duk_ret_t duk__do_compile(duk_hthread *thr, void *udata)
Definition: duktape.c:16703
#define DUK_OP_LT
Definition: duktape.c:3526
#define DUK_BIDX_FLOAT32ARRAY_PROTOTYPE
Definition: duktape.c:2334
DUK_INTERNAL_DECL duk_ret_t duk_bi_symbol_tostring_shared(duk_context *ctx)
Definition: duktape.c:44410
#define DUK_HOBJECT_CLASS_AS_FLAGS(v)
Definition: duktape.c:6632
DUK_LOCAL void duk__call_thread_state_update(duk_hthread *thr)
Definition: duktape.c:67964
#define DUK_OP_IFFALSE_C
Definition: duktape.c:3541
DUK_INTERNAL_DECL duk_small_int_t duk_unicode_is_identifier_start(duk_codepoint_t cp)
Definition: duktape.c:13295
#define DUK_ASC_LCURLY
Definition: duktape.c:10881
DUK_INTERNAL_DECL duk_ret_t duk_bi_thread_resume(duk_context *ctx)
Definition: duktape.c:44522
DUK_LOCAL const duk__exp_limits duk__str2num_exp_limits[]
Definition: duktape.c:88205
duk_double_t(* duk__toint_coercer)(duk_hthread *thr, duk_tval *tv)
Definition: duktape.c:21630
DUK_EXTERNAL void duk_decode_string(duk_hthread *thr, duk_idx_t idx, duk_decode_char_function callback, void *udata)
Definition: duktape.c:25762
#define DUK_HOBJECT_SET_ESIZE(h, v)
Definition: duktape.c:7128
#define DUK_HOBJECT_CLASS_NUMBER
Definition: duktape.c:6645
DUK_LOCAL void duk__strtable_grow_inplace(duk_heap *heap)
Definition: duktape.c:55600
DUK_EXTERNAL void duk_error_va_raw(duk_hthread *thr, duk_errcode_t err_code, const char *filename, duk_int_t line, const char *fmt, va_list ap)
Definition: duktape.c:25091
#define DUK_OP_MOD_CR
Definition: duktape.c:3564
#define DUK_OP_BASL
Definition: duktape.c:3587
#define DUK_HSTRING_SET_EVAL_OR_ARGUMENTS(x)
Definition: duktape.c:6354
#define DUK__JSON_ENCSTR_CHUNKSIZE
Definition: duktape.c:37385
#define DUK_DBG_CMD_ADDBREAK
Definition: duktape.c:9739
static const duk_uint32_t duk__bufobj_flags_lookup[]
Definition: duktape.c:23916
DUK_INTERNAL_DECL void duk_tval_set_number_chkfast_slow(duk_tval *tv, duk_double_t x)
Definition: duktape.c:93669
#define duk_xdef_prop_stridx_short(thr, obj_idx, stridx, desc_flags)
Definition: duktape.c:6198
DUK_EXTERNAL void * duk_get_buffer_default(duk_hthread *thr, duk_idx_t idx, duk_size_t *out_size, void *def_ptr, duk_size_t def_len)
Definition: duktape.c:20693
DUK_LOCAL duk_uint32_t duk__encode_i32(duk_int32_t x)
Definition: duktape.c:90572
#define DUK_HOBJECT_FLAG_SPECIAL_CALL
Definition: duktape.c:6614
#define DUK_STRIDX_VALUE
Definition: duktape.c:1681
#define DUK_S2N_FLAG_ALLOW_NAKED_FRAC
Definition: duktape.c:11286
DUK_INTERNAL_DECL void duk_free_hobject(duk_heap *heap, duk_hobject *h)
Definition: duktape.c:50276
DUK_INTERNAL DUK_COLD void duk_err_type_invalid_args(duk_hthread *thr, const char *filename, duk_int_t linenumber)
Definition: duktape.c:12554
#define DUK_HSTRING_HAS_EXTDATA(x)
Definition: duktape.c:6345
#define DUK_HEAP_HAS_INTERRUPT_RUNNING(heap)
Definition: duktape.c:8975
#define DUK_STR_INVALID_TOKEN
Definition: duktape.c:3265
DUK_LOCAL duk_bool_t duk__compare_number(duk_bool_t retval, duk_double_t d1, duk_double_t d2)
Definition: duktape.c:83301
#define DUK_DEC_C(x)
Definition: duktape.c:3437
#define DUK_LFUNC_MAGIC_MIN
Definition: duktape.c:1542
#define DUK_HTHREAD_STATE_INACTIVE
Definition: duktape.c:8152
#define DUK__PROP_TYPE_BUILTIN
Definition: duktape.c:64547
#define DUK__FUN()
Definition: duktape.c:79912
DUK_EXTERNAL duk_errcode_t duk_get_error_code(duk_hthread *thr, duk_idx_t idx)
Definition: duktape.c:22923
#define DUK_OP_GT_CR
Definition: duktape.c:3518
#define DUK_STR_INVALID_ARGS
Definition: duktape.c:3185
#define DUK_ACT_FLAG_DIRECT_EVAL
Definition: duktape.c:8061
DUK_LOCAL_DECL void duk__add_label(duk_compiler_ctx *comp_ctx, duk_hstring *h_label, duk_int_t pc_label, duk_int_t label_id)
Definition: duktape.c:71722
DUK_INTERNAL_DECL duk_hstring * duk_get_hstring(duk_hthread *thr, duk_idx_t idx)
Definition: duktape.c:20834
DUK_EXTERNAL void duk_error_raw(duk_hthread *thr, duk_errcode_t err_code, const char *filename, duk_int_t line, const char *fmt,...)
Definition: duktape.c:25104
#define DUK_IVAL_PLAIN
Definition: duktape.c:4263
DUK_INTERNAL_DECL duk_ret_t duk_bi_object_prototype_property_is_enumerable(duk_context *ctx)
Definition: duktape.c:41648
DUK_INTERNAL_DECL duk_ret_t duk_bi_string_prototype_search(duk_context *ctx)
Definition: duktape.c:43900
duk_int32_t duk_regconst_t
Definition: duktape.c:4281
DUK_INTERNAL_DECL duk_ret_t duk_bi_global_object_encode_uri_component(duk_context *ctx)
Definition: duktape.c:37339
DUK_EXTERNAL const char * duk_hex_encode(duk_hthread *thr, duk_idx_t idx)
Definition: duktape.c:16429
DUK_LOCAL duk_int32_t duk__bc_get_i32(duk_re_matcher_ctx *re_ctx, const duk_uint8_t **pc)
Definition: duktape.c:91835
#define DUK_HBUFFER_FLAG_EXTERNAL
Definition: duktape.c:8585
DUK_EXTERNAL duk_size_t duk_get_length(duk_hthread *thr, duk_idx_t idx)
Definition: duktape.c:21251
DUK_INTERNAL_DECL duk_hstring * duk_heap_strtable_intern(duk_heap *heap, const duk_uint8_t *str, duk_uint32_t blen)
Definition: duktape.c:56052
DUK_INTERNAL_DECL duk_int_t duk_to_int_check_range(duk_hthread *thr, duk_idx_t idx, duk_int_t minval, duk_int_t maxval)
Definition: duktape.c:22054
DUK_INTERNAL const duk_uint16_t duk_unicode_re_ranges_not_wordchar[10]
Definition: duktape.c:13862
DUK_LOCAL_DECL void duk__ispec_toforcedreg(duk_compiler_ctx *comp_ctx, duk_ispec *x, duk_regconst_t forced_reg)
Definition: duktape.c:71305
DUK_LOCAL_DECL duk_bool_t duk__check_arguments_map_for_get(duk_hthread *thr, duk_hobject *obj, duk_hstring *key, duk_propdesc *temp_desc)
Definition: duktape.c:59620
DUK_INTERNAL_DECL void * duk_push_fixed_buffer_nozero(duk_hthread *thr, duk_size_t len)
Definition: duktape.c:24223
#define DUK_BIDX_GLOBAL_ENV
Definition: duktape.c:2287
DUK_INTERNAL_DECL void duk_js_compile(duk_hthread *thr, const duk_uint8_t *src_buffer, duk_size_t src_length, duk_small_uint_t flags)
Definition: duktape.c:77041
#define DUK_HOBJECT_IS_ENV(h)
Definition: duktape.c:6709
#define DUK__YEAR(x)
Definition: duktape.c:32738
#define DUK_HEAPHDR_HAS_REACHABLE(h)
Definition: duktape.c:4784
#define DUK__PI_MONTH
Definition: duktape.c:32788
#define DUK_STRIDX_INT32_ARRAY
Definition: duktape.c:1648
#define DUK_DBG_CMD_PAUSE
Definition: duktape.c:9733
#define DUK_HBUFFER_DYNAMIC_SET_DATA_PTR(heap, x, v)
Definition: duktape.c:8679
#define DUK_TOK_NEW
Definition: duktape.c:3867
#define DUK_OP_DELPROP_RR
Definition: duktape.c:3623
DUK_INTERNAL_DECL void duk_js_push_closure(duk_hthread *thr, duk_hcompfunc *fun_temp, duk_hobject *outer_var_env, duk_hobject *outer_lex_env, duk_bool_t add_auto_proto)
Definition: duktape.c:84040
DUK_INTERNAL_DECL void duk_dblunion_host_to_big(duk_double_union *u)
Definition: duktape.c:100864
DUK_INTERNAL_DECL duk_uint_fast32_t duk_heap_strcache_offset_char2byte(duk_hthread *thr, duk_hstring *h, duk_uint_fast32_t char_offset)
Definition: duktape.c:55102
DUK_INTERNAL_DECL duk_ret_t duk_bi_date_prototype_toprimitive(duk_context *ctx)
Definition: duktape.c:34477
#define DUK_HOBJECT_SET_STRICT(h)
Definition: duktape.c:6785
DUK_EXTERNAL void duk_cbor_decode(duk_hthread *thr, duk_idx_t idx, duk_uint_t decode_flags)
Definition: duktape.c:32617
#define DUK_STATS_INC(heap, fieldname)
Definition: duktape.c:9055
#define DUK_ASC_COLON
Definition: duktape.c:10816
#define DUK_CAT_FLAG_LEXENV_ACTIVE
Definition: duktape.c:8089
#define DUK_TOK_COLON
Definition: duktape.c:3952
#define DUK_ASC_LC_J
Definition: duktape.c:10864
#define DUK__FUNC_FLAG_METDEF
Definition: duktape.c:69301
DUK_INTERNAL_DECL duk_ret_t duk_bi_object_constructor_keys_shared(duk_context *ctx)
Definition: duktape.c:41944
#define DUK_HEAP_MARK_AND_SWEEP_TRIGGER_ADD
Definition: duktape.c:9076
#define DUK_STR_NOT_THREAD
Definition: duktape.c:3207
#define DUK_N2S_FLAG_FORCE_EXP
Definition: duktape.c:11235
#define DUK_TVAL_SET_BOOLEAN_UPDREF
Definition: duktape.c:5422
struct duk_hbuffer_external duk_hbuffer_external
Definition: duktape.c:852
#define DUK__DIGITCHAR(x)
Definition: duktape.c:88176
#define DUK_OP_NEQ_RC
Definition: duktape.c:3504
DUK_EXTERNAL void duk_dup_top(duk_hthread *thr)
Definition: duktape.c:19792
DUK_LOCAL_DECL void duk__json_enc_buffer_jx_jc(duk_json_enc_ctx *js_ctx, duk_hbuffer *h)
Definition: duktape.c:38919
#define DUK__FUNC_FLAG_GETSET
Definition: duktape.c:69300
static duk_uint8_t * duk__dump_func(duk_hthread *thr, duk_hcompfunc *func, duk_bufwriter_ctx *bw_ctx, duk_uint8_t *p)
Definition: duktape.c:14643
#define DUK_LFUNC_NARGS_VARARGS
Definition: duktape.c:1537
#define DUK_HPROXY_ASSERT_VALID(h)
Definition: duktape.c:8924
#define DUK_OP_ENDFIN
Definition: duktape.c:3681
DUK_INTERNAL_DECL duk_double_t duk_bi_date_get_now_time(void)
Definition: duktape.c:34592
DUK_INTERNAL_DECL void duk_bw_write_ensure_slice(duk_hthread *thr, duk_bufwriter_ctx *bw, duk_size_t src_off, duk_size_t len)
Definition: duktape.c:100257
#define DUK_HNATFUNC_ASSERT_VALID(h)
Definition: duktape.c:7812
#define DUK_HEAPHDR_GET_REFCOUNT(h)
Definition: duktape.c:4724
#define DUK_TOK_REGEXP
Definition: duktape.c:3972
DUK_INTERNAL_DECL duk_hobject * duk_error_prototype_from_code(duk_hthread *thr, duk_errcode_t err_code)
Definition: duktape.c:49724
#define DUK_ASC_LC_Y
Definition: duktape.c:10879
#define DUK_ASC_LC_P
Definition: duktape.c:10870
#define DUK_BC_OP_MAX
Definition: duktape.c:3459
DUK_LOCAL void duk__initbuffer(duk_lexer_ctx *lex_ctx)
Definition: duktape.c:86220
#define DUK_ASC_SEMICOLON
Definition: duktape.c:10817
#define DUK__ALLOCTEMP(comp_ctx)
Definition: duktape.c:69066
#define DUK_LEXER_INITCTX(ctx)
Definition: duktape.c:3830
#define DUK__BYTECODE_INITIAL_ALLOC
Definition: duktape.c:14434
#define DUK_HOBJECT_IS_THREAD(h)
Definition: duktape.c:6719
#define DUK_TVAL_GET_STRING(tv)
Definition: duktape.c:1473
DUK_INTERNAL_DECL duk_int32_t duk_js_toint32(duk_hthread *thr, duk_tval *tv)
Definition: duktape.c:82805
#define DUK_OP_CLOSURE
Definition: duktape.c:3665
DUK_EXTERNAL void * duk_realloc_raw(duk_hthread *thr, void *ptr, duk_size_t size)
Definition: duktape.c:17576
DUK_EXTERNAL const char * duk_to_lstring(duk_hthread *thr, duk_idx_t idx, duk_size_t *out_len)
Definition: duktape.c:21765
#define DUK_HOBJECT_DECREF_NORZ_ALLOWNULL(thr, h)
Definition: duktape.c:5133
DUK_LOCAL_DECL void duk__parse_stmts(duk_compiler_ctx *comp_ctx, duk_bool_t allow_source_elem, duk_bool_t expect_eof, duk_bool_t regexp_after)
Definition: duktape.c:75890
#define DUK_TOK_ELSE
Definition: duktape.c:3860
DUK_EXTERNAL void duk_require_stack(duk_hthread *thr, duk_idx_t extra)
Definition: duktape.c:19680
DUK_EXTERNAL duk_uint32_t duk_to_uint32(duk_hthread *thr, duk_idx_t idx)
Definition: duktape.c:21694
DUK_INTERNAL_DECL duk_bool_t duk_hobject_getprop(duk_hthread *thr, duk_tval *tv_obj, duk_tval *tv_key)
Definition: duktape.c:60464
#define DUK_OP_SEQ
Definition: duktape.c:3506
#define DUK_S2N_FLAG_ALLOW_AUTO_OCT_INT
Definition: duktape.c:11310
DUK_EXTERNAL duk_hthread * duk_require_context(duk_hthread *thr, duk_idx_t idx)
Definition: duktape.c:21074
DUK_LOCAL duk_bool_t duk__js_instanceof_helper(duk_hthread *thr, duk_tval *tv_x, duk_tval *tv_y, duk_bool_t skip_sym_check)
Definition: duktape.c:83456
#define DUK_OP_BASL_RR
Definition: duktape.c:3588
#define DUK_HEAPHDR_ASSERT_VALID(h)
Definition: duktape.c:4866
#define DUK_DBG_CMD_GETVAR
Definition: duktape.c:9741
DUK_INTERNAL_DECL duk_ret_t duk_bi_global_object_unescape(duk_context *ctx)
Definition: duktape.c:37350
#define DUK_RE_COMPILE_TOKEN_LIMIT
Definition: duktape.c:4482
DUK_INTERNAL_DECL duk_hbuffer * duk_require_hbuffer(duk_hthread *thr, duk_idx_t idx)
Definition: duktape.c:20900
DUK_LOCAL void duk__handle_catch_part2(duk_hthread *thr)
Definition: duktape.c:78087
#define DUK_ALLOC_CHECKED(thr, size)
Definition: duktape.c:9181
#define DUK_STRIDX_NAME
Definition: duktape.c:1858
DUK_LOCAL DUK__RZ_INLINE void duk__hbuffer_refzero_helper(duk_hthread *thr, duk_hbuffer *h)
Definition: duktape.c:54746
static const duk_uint8_t duk__buffer_nbytes_from_fldtype[6]
Definition: duktape.c:27845
#define DUK_DCERROR_RANGE_INVALID_ARGS(thr)
Definition: duktape.c:10314
#define DUK__PM_YEAR
Definition: duktape.c:32798
DUK_INTERNAL_DECL duk_tval * duk_get_tval_or_unused(duk_hthread *thr, duk_idx_t idx)
Definition: duktape.c:19008
#define DUK_ASC_LF
Definition: duktape.c:10768
DUK_INTERNAL_DECL duk_uint_fast32_t duk_hobject_pc2line_query(duk_hthread *thr, duk_idx_t idx_func, duk_uint_fast32_t pc)
Definition: duktape.c:57871
#define DUK_STR_INTERNAL_ERROR
Definition: duktape.c:3182
DUK_LOCAL void duk__emit_load_int32_raw(duk_compiler_ctx *comp_ctx, duk_regconst_t reg, duk_int32_t val, duk_small_uint_t op_flags)
Definition: duktape.c:70664
#define DUK_ASC_UC_D
Definition: duktape.c:10826
#define DUK_TOK_NULL
Definition: duktape.c:3891
#define DUK__SM_SPACE
Definition: duktape.c:32822
#define DUK_STRIDX_UC_NULL
Definition: duktape.c:1582
DUK_INTERNAL_DECL duk_ret_t duk_bi_nodejs_buffer_byte_length(duk_context *ctx)
Definition: duktape.c:29896
#define DUK_RETOK_ATOM_START_CHARCLASS_INVERTED
Definition: duktape.c:4145
duk_double_t duk__sort_key_t
Definition: duktape.c:56937
#define DUK_HOBJECT_CMASK_NUMBER
Definition: duktape.c:6680
#define DUK_OP_GE_RC
Definition: duktape.c:3524
#define DUK_TVAL_SET_NUMBER_CHKFAST_UPDREF
Definition: duktape.c:5424
DUK_LOCAL void duk__handle_createargs_for_call(duk_hthread *thr, duk_hobject *func, duk_hobject *env, duk_idx_t idx_args)
Definition: duktape.c:66487
#define DUK__PM_MONTH
Definition: duktape.c:32799
DUK_EXTERNAL void duk_json_decode(duk_hthread *thr, duk_idx_t idx)
Definition: duktape.c:16612
DUK_EXTERNAL void duk_push_int(duk_hthread *thr, duk_int_t val)
Definition: duktape.c:23046
#define DUK_LEXER_SETPOINT(ctx, pt)
Definition: duktape.c:3832
DUK_EXTERNAL void duk_get_prototype(duk_hthread *thr, duk_idx_t idx)
Definition: duktape.c:18535
#define DUK_STR_UNEXPECTED_END_OF_PATTERN
Definition: duktape.c:3300
DUK_EXTERNAL void * duk_alloc_raw(duk_hthread *thr, duk_size_t size)
Definition: duktape.c:17564
DUK_INTERNAL_DECL void duk_heaphdr_refzero_norz(duk_hthread *thr, duk_heaphdr *h)
Definition: duktape.c:54815
#define DUK_STRIDX_FALSE
Definition: duktape.c:2050
DUK_LOCAL DUK_COLD DUK_NOINLINE void duk__strtable_resize_check(duk_heap *heap)
Definition: duktape.c:55803
#define DUK_OP_BLSR_CC
Definition: duktape.c:3596
DUK_LOCAL_DECL void duk__json_dec_string(duk_json_dec_ctx *js_ctx)
Definition: duktape.c:37741
DUK_LOCAL duk_bool_t duk__put_prop_shared(duk_hthread *thr, duk_idx_t obj_idx, duk_idx_t idx_key)
Definition: duktape.c:17802
#define DUK_TOK_SEMICOLON
Definition: duktape.c:3923
#define DUK_OP_REGEXP_CC
Definition: duktape.c:3664
#define DUK_LJ_TYPE_UNKNOWN
Definition: duktape.c:8994
#define DUK__ITER_EVERY
Definition: duktape.c:27507
DUK_INTERNAL_DECL duk_hbufobj * duk_push_bufobj_raw(duk_hthread *thr, duk_uint_t hobject_flags_and_class, duk_small_int_t prototype_bidx)
Definition: duktape.c:23883
DUK_INTERNAL_DECL duk_ret_t duk_bi_number_prototype_to_precision(duk_context *ctx)
Definition: duktape.c:41278
#define DUK__MAX_FUNCS
Definition: duktape.c:69080
#define DUK_TAG_STRING
Definition: duktape.c:1267
#define DUK_HOBJECT_HAS_EXOTIC_ARGUMENTS(h)
Definition: duktape.c:6766
DUK_LOCAL_DECL duk_int_t duk__parse_arguments(duk_compiler_ctx *comp_ctx, duk_ivalue *res)
Definition: duktape.c:72364
DUK_EXTERNAL void * duk_opt_buffer(duk_hthread *thr, duk_idx_t idx, duk_size_t *out_size, void *def_ptr, duk_size_t def_size)
Definition: duktape.c:20681
DUK_LOCAL void duk__push_stridx(duk_hthread *thr, duk_bitdecoder_ctx *bd)
Definition: duktape.c:64677
#define DUK_OP_BLSR_CR
Definition: duktape.c:3594
#define DUK_BC_BC_MAX
Definition: duktape.c:3467
#define DUK_TOK_CASE
Definition: duktape.c:3853
DUK_INTERNAL_DECL void * duk_heap_mem_alloc_zeroed(duk_heap *heap, duk_size_t size)
Definition: duktape.c:53676
#define DUK_HOBJECT_P_SET_REALLOC_PTRS(p_base, set_e_k, set_e_pv, set_e_f, set_a, set_h, n_ent, n_arr, n_hash)
Definition: duktape.c:6959
#define DUK_HEAPHDR_SET_TYPE(h, val)
Definition: duktape.c:4753
#define DUK_OP_BAND_CC
Definition: duktape.c:3576
#define DUK_DD(x)
Definition: duktape.c:9959
DUK_INTERNAL_DECL void duk_remove_n(duk_hthread *thr, duk_idx_t idx, duk_idx_t count)
Definition: duktape.c:20025
DUK_LOCAL duk_ret_t duk__safe_to_string_raw(duk_hthread *thr, void *udata)
Definition: duktape.c:21773
DUK_LOCAL void duk__bi_copy(duk__bigint *x, duk__bigint *y)
Definition: duktape.c:88284
DUK_EXTERNAL duk_bool_t duk_opt_boolean(duk_hthread *thr, duk_idx_t idx, duk_bool_t def_value)
Definition: duktape.c:20261
#define DUK_OP_CSVAR
Definition: duktape.c:3685
DUK_INTERNAL_DECL duk_ret_t duk_bi_textencoder_prototype_encode(duk_context *ctx)
Definition: duktape.c:35604
DUK_INTERNAL_DECL duk_bool_t duk_hobject_delprop_raw(duk_hthread *thr, duk_hobject *obj, duk_hstring *key, duk_small_uint_t flags)
Definition: duktape.c:62353
DUK_LOCAL void duk__get_this_regexp(duk_hthread *thr)
Definition: duktape.c:42466
DUK_LOCAL duk_ret_t duk__get_part_helper(duk_hthread *thr, duk_small_uint_t flags_and_idx)
Definition: duktape.c:33822
#define DUK_HOBJECT_FLAG_BUFOBJ
Definition: duktape.c:6597
DUK_LOCAL DUK_EXEC_NOINLINE_PERF duk_small_uint_t duk__handle_op_nextenum(duk_hthread *thr, duk_uint_fast32_t ins)
Definition: duktape.c:79804
#define DUK_HEAP_INSERT_INTO_FINALIZE_LIST(heap, hdr)
Definition: duktape.c:9108
#define DUK__HEAPPTR_ENC16(heap, ptr)
Definition: duktape.c:55349
#define DUK_OP_CALL10
Definition: duktape.c:3700
#define DUK_STR_NOT_EXTENSIBLE
Definition: duktape.c:3192
#define DUK_DBLUNION_IS_NEGINF(u)
Definition: duktape.c:562
DUK_LOCAL void duk__sort_enum_keys_es6(duk_hthread *thr, duk_hobject *h_obj, duk_int_fast32_t idx_start, duk_int_fast32_t idx_end)
Definition: duktape.c:56979
DUK_INTERNAL_DECL duk_ret_t duk_bi_number_prototype_to_string(duk_context *ctx)
Definition: duktape.c:41185
DUK_EXTERNAL void duk_get_memory_functions(duk_hthread *thr, duk_memory_functions *out_funcs)
Definition: duktape.c:17610
DUK_INTERNAL_DECL duk_ret_t duk_bi_string_constructor_from_char_code(duk_context *ctx)
Definition: duktape.c:42896
#define DUK_STR_EXPECTED_IDENTIFIER
Definition: duktape.c:3278
DUK_LOCAL duk_hobject * duk__get_hobject_promote_mask_raw(duk_hthread *thr, duk_idx_t idx, duk_uint_t type_mask)
Definition: duktape.c:21160
#define DUK_HOBJECT_HAS_ARRAY_PART(h)
Definition: duktape.c:6757
DUK_EXTERNAL duk_bool_t duk_del_prop_lstring(duk_hthread *thr, duk_idx_t obj_idx, const char *key, duk_size_t key_len)
Definition: duktape.c:17931
#define DUK_ASC_PLUS
Definition: duktape.c:10801
#define DUK_HOBJECT_CLASS_SYMBOL
Definition: duktape.c:6649
#define DUK_HSTRING_DECREF(thr, h)
Definition: duktape.c:5048
#define DUK_HEAPHDR_FLAG_FINALIZED
Definition: duktape.c:4684
#define DUK_HOBJECT_IS_NATFUNC(h)
Definition: duktape.c:6713
#define DUK_REOP_PERIOD
Definition: duktape.c:4490
DUK_EXTERNAL duk_bool_t duk_check_type(duk_hthread *thr, duk_idx_t idx, duk_int_t type)
Definition: duktape.c:22591
DUK_EXTERNAL void * duk_to_buffer_raw(duk_hthread *thr, duk_idx_t idx, duk_size_t *out_size, duk_uint_t mode)
Definition: duktape.c:22209
#define DUK_DBLUNION_DOUBLE_NTOH(u)
Definition: duktape.c:616
#define DUK_PAUSE_FLAG_FUNC_EXIT
Definition: duktape.c:9219
#define DUK_OP_BOR_RR
Definition: duktape.c:3578
#define DUK_BIDX_ARRAY_PROTOTYPE
Definition: duktape.c:2294
#define DUK_ASC_SPACE
Definition: duktape.c:10790
#define DUK_HARRAY_ASSERT_VALID(h)
Definition: duktape.c:8464
DUK_INTERNAL_DECL duk_bool_t duk_double_is_nan(duk_double_t x)
Definition: duktape.c:100618
#define DUK_HSTRING_INCREF(thr, h)
Definition: duktape.c:5047
#define DUK_HOBJECT_FLAG_EXOTIC_STRINGOBJ
Definition: duktape.c:6610
#define DUK__INT_RESTART
Definition: duktape.c:78933
DUK_LOCAL duk_bool_t duk__abandon_array_density_check(duk_uint32_t a_used, duk_uint32_t a_size)
Definition: duktape.c:58222
DUK_LOCAL const duk_uint8_t duk__parse_iso8601_seps[]
Definition: duktape.c:32846
#define DUK_TVAL_SET_TVAL(tv, x)
Definition: duktape.c:1442
#define DUK_HOBJECT_IS_BOUNDFUNC(h)
Definition: duktape.c:6711
#define DUK_OP_EQ_RC
Definition: duktape.c:3499
#define DUK_HEAPHDR_FLAG_REACHABLE
Definition: duktape.c:4681
#define DUK_TOK_BOR_EQ
Definition: duktape.c:3964
#define DUK__SM_COLON
Definition: duktape.c:32823
#define DUK_BC_TRYCATCH_FLAG_HAVE_CATCH
Definition: duktape.c:3777
#define DUK_OP_PREDECP_CC
Definition: duktape.c:3644
DUK_INTERNAL_DECL duk_tval * duk_hobject_find_entry_tval_ptr_stridx(duk_heap *heap, duk_hobject *obj, duk_small_uint_t stridx)
Definition: duktape.c:59352
const duk_uint8_t duk_unicode_idp_m_ids_noa[576]
Definition: duktape.c:93904
#define DUK_BC_JUMP_BIAS
Definition: duktape.c:3798
#define DUK_TVAL_IS_BOOLEAN_TRUE(tv)
Definition: duktape.c:1484
#define DUK_TOK_SNEQ
Definition: duktape.c:3932
DUK_EXTERNAL void duk_pop(duk_hthread *thr)
Definition: duktape.c:24715
#define DUK_STR_COMPILER_RECURSION_LIMIT
Definition: duktape.c:3316
DUK_LOCAL void duk__peephole_optimize_bytecode(duk_compiler_ctx *comp_ctx)
Definition: duktape.c:70870
#define DUK_HTHREAD_STATE_RESUMED
Definition: duktape.c:8154
#define DUK_OP_UNUSED221
Definition: duktape.c:3736
DUK_LOCAL_DECL void duk__json_dec_eat_white(duk_json_dec_ctx *js_ctx)
Definition: duktape.c:37562
#define DUK_REOP_SQGREEDY
Definition: duktape.c:4497
DUK_INTERNAL DUK_COLD void duk_err_error(duk_hthread *thr, const char *filename, duk_int_t linenumber, const char *message)
Definition: duktape.c:12542
#define DUK_TVAL_SET_TVAL_UPDREF
Definition: duktape.c:5445
#define DUK_RAW_READINC_DOUBLE_BE(ptr)
Definition: duktape.c:2458
#define DUK_DCERROR_TYPE_INVALID_ARGS(thr)
Definition: duktape.c:10357
#define DUK__CP_CONTINUE
Definition: duktape.c:35283
#define DUK_BD_BITPACKED_STRING_MAXLEN
Definition: duktape.c:2408
#define DUK_PAUSE_FLAG_ONE_OPCODE
Definition: duktape.c:9215
#define DUK_TOK_ALSHIFT
Definition: duktape.c:3941
#define DUK_BW_SLACK_ADD
Definition: duktape.c:2507
DUK_INTERNAL_DECL duk_double_t duk_to_number_tval(duk_hthread *thr, duk_tval *tv)
Definition: duktape.c:21595
DUK_LOCAL duk_ret_t duk__error_setter_helper(duk_hthread *thr, duk_small_uint_t stridx_key)
Definition: duktape.c:36144
#define DUK_OP_UNUSED227
Definition: duktape.c:3742
DUK_INTERNAL_DECL duk_ret_t duk_bi_object_setprototype_shared(duk_context *ctx)
Definition: duktape.c:41717
DUK_LOCAL void duk__add_enum_key(duk_hthread *thr, duk_hstring *k)
Definition: duktape.c:57058
#define DUK_OP_LDINTX
Definition: duktape.c:3485
DUK_LOCAL void duk__to_regexp_helper(duk_hthread *thr, duk_idx_t idx, duk_bool_t force_new)
Definition: duktape.c:43874
#define DUK_BC_ABC_MIN
Definition: duktape.c:3468
DUK_LOCAL_DECL void duk__json_enc_objarr_exit(duk_json_enc_ctx *js_ctx, duk_idx_t *entry_top)
Definition: duktape.c:39150
DUK_LOCAL DUK_EXEC_NOINLINE_PERF DUK_COLD duk_small_uint_t duk__executor_interrupt(duk_hthread *thr)
Definition: duktape.c:79121
#define DUK_HCOMPFUNC_ASSERT_VALID(h)
Definition: duktape.c:7659
DUK_LOCAL void duk__call_env_setup(duk_hthread *thr, duk_hobject *func, duk_activation *act, duk_idx_t idx_args)
Definition: duktape.c:67901
#define DUK_OP_UNUSED222
Definition: duktape.c:3737
#define DUK_STRIDX_INVALID_DATE
Definition: duktape.c:1777
#define DUK_PUSH_SPRINTF_INITIAL_SIZE
Definition: duktape.c:5921
DUK_LOCAL_DECL duk_uint8_t duk__json_dec_peek(duk_json_dec_ctx *js_ctx)
Definition: duktape.c:37593
#define DUK_OP_CSVAR_CR
Definition: duktape.c:3687
DUK_INTERNAL_DECL double duk_js_arith_pow(double x, double y)
Definition: duktape.c:65991
#define DUK_HTHREAD_STRING_LC_ARGUMENTS(thr)
Definition: duktape.c:1782
#define DUK__PACK_RULE(partmask, sepmask, nextpart, flags)
Definition: duktape.c:32833
DUK_LOCAL void duk__advance_bytes(duk_lexer_ctx *lex_ctx, duk_small_uint_t count_bytes)
Definition: duktape.c:86025
#define DUK_STR_NOT_FUNCTION
Definition: duktape.c:3211
DUK_INTERNAL_DECL duk_ret_t duk_bi_array_prototype_push(duk_context *ctx)
Definition: duktape.c:26645
#define DUK_STR_FMT_INVALID_JSON
Definition: duktape.c:3236
DUK_LOCAL int duk__transform_helper(duk_hthread *thr, duk__transform_callback callback, const void *udata)
Definition: duktape.c:36752
DUK_INTERNAL_DECL duk_ret_t duk_bi_typedarray_set(duk_context *ctx)
Definition: duktape.c:29383
#define DUK_DBG_CMD_APPNOTIFY
Definition: duktape.c:9728
void(* duk_re_range_callback)(void *user, duk_codepoint_t r1, duk_codepoint_t r2, duk_bool_t direct)
Definition: duktape.c:3809
#define DUK_CAT_HAS_CATCH_BINDING_ENABLED(c)
Definition: duktape.c:8100
#define DUK_ASSERT_SET_GARBAGE(ptr, size)
Definition: duktape.c:10606
#define DUK_HEAPHDR_IS_BUFFER(h)
Definition: duktape.c:4841
DUK_LOCAL double duk__fmin_fixed(double x, double y)
Definition: duktape.c:40653
DUK_INTERNAL_DECL duk_hnatfunc * duk_hnatfunc_alloc(duk_hthread *thr, duk_uint_t hobject_flags)
Definition: duktape.c:56592
DUK_LOCAL_DECL void duk__expr_toforcedreg(duk_compiler_ctx *comp_ctx, duk_ivalue *res, duk_small_uint_t rbp_flags, duk_regconst_t forced_reg)
Definition: duktape.c:74034
#define DUK_HTHREAD_INCREF(thr, h)
Definition: duktape.c:5067
#define DUK_RE_FLAG_GLOBAL
Definition: duktape.c:4509
#define DUK__ISREG_NOTTEMP(comp_ctx, x)
Definition: duktape.c:69060
DUK_INTERNAL_DECL duk_hbuffer * duk_known_hbuffer(duk_hthread *thr, duk_idx_t idx)
Definition: duktape.c:21365
DUK_LOCAL_DECL void duk__abandon_array_part(duk_hthread *thr, duk_hobject *obj)
Definition: duktape.c:59111
DUK_LOCAL void duk__cbor_decode_objarr_entry(duk_cbor_decode_context *dec_ctx)
Definition: duktape.c:31436
#define DUK_OP_TYPEOF
Definition: duktape.c:3666
DUK_INTERNAL_DECL void duk_hobject_define_property_internal_arridx(duk_hthread *thr, duk_hobject *obj, duk_uarridx_t arr_idx, duk_small_uint_t flags)
Definition: duktape.c:62862
#define DUK_TOK_DEBUGGER
Definition: duktape.c:3856
#define DUK_DBG_IB_INT4
Definition: duktape.c:9695
#define DUK_S2N_FLAG_ALLOW_AUTO_HEX_INT
Definition: duktape.c:11300
#define DUK_RETOK_ATOM_DIGIT
Definition: duktape.c:4135
DUK_LOCAL duk_bool_t duk__cbor_decode_map(duk_cbor_decode_context *dec_ctx, duk_uint8_t ib, duk_uint8_t ai)
Definition: duktape.c:31941
#define DUK_ACT_FLAG_CONSTRUCT
Definition: duktape.c:8059
#define DUK_TOK_FOR
Definition: duktape.c:3862
DUK_LOCAL_DECL void duk__ivalue_var_fromstack(duk_compiler_ctx *comp_ctx, duk_ivalue *x)
Definition: duktape.c:70996
DUK_EXTERNAL void * duk_require_heapptr(duk_hthread *thr, duk_idx_t idx)
Definition: duktape.c:21141
#define DUK_TOK_DECREMENT
Definition: duktape.c:3940
#define DUK_ASC_UC_W
Definition: duktape.c:10845
#define DUK_BIDX_ERROR_PROTOTYPE
Definition: duktape.c:2306
#define DUK_COMPILER_PEEPHOLE_MAXITER
Definition: duktape.c:4249
#define DUK_OP_SEQ_RC
Definition: duktape.c:3509
#define DUK__PI_TZHOUR
Definition: duktape.c:32794
#define DUK_OP_MPUTOBJI
Definition: duktape.c:3709
#define DUK__IVAL_FLAG_REQUIRE_SHORT
Definition: duktape.c:70946
DUK_LOCAL double duk__floor(double x)
Definition: duktape.c:40814
#define DUK__LONGJMP_RETHROW
Definition: duktape.c:77935
#define DUK_HEAP_SET_DEBUGGER_PAUSED(heap)
Definition: duktape.c:8982
DUK_LOCAL duk_hbufobj * duk__get_bufobj_this(duk_hthread *thr)
Definition: duktape.c:27960
#define DUK_OP_DIV
Definition: duktape.c:3557
#define DUK_STRIDX_DELETE_PROPERTY
Definition: duktape.c:1795
static const duk_uint8_t duk__buffer_proto_from_elemtype[9]
Definition: duktape.c:27838
#define DUK_HOBJECT_CLASS_OBJENV
Definition: duktape.c:6650
DUK_LOCAL_DECL void duk__parse_var_stmt(duk_compiler_ctx *comp_ctx, duk_ivalue *res, duk_small_uint_t expr_flags)
Definition: duktape.c:74214
#define DUK_BIDX_GLOBAL
Definition: duktape.c:2286
DUK_INTERNAL_DECL void duk_lexer_parse_js_input_element(duk_lexer_ctx *lex_ctx, duk_token *out_token, duk_bool_t strict_mode, duk_bool_t regexp_mode)
Definition: duktape.c:86732
#define DUK_BW_INSERT_ENSURE_BYTES(thr, bw, dst_off, buf, len)
Definition: duktape.c:2872
DUK_INTERNAL_DECL duk_ret_t duk_bi_reflect_apply(duk_context *ctx)
Definition: duktape.c:36368
#define DUK_DBG_IB_HEAPPTR
Definition: duktape.c:9709
DUK_INTERNAL_DECL duk_ret_t duk_bi_duktape_object_dec(duk_context *ctx)
Definition: duktape.c:35205
#define DUK_TVAL_IS_STRING(tv)
Definition: duktape.c:1496
DUK_LOCAL duk_tval * duk__obtain_arridx_slot_slowpath(duk_hthread *thr, duk_uint32_t arr_idx, duk_hobject *obj)
Definition: duktape.c:58321
#define DUK_STR_NOT_CONSTRUCTABLE
Definition: duktape.c:3189
DUK_LOCAL_DECL duk_bool_t duk__lookup_lhs(duk_compiler_ctx *ctx, duk_regconst_t *out_reg_varbind, duk_regconst_t *out_rc_varname)
Definition: duktape.c:71691
#define DUK_HBUFOBJ_ELEM_INT32
Definition: duktape.c:7902
#define DUK__CF_ACCEPT
Definition: duktape.c:32830
#define DUK_ASC_LC_K
Definition: duktape.c:10865
#define DUK__FLOAT_ROUND_LIMIT
Definition: duktape.c:100532
DUK_INTERNAL_DECL duk_ret_t duk_bi_array_prototype_reverse(duk_context *ctx)
Definition: duktape.c:27193
#define DUK_PROPDESC_FLAG_NO_OVERWRITE
Definition: duktape.c:6848
DUK_EXTERNAL void duk_call_method(duk_hthread *thr, duk_idx_t nargs)
Definition: duktape.c:15335
#define DUK_HCOMPFUNC_GET_FUNCS_END(heap, h)
Definition: duktape.c:7623
#define DUK_STRIDX_DATA
Definition: duktape.c:1834
#define DUK_LFUNC_FLAGS_PACK(magic, length, nargs)
Definition: duktape.c:1535
#define DUK_ASC_LANGLE
Definition: duktape.c:10818
#define DUK_HOBJECT_DECREF(thr, h)
Definition: duktape.c:5052
DUK_INTERNAL_DECL void duk_bw_insert_ensure_bytes(duk_hthread *thr, duk_bufwriter_ctx *bw, duk_size_t dst_off, const duk_uint8_t *buf, duk_size_t len)
Definition: duktape.c:100292
#define duk_memset_unsafe(dst, val, len)
Definition: duktape.c:3080
#define DUK__FLD_32BIT
Definition: duktape.c:30045
DUK_INTERNAL_DECL duk_int_t duk_handle_safe_call(duk_hthread *thr, duk_safe_call_function func, void *udata, duk_idx_t num_stack_args, duk_idx_t num_stack_res)
Definition: duktape.c:68698
#define DUK_OP_DECLVAR
Definition: duktape.c:3655
DUK_INTERNAL_DECL duk_bool_t duk_js_equals_helper(duk_hthread *thr, duk_tval *tv_x, duk_tval *tv_y, duk_small_uint_t flags)
Definition: duktape.c:82974
#define DUK_ALLOC_RAW(heap, size)
Definition: duktape.c:9131
DUK_EXTERNAL const char * duk_get_lstring_default(duk_hthread *thr, duk_idx_t idx, duk_size_t *out_len, const char *def_ptr, duk_size_t def_len)
Definition: duktape.c:20481
DUK_LOCAL duk_codepoint_t duk__slow_case_conversion(duk_hthread *thr, duk_bufwriter_ctx *bw, duk_codepoint_t cp, duk_bitdecoder_ctx *bd_ctx)
Definition: duktape.c:13524
#define DUK_OP_INSTOF_RR
Definition: duktape.c:3603
DUK_INTERNAL_DECL duk_ret_t duk_bi_error_prototype_stack_setter(duk_context *ctx)
Definition: duktape.c:36170
#define DUK__IDX_BCBYTES
Definition: duktape.c:17338
DUK_LOCAL_DECL void duk__expr_toplain_ignore(duk_compiler_ctx *comp_ctx, duk_ivalue *res, duk_small_uint_t rbp_flags)
Definition: duktape.c:74060
#define DUK_PAUSE_FLAG_UNCAUGHT_ERROR
Definition: duktape.c:9221
#define DUK_DCERROR_RANGE_INVALID_LENGTH(thr)
Definition: duktape.c:10332
#define DUK_ASC_LC_D
Definition: duktape.c:10858
#define DUK_HOBJECT_CLASS_ERROR
Definition: duktape.c:6642
DUK_INTERNAL_DECL duk_bool_t duk_bi_date_timeval_in_valid_range(duk_double_t x)
Definition: duktape.c:33159
#define DUK_DOUBLE_2TO31
Definition: duktape.c:2374
#define DUK_STR_INVALID_FOR
Definition: duktape.c:3280
DUK_LOCAL void duk__regexp_generate_ranges(void *userdata, duk_codepoint_t r1, duk_codepoint_t r2, duk_bool_t direct)
Definition: duktape.c:90871
#define DUK_LEXER_TEMP_BUF_LIMIT
Definition: duktape.c:4149
DUK_INTERNAL_DECL duk_hnatfunc * duk_get_hnatfunc(duk_hthread *thr, duk_idx_t idx)
Definition: duktape.c:20963
#define DUK_STR_PARSE_ERROR
Definition: duktape.c:3268
DUK_INTERNAL_DECL duk_ret_t duk_bi_global_object_parse_int(duk_context *ctx)
Definition: duktape.c:37240
#define DUK_GET_TVAL_POSIDX(thr, idx)
Definition: duktape.c:6270
DUK_EXTERNAL void duk_push_context_dump(duk_hthread *thr)
Definition: duktape.c:16824
#define DUK_HSTRING_DECREF_NORZ(thr, h)
Definition: duktape.c:5049
DUK_LOCAL duk_ret_t duk__to_string_helper(duk_hthread *thr, duk_small_uint_t flags)
Definition: duktape.c:33766
DUK_INTERNAL DUK_COLD void duk_err_range_push_beyond(duk_hthread *thr, const char *filename, duk_int_t linenumber)
Definition: duktape.c:12551
DUK_INTERNAL_DECL duk_double_t duk_util_tinyrandom_get_double(duk_hthread *thr)
Definition: duktape.c:101070
#define DUK_CAT_FLAG_CATCH_ENABLED
Definition: duktape.c:8086
#define DUK_HSTRING_SET_SYMBOL(x)
Definition: duktape.c:6350
#define DUK_TOK_FALSE
Definition: duktape.c:3893
DUK_EXTERNAL duk_int_t duk_to_int(duk_hthread *thr, duk_idx_t idx)
Definition: duktape.c:21660
#define DUK_STR_INVALID_ARRAY_LITERAL
Definition: duktape.c:3271
DUK_LOCAL_DECL duk_small_uint_t duk__expr_lbp(duk_compiler_ctx *comp_ctx)
Definition: duktape.c:73888
DUK_INTERNAL_DECL duk_tval * duk_hobject_find_entry_tval_ptr_and_attrs(duk_heap *heap, duk_hobject *obj, duk_hstring *key, duk_uint_t *out_attrs)
Definition: duktape.c:59357
DUK_LOCAL duk_codepoint_t duk__utf8_decode_next(duk__decode_context *dec_ctx, duk_uint8_t x)
Definition: duktape.c:35310
#define DUK_BIDX_REFERENCE_ERROR_PROTOTYPE
Definition: duktape.c:2312
#define DUK_STRIDX_JOIN
Definition: duktape.c:1693
DUK_INTERNAL_DECL void duk_push_hobject_bidx(duk_hthread *thr, duk_small_int_t builtin_idx)
Definition: duktape.c:24581
DUK_INTERNAL_DECL duk_hstring * duk_require_hstring_notsymbol(duk_hthread *thr, duk_idx_t idx)
Definition: duktape.c:20864
DUK_INTERNAL_DECL duk_ret_t duk_bi_global_object_parse_float(duk_context *ctx)
Definition: duktape.c:37284
#define DUK_DBLUNION_GET_HIGH32(u)
Definition: duktape.c:392
DUK_INTERNAL_DECL int duk_repl_signbit(double x)
Definition: duktape.c:11470
#define DUK_STR_TOKEN_LIMIT
Definition: duktape.c:3262
#define DUK_BIDX_URI_ERROR_PROTOTYPE
Definition: duktape.c:2318
#define DUK_PROPDESC_FLAGS_MASK
Definition: duktape.c:6842
DUK_INTERNAL_DECL duk_bool_t duk_js_isarray(duk_tval *tv)
Definition: duktape.c:83798
DUK_INTERNAL_DECL duk_hcompfunc * duk_push_hcompfunc(duk_hthread *thr)
Definition: duktape.c:23697
DUK_LOCAL void duk__transform_callback_decode_uri(duk__transform_context *tfm_ctx, const void *udata, duk_codepoint_t cp)
Definition: duktape.c:36846
#define DUK_HOBJECT_CLASS_FLOAT32ARRAY
Definition: duktape.c:6664
DUK_LOCAL_DECL void duk__json_enc_object(duk_json_enc_ctx *js_ctx)
Definition: duktape.c:39183
DUK_LOCAL duk_size_t duk__cbor_get_reserve(duk_cbor_encode_context *enc_ctx)
Definition: duktape.c:30889
#define DUK_HOBJECT_FLAG_FASTREFS
Definition: duktape.c:6598
#define DUK_STR_INVALID_BYTECODE
Definition: duktape.c:3227
#define DUK_HOBJECT_E_SLOT_CLEAR_WRITABLE(heap, h, i)
Definition: duktape.c:7077
#define DUK_ASC_UC_O
Definition: duktape.c:10837
DUK_INTERNAL_DECL duk_hobject * duk_hobject_resolve_proxy_target(duk_hobject *obj)
Definition: duktape.c:58408
#define DUK_DBG_IB_BUF2
Definition: duktape.c:9699
#define DUK_HOBJECT_GET_HSIZE(h)
Definition: duktape.c:7144
#define DUK_S2N_FLAG_ALLOW_AUTO_BIN_INT
Definition: duktape.c:11315
#define DUK_RETOK_ATOM_END_GROUP
Definition: duktape.c:4146
#define DUK_BIDX_TYPE_ERROR_THROWER
Definition: duktape.c:2319
DUK_LOCAL void duk__bi_mul_copy(duk__bigint *x, duk__bigint *y, duk__bigint *t)
Definition: duktape.c:88698
#define DUK_HOBJECT_CMASK_ALL_BUFOBJS
Definition: duktape.c:6701
#define DUK_OP_NEWOBJ
Definition: duktape.c:3706
#define DUK__TOKEN_LBP_GET_BP(x)
Definition: duktape.c:69347
DUK_EXTERNAL void duk_pull(duk_hthread *thr, duk_idx_t from_idx)
Definition: duktape.c:19900
DUK_LOCAL void duk__cbor_decode_req_stack(duk_cbor_decode_context *dec_ctx)
Definition: duktape.c:31432
DUK_INTERNAL_DECL void duk_raw_writeinc_double_be(duk_uint8_t **p, duk_double_t val)
Definition: duktape.c:14002
DUK_LOCAL void duk__bi_mul_small_copy(duk__bigint *x, duk_uint32_t y, duk__bigint *t)
Definition: duktape.c:88704
#define DUK_REOP_SPLIT2
Definition: duktape.c:4495
#define DUK_TVAL_ASSERT_VALID(tv)
Definition: duktape.c:1562
#define DUK_GET_TVAL_NEGIDX(thr, idx)
Definition: duktape.c:6269
DUK_LOCAL_DECL duk_regconst_t duk__ispec_toregconst_raw(duk_compiler_ctx *comp_ctx, duk_ispec *x, duk_regconst_t forced_reg, duk_small_uint_t flags)
Definition: duktape.c:71135
DUK_INTERNAL_DECL duk_ret_t duk_bi_object_constructor_define_properties(duk_context *ctx)
Definition: duktape.c:41488
DUK_EXTERNAL void duk_push_global_stash(duk_hthread *thr)
Definition: duktape.c:23387
DUK_INTERNAL_DECL void duk_heap_process_finalize_list(duk_heap *heap)
Definition: duktape.c:51611
DUK_INTERNAL_DECL duk_ret_t duk_bi_string_prototype_concat(duk_context *ctx)
Definition: duktape.c:44011
#define DUK_UNICODE_CP_ZWJ
Definition: duktape.c:10743
DUK_INTERNAL_DECL duk_ret_t duk_bi_arraybuffer_constructor(duk_context *ctx)
Definition: duktape.c:28421
#define DUK_OP_PREINCP_CR
Definition: duktape.c:3637
#define DUK_HEAP_CLEAR_INTERRUPT_RUNNING(heap)
Definition: duktape.c:8986
DUK_EXTERNAL duk_bool_t duk_is_bound_function(duk_hthread *thr, duk_idx_t idx)
Definition: duktape.c:22861
#define DUK_TOK_LPAREN
Definition: duktape.c:3920
DUK_INTERNAL_DECL void duk_pack(duk_hthread *thr, duk_idx_t count)
Definition: duktape.c:24854
#define DUK_OP_ADD_RR
Definition: duktape.c:3543
#define DUK_DCERROR_RANGE_INVALID_COUNT(thr)
Definition: duktape.c:10323
DUK_EXTERNAL duk_bool_t duk_is_string(duk_hthread *thr, duk_idx_t idx)
Definition: duktape.c:22713
#define DUK_BC_INCDECP_FLAG_POST
Definition: duktape.c:3477
DUK_EXTERNAL duk_bool_t duk_is_object(duk_hthread *thr, duk_idx_t idx)
Definition: duktape.c:22723
DUK_LOCAL void duk__append_slice(duk_re_compiler_ctx *re_ctx, duk_uint32_t data_offset, duk_uint32_t data_length)
Definition: duktape.c:90642
DUK_EXTERNAL duk_bool_t duk_is_valid_index(duk_hthread *thr, duk_idx_t idx)
Definition: duktape.c:19050
DUK_EXTERNAL void duk_to_undefined(duk_hthread *thr, duk_idx_t idx)
Definition: duktape.c:21418
DUK_INTERNAL_DECL void duk_push_hstring_stridx(duk_hthread *thr, duk_small_uint_t stridx)
Definition: duktape.c:24550
#define DUK_CAT_GET_LABEL(c)
Definition: duktape.c:8096
DUK_LOCAL void duk__appendbuffer(duk_lexer_ctx *lex_ctx, duk_codepoint_t x)
Definition: duktape.c:86237
#define DUK_STRIDX_JSON_EXT_FUNCTION2
Definition: duktape.c:1942
DUK_INTERNAL_DECL const char * duk_require_lstring_notsymbol(duk_hthread *thr, duk_idx_t idx, duk_size_t *out_len)
Definition: duktape.c:20430
#define DUK_TVAL_SET_POINTER(tv, hptr)
Definition: duktape.c:1392
#define DUK_OP_EXP_RR
Definition: duktape.c:3568
#define DUK_TOK_SWITCH
Definition: duktape.c:3869
DUK_LOCAL const duk_uint_t duk__type_from_tag[]
Definition: duktape.c:18722
DUK_LOCAL void duk__mark_roots_heap(duk_heap *heap)
Definition: duktape.c:52325
#define DUK_REOP_LOOKPOS
Definition: duktape.c:4500
#define DUK__BP_LOR
Definition: duktape.c:69327
DUK_EXTERNAL duk_bool_t duk_is_boolean(duk_hthread *thr, duk_idx_t idx)
Definition: duktape.c:22670
#define DUK_HEAPHDR_HAS_READONLY(h)
Definition: duktape.c:4800
DUK_INTERNAL_DECL duk_double_t duk_double_trunc_towards_zero(duk_double_t x)
Definition: duktape.c:100701
DUK_LOCAL void duk__call_setup_act_not_tailcall(duk_hthread *thr, duk_small_uint_t call_flags, duk_idx_t idx_func, duk_hobject *func, duk_size_t entry_valstack_bottom_byteoff, duk_size_t entry_valstack_end_byteoff, duk_idx_t *out_nargs, duk_idx_t *out_nregs, duk_size_t *out_vs_min_bytes, duk_activation **out_act)
Definition: duktape.c:67745
DUK_INTERNAL_DECL duk_ret_t duk_bi_nodejs_buffer_copy(duk_context *ctx)
Definition: duktape.c:29241
DUK_INTERNAL_DECL duk_hobject * duk_push_object_helper(duk_hthread *thr, duk_uint_t hobject_flags_and_class, duk_small_int_t prototype_bidx)
Definition: duktape.c:23501
static const duk_uint8_t * duk__load_func(duk_hthread *thr, const duk_uint8_t *p, const duk_uint8_t *p_end)
Definition: duktape.c:14799
#define DUK_BW_WRITE_RAW_U8(thr, bw_ctx, val)
Definition: duktape.c:2615
struct duk_hbufobj duk_hbufobj
Definition: duktape.c:845
#define DUK_OP_BXOR_CR
Definition: duktape.c:3584
#define DUK_ASSERT_VALSTACK_SPACE(thr, n)
Definition: duktape.c:10628
#define DUK_TVAL_IS_LIGHTFUNC(tv)
Definition: duktape.c:1495
#define DUK_HOBJECT_HAS_CALLABLE(h)
Definition: duktape.c:6747
#define DUK__IDX_ASIZE
Definition: duktape.c:17336
#define DUK_OP_CALL15
Definition: duktape.c:3705
#define DUK_ERROR_UNSUPPORTED(thr)
Definition: duktape.c:10289
#define DUK_HSTRING_GET_BYTELEN(x)
Definition: duktape.c:6410
#define DUK_RETOK_ATOM_NOT_WHITE
Definition: duktape.c:4138
DUK_INTERNAL_DECL duk_bool_t duk_hthread_init_stacks(duk_heap *heap, duk_hthread *thr)
Definition: duktape.c:64478
#define DUK_OP_UNUSED255
Definition: duktape.c:3770
#define DUK_OP_CALL13
Definition: duktape.c:3703
DUK_LOCAL_DECL void duk__json_dec_syntax_error(duk_json_dec_ctx *js_ctx)
Definition: duktape.c:37553
#define DUK__IN_BODY(barg, carg)
#define DUK_ASC_SINGLEQUOTE
Definition: duktape.c:10797
#define DUK_ENC_OP_A_BC(op, a, bc)
Definition: duktape.c:3443
#define DUK_BW_GET_SIZE(thr, bw_ctx)
Definition: duktape.c:2563
#define DUK_OP_NEQ_CC
Definition: duktape.c:3505
#define DUK_DBG_IB_LIGHTFUNC
Definition: duktape.c:9708
#define DUK__FUNC_FLAG_DECL
Definition: duktape.c:69299
DUK_INTERNAL_DECL duk_ret_t duk_bi_math_object_max(duk_context *ctx)
Definition: duktape.c:40918
#define DUK_DBG_CMD_STEPOUT
Definition: duktape.c:9737
DUK_INTERNAL_DECL duk_small_uint_t duk_get_class_number(duk_hthread *thr, duk_idx_t idx)
Definition: duktape.c:22565
#define DUK_HEAPHDR_GET_FLAGS(h)
Definition: duktape.c:4747
#define DUK_HOBJECT_CLASS_UINT8ARRAY
Definition: duktape.c:6658
DUK_INTERNAL_DECL duk_bool_t duk_hobject_object_is_sealed_frozen_helper(duk_hthread *thr, duk_hobject *obj, duk_bool_t is_frozen)
Definition: duktape.c:64195
DUK_LOCAL_DECL void duk__emit_op_only(duk_compiler_ctx *comp_ctx, duk_small_uint_t op)
Definition: duktape.c:70260
#define DUK_BIDX_NUMBER_PROTOTYPE
Definition: duktape.c:2300
#define DUK__BITPACK_EIGHTBIT
Definition: duktape.c:100041
#define DUK_TOK_MOD
Definition: duktape.c:3937
DUK_LOCAL const duk_uint16_t duk__closure_copy_proplist[]
Definition: duktape.c:84024
#define DUK_HCOMPFUNC_DECREF_NORZ(thr, h)
Definition: duktape.c:5060
#define DUK__NUM_ISO8601_PARSER_PARTS
Definition: duktape.c:32784
#define DUK_STRIDX_LC_NULL
Definition: duktape.c:2044
#define DUK_STRIDX_EMPTY_STRING
Definition: duktape.c:1624
#define DUK__FLD_VARINT
Definition: duktape.c:30048
#define DUK_DBG_CMD_GETLOCALS
Definition: duktape.c:9744
#define DUK_OP_UNUSED207
Definition: duktape.c:3721
DUK_INTERNAL_DECL duk_hcompfunc * duk_hcompfunc_alloc(duk_hthread *thr, duk_uint_t hobject_flags)
Definition: duktape.c:56573
#define DUK_BIDX_SYNTAX_ERROR_PROTOTYPE
Definition: duktape.c:2314
DUK_EXTERNAL void duk_remove(duk_hthread *thr, duk_idx_t idx)
Definition: duktape.c:19974
#define DUK_PAUSE_FLAG_LINE_CHANGE
Definition: duktape.c:9217
DUK_LOCAL const duk__one_arg_func duk__one_arg_funcs[]
Definition: duktape.c:40863
#define DUK_HTHREAD_STATE_RUNNING
Definition: duktape.c:8153
#define DUK_OP_POSTDECR
Definition: duktape.c:3630
#define DUK_BIDX_UINT32ARRAY_PROTOTYPE
Definition: duktape.c:2333
#define DUK_ASC_UC_I
Definition: duktape.c:10831
#define DUK_HOBJECT_CLASS_GLOBAL
Definition: duktape.c:6648
#define DUK_REOP_LOOKNEG
Definition: duktape.c:4501
DUK_LOCAL const duk_uint8_t duk__bitpacked_lookup[16]
Definition: duktape.c:100043
DUK_INTERNAL_DECL duk_hobject * duk_get_hobject_promote_mask(duk_hthread *thr, duk_idx_t idx, duk_uint_t type_mask)
Definition: duktape.c:21197
DUK_EXTERNAL duk_bool_t duk_put_prop_string(duk_hthread *thr, duk_idx_t obj_idx, const char *key)
Definition: duktape.c:17836
#define DUK_STRIDX_INT_VARMAP
Definition: duktape.c:1879
#define DUK_STRIDX_UC_OBJECT
Definition: duktape.c:1591
#define DUK_OP_CALL9
Definition: duktape.c:3699
DUK_INTERNAL_DECL void duk_raw_writeinc_float_be(duk_uint8_t **p, duk_float_t val)
Definition: duktape.c:13997
DUK_LOCAL_DECL void duk__parse_stmt(duk_compiler_ctx *comp_ctx, duk_ivalue *res, duk_bool_t allow_source_elem)
Definition: duktape.c:75378
DUK_LOCAL duk_codepoint_t duk__case_transform_helper(duk_hthread *thr, duk_bufwriter_ctx *bw, duk_codepoint_t cp, duk_codepoint_t prev, duk_codepoint_t next, duk_bool_t uppercase)
Definition: duktape.c:13630
DUK_LOCAL_DECL void duk__emit_jump(duk_compiler_ctx *comp_ctx, duk_int_t target_pc)
Definition: duktape.c:70712
#define DUK_DBG_IB_STR4
Definition: duktape.c:9696
#define DUK_STRIDX_LENGTH
Definition: duktape.c:1840
#define DUK__BP_CONDITIONAL
Definition: duktape.c:69326
#define DUK__BITPACK_SWITCH
Definition: duktape.c:100039
#define DUK_RETOK_ASSERT_WORD_BOUNDARY
Definition: duktape.c:4129
DUK_LOCAL duk_codepoint_t duk__lexer_parse_legacy_octal(duk_lexer_ctx *lex_ctx, duk_small_uint_t *out_adv, duk_bool_t reject_annex_b)
Definition: duktape.c:86453
DUK_INTERNAL_DECL duk_int_t duk_to_int_clamped(duk_hthread *thr, duk_idx_t idx, duk_int_t minval, duk_int_t maxval)
Definition: duktape.c:22046
DUK_EXTERNAL void duk_set_prototype(duk_hthread *thr, duk_idx_t idx)
Definition: duktape.c:18553
DUK_EXTERNAL duk_uint_t duk_get_uint_default(duk_hthread *thr, duk_idx_t idx, duk_uint_t def_value)
Definition: duktape.c:20359
#define DUK_STRIDX_WELLKNOWN_SYMBOL_TO_STRING_TAG
Definition: duktape.c:1813
#define DUK_HEAP_SET_MARKANDSWEEP_RECLIMIT_REACHED(heap)
Definition: duktape.c:8979
#define DUK_HOBJECT_HAS_HAVE_FINALIZER(h)
Definition: duktape.c:6763
#define DUK__BP_ADDITIVE
Definition: duktape.c:69335
DUK_LOCAL_DECL void duk__patch_trycatch(duk_compiler_ctx *comp_ctx, duk_int_t ldconst_pc, duk_int_t trycatch_pc, duk_regconst_t reg_catch, duk_regconst_t const_varname, duk_small_uint_t flags)
Definition: duktape.c:70798
DUK_LOCAL duk_bool_t duk__getvar_helper(duk_hthread *thr, duk_hobject *env, duk_activation *act, duk_hstring *name, duk_bool_t throw_flag)
Definition: duktape.c:85100
DUK_INTERNAL_DECL void duk_raw_write_u32_be(duk_uint8_t *p, duk_uint32_t val)
Definition: duktape.c:13957
#define DUK_HNATFUNC_NARGS_MAX
Definition: duktape.c:7818
#define DUK_OP_PREINCR
Definition: duktape.c:3627
DUK_EXTERNAL void * duk_require_buffer(duk_hthread *thr, duk_idx_t idx, duk_size_t *out_size)
Definition: duktape.c:20703
#define DUK_PC2LINE_SKIP
Definition: duktape.c:7253
DUK_INTERNAL_DECL void duk_set_top_and_wipe(duk_hthread *thr, duk_idx_t top, duk_idx_t idx_wipe_start)
Definition: duktape.c:19269
#define DUK_JSON_FLAG_EXT_CUSTOM
Definition: duktape.c:11028
#define DUK_OP_BAND
Definition: duktape.c:3572
DUK_INTERNAL_DECL duk_small_int_t duk_unicode_get_xutf8_length(duk_ucodepoint_t cp)
Definition: duktape.c:12675
#define DUK_BIDX_REGEXP_CONSTRUCTOR
Definition: duktape.c:2303
DUK_EXTERNAL void duk_time_to_components(duk_hthread *thr, duk_double_t timeval, duk_time_components *comp)
Definition: duktape.c:26020
DUK_INTERNAL_DECL void duk_heap_free_freelists(duk_heap *heap)
Definition: duktape.c:50432
DUK_LOCAL const duk_uint8_t * duk__load_buffer_raw(duk_hthread *thr, const duk_uint8_t *p)
Definition: duktape.c:14450
#define DUK_HBUFOBJ_ASSERT_VALID(h)
Definition: duktape.c:7914
DUK_INTERNAL_DECL duk_bool_t duk_hobject_object_ownprop_helper(duk_hthread *thr, duk_small_uint_t required_desc_flags)
Definition: duktape.c:64099
#define DUK_OP_NEQ_CR
Definition: duktape.c:3503
#define DUK_DBG_IB_ERROR
Definition: duktape.c:9691
DUK_EXTERNAL duk_int_t duk_opt_int(duk_hthread *thr, duk_idx_t idx, duk_int_t def_value)
Definition: duktape.c:20377
DUK_INTERNAL const duk_int8_t duk_hex_dectab[256]
Definition: duktape.c:14044
DUK_EXTERNAL void duk_trim(duk_hthread *thr, duk_idx_t idx)
Definition: duktape.c:25873
DUK_LOCAL duk_uint8_t duk__cbor_decode_readbyte(duk_cbor_decode_context *dec_ctx)
Definition: duktape.c:31457
#define DUK_OP_MPUTARRI
Definition: duktape.c:3713
DUK_INTERNAL_DECL duk_bool_t duk_js_isarray_hobject(duk_hobject *h)
Definition: duktape.c:83790
#define DUK_OP_GT_CC
Definition: duktape.c:3520
DUK_EXTERNAL void duk_require_function(duk_hthread *thr, duk_idx_t idx)
Definition: duktape.c:21047
#define DUK_STR_PROTOTYPE_CHAIN_LIMIT
Definition: duktape.c:3313
#define DUK_OP_DIV_RC
Definition: duktape.c:3560
DUK_LOCAL_DECL void duk__patch_jump_here(duk_compiler_ctx *comp_ctx, duk_int_t jump_pc)
Definition: duktape.c:70794
DUK_LOCAL const duk_uint8_t * duk__prep_codec_arg(duk_hthread *thr, duk_idx_t idx, duk_size_t *out_len)
Definition: duktape.c:15731
#define DUK__VALSTACK_PROXY_LOOKUP
Definition: duktape.c:57957
DUK_INTERNAL_DECL duk_bool_t duk_double_is_posinf(duk_double_t x)
Definition: duktape.c:100606
#define DUK_DBG_CMD_LISTBREAK
Definition: duktape.c:9738
DUK_LOCAL_DECL duk_bool_t duk__json_enc_value(duk_json_enc_ctx *js_ctx, duk_idx_t idx_holder)
Definition: duktape.c:39346
#define DUK_HTHREAD_STRING_SET(thr)
Definition: duktape.c:1845
DUK_LOCAL double duk__exp(double x)
Definition: duktape.c:40811
DUK_LOCAL_DECL void duk__advance_helper(duk_compiler_ctx *comp_ctx, duk_small_int_t expect)
Definition: duktape.c:69496
#define DUK_DBG_CMD_STEPOVER
Definition: duktape.c:9736
#define DUK_STRIDX_INT_VALUE
Definition: duktape.c:1897
#define DUK_BIDX_FLOAT64ARRAY_PROTOTYPE
Definition: duktape.c:2335
DUK_EXTERNAL duk_int_t duk_get_int_default(duk_hthread *thr, duk_idx_t idx, duk_int_t def_value)
Definition: duktape.c:20353
#define DUK_REALLOC_RAW(heap, ptr, newsize)
Definition: duktape.c:9133
#define DUK_ENC_OP_A(op, a)
Definition: duktape.c:3449
DUK_EXTERNAL duk_hthread * duk_create_heap(duk_alloc_function alloc_func, duk_realloc_function realloc_func, duk_free_function free_func, void *heap_udata, duk_fatal_function fatal_handler)
Definition: duktape.c:17094
DUK_INTERNAL_DECL duk_ret_t duk_bi_symbol_toprimitive(duk_context *ctx)
Definition: duktape.c:44457
#define DUK_TVAL_UNUSED_INITIALIZER()
Definition: duktape.c:1253
#define DUK_ASC_LC_H
Definition: duktape.c:10862
#define DUK_BW_INIT_WITHBUF(thr, bw_ctx, buf)
Definition: duktape.c:2517
#define DUK_HSTRING_FLAG_EXTDATA
Definition: duktape.c:6335
DUK_INTERNAL_DECL duk_ret_t duk_hobject_get_enumerated_keys(duk_hthread *thr, duk_small_uint_t enum_flags)
Definition: duktape.c:57539
DUK_INTERNAL_DECL duk_int_t duk_double_to_int_t(duk_double_t x)
Definition: duktape.c:100492
DUK_INTERNAL_DECL duk_bool_t duk_hobject_delprop(duk_hthread *thr, duk_tval *tv_obj, duk_tval *tv_key, duk_bool_t throw_flag)
Definition: duktape.c:62522
#define DUK_STRIDX_NAN
Definition: duktape.c:1756
DUK_EXTERNAL duk_bool_t duk_is_symbol(duk_hthread *thr, duk_idx_t idx)
Definition: duktape.c:22771
DUK_LOCAL_DECL void duk__ivalue_toplain_ignore(duk_compiler_ctx *comp_ctx, duk_ivalue *x)
Definition: duktape.c:71523
#define DUK_GET_HOBJECT_NEGIDX(thr, idx)
Definition: duktape.c:6271
#define DUK_TVAL_IS_FASTINT(tv)
Definition: duktape.c:1488
DUK_INTERNAL_DECL void duk_bw_remove_raw_slice(duk_hthread *thr, duk_bufwriter_ctx *bw, duk_size_t off, duk_size_t len)
Definition: duktape.c:100389
DUK_INTERNAL_DECL duk_ret_t duk_bi_date_prototype_get_timezone_offset(duk_context *ctx)
Definition: duktape.c:34371
DUK_LOCAL duk_uint32_t duk__insert_i32(duk_re_compiler_ctx *re_ctx, duk_uint32_t offset, duk_int32_t x)
Definition: duktape.c:90612
#define DUK_OP_ADD
Definition: duktape.c:3542
DUK_INTERNAL_DECL void duk_clear_prototype(duk_hthread *thr, duk_idx_t idx)
Definition: duktape.c:18577
#define DUK_RETOK_ATOM_NOT_WORD_CHAR
Definition: duktape.c:4140
#define DUK_STR_BYTECODE_LIMIT
Definition: duktape.c:3317
#define DUK_PROPDESC_FLAG_CONFIGURABLE
Definition: duktape.c:6838
#define DUK_OP_UNUSED215
Definition: duktape.c:3730
#define DUK_OP_SUB_RR
Definition: duktape.c:3548
#define DUK_DBG_CMD_STEPINTO
Definition: duktape.c:9735
DUK_INTERNAL_DECL duk_hthread * duk_hthread_alloc(duk_hthread *thr, duk_uint_t hobject_flags)
Definition: duktape.c:56688
#define DUK_HTHREAD_STRING_JX(thr)
Definition: duktape.c:1923
DUK_INTERNAL_DECL duk_hstring * duk_require_hstring(duk_hthread *thr, duk_idx_t idx)
Definition: duktape.c:20851
DUK_INTERNAL_DECL duk_hstring * duk_heap_strtable_intern_u32(duk_heap *heap, duk_uint32_t val)
Definition: duktape.c:56114
#define DUK__BP_FOR_EXPR
Definition: duktape.c:69323
DUK_INTERNAL DUK_COLD void duk_err_error_alloc_failed(duk_hthread *thr, const char *filename, duk_int_t linenumber)
Definition: duktape.c:12539
#define DUK_HOBJECT_H_GET_INDEX(heap, h, i)
Definition: duktape.c:7017
DUK_EXTERNAL duk_bool_t duk_del_prop_string(duk_hthread *thr, duk_idx_t obj_idx, const char *key)
Definition: duktape.c:17922
DUK_LOCAL_DECL duk_uint8_t * duk__emit_esc_auto_fast(duk_json_enc_ctx *js_ctx, duk_uint_fast32_t cp, duk_uint8_t *q)
Definition: duktape.c:38460
#define DUK_TOK_QUESTION
Definition: duktape.c:3951
DUK_INTERNAL_DECL void duk_remove_m2(duk_hthread *thr)
Definition: duktape.c:20019
DUK_INTERNAL_DECL duk_bool_t duk_hobject_hasprop_raw(duk_hthread *thr, duk_hobject *obj, duk_hstring *key)
Definition: duktape.c:61102
#define DUK__CP_RETRY
Definition: duktape.c:35285
DUK_LOCAL_DECL duk_regconst_t duk__ivalue_totempconst(duk_compiler_ctx *comp_ctx, duk_ivalue *x)
Definition: duktape.c:71595
DUK_INTERNAL_DECL duk_hdecenv * duk_hdecenv_alloc(duk_hthread *thr, duk_uint_t hobject_flags)
Definition: duktape.c:56709
DUK_EXTERNAL duk_bool_t duk_is_strict_call(duk_hthread *thr)
Definition: duktape.c:15586
DUK_INTERNAL_DECL duk_hboundfunc * duk_push_hboundfunc(duk_hthread *thr)
Definition: duktape.c:23732
DUK_LOCAL_DECL void duk__emit_if_false_skip(duk_compiler_ctx *comp_ctx, duk_regconst_t regconst)
Definition: duktape.c:70845
DUK_INTERNAL_DECL duk_ret_t duk_bi_buffer_compare_shared(duk_context *ctx)
Definition: duktape.c:29068
DUK_EXTERNAL duk_int_t duk_pcall(duk_hthread *thr, duk_idx_t nargs)
Definition: duktape.c:15390
#define duk_memmove_unsafe(dst, src, len)
Definition: duktape.c:3059
#define DUK__PI_YEAR
Definition: duktape.c:32787
DUK_LOCAL_DECL void duk__ivalue_regconst(duk_ivalue *x, duk_regconst_t regconst)
Definition: duktape.c:70984
#define DUK__CHECK_SPACE()
Definition: duktape.c:18745
DUK_LOCAL duk_ret_t duk__error_getter_helper(duk_hthread *thr, duk_small_int_t output_type)
Definition: duktape.c:35899
DUK_INTERNAL_DECL void duk_err_setup_ljstate1(duk_hthread *thr, duk_small_uint_t lj_type, duk_tval *tv_val)
Definition: duktape.c:49840
#define DUK__INT_NOACTION
Definition: duktape.c:78932
#define DUK_HOBJECT_HAS_COMPFUNC(h)
Definition: duktape.c:6749
DUK_EXTERNAL duk_bool_t duk_is_constructor_call(duk_hthread *thr)
Definition: duktape.c:15565
#define DUK__ERROR_STASH_SHARED(code)
Definition: duktape.c:25147
#define DUK_TOK_CATCH
Definition: duktape.c:3854
DUK_EXTERNAL duk_int_t duk_pnew(duk_hthread *thr, duk_idx_t nargs)
Definition: duktape.c:15546
#define DUK__ALLOW_AUTO_SEMI_ALWAYS
Definition: duktape.c:74112
#define DUK_STR_CYCLIC_INPUT
Definition: duktape.c:3237
#define DUK_STRIDX_PC
Definition: duktape.c:1849
DUK_LOCAL DUK_EXEC_NOINLINE_PERF duk_instr_t * duk__handle_op_endcatch(duk_hthread *thr, duk_uint_fast32_t ins)
Definition: duktape.c:79610
DUK_INTERNAL_DECL void duk_heap_strtable_force_resize(duk_heap *heap)
Definition: duktape.c:56331
DUK_LOCAL void duk__cbor_encode(duk_hthread *thr, duk_idx_t idx, duk_uint_t encode_flags)
Definition: duktape.c:32535
#define DUK_HOBJECT_E_SET_VALUE_SETTER(heap, h, i, v)
Definition: duktape.c:7036
#define DUK_IS_POWER_OF_TWO(x)
Definition: duktape.c:3154
DUK_INTERNAL_DECL duk_ret_t duk_bi_number_constructor(duk_context *ctx)
Definition: duktape.c:41130
DUK_LOCAL void duk__update_default_instance_proto(duk_hthread *thr, duk_idx_t idx_func)
Definition: duktape.c:66542
#define DUK_HBUFOBJ_VALID_BYTEOFFSET_EXCL(h, off)
Definition: duktape.c:7956
#define DUK_BC_INCDECP_FLAG_DEC
Definition: duktape.c:3476
DUK_INTERNAL_DECL void duk_hthread_sync_and_null_currpc(duk_hthread *thr)
Definition: duktape.c:65508
#define DUK_OP_ENDTRY
Definition: duktape.c:3679
#define DUK_ASC_LC_G
Definition: duktape.c:10861
#define DUK_TOK_STRING
Definition: duktape.c:3971
#define DUK_HEAPHDR_ASSERT_LINKS(heap, h)
Definition: duktape.c:4863
DUK_INTERNAL_DECL duk_bool_t duk_double_is_integer(duk_double_t x)
Definition: duktape.c:100742
DUK_EXTERNAL duk_bool_t duk_is_thread(duk_hthread *thr, duk_idx_t idx)
Definition: duktape.c:22866
DUK_INTERNAL_DECL duk_ret_t duk_bi_string_prototype_substr(duk_context *ctx)
Definition: duktape.c:43063
#define DUK_TOK_RBRACKET
Definition: duktape.c:3919
#define DUK__BC_INITIAL_INSTS
Definition: duktape.c:69087
#define DUK__FLOAT_MAX
Definition: duktape.c:100537
DUK_LOCAL const char *const duk__toprim_hint_strings[3]
Definition: duktape.c:21439
#define DUK_CAT_FLAG_FINALLY_ENABLED
Definition: duktape.c:8087
#define DUK_STR_UNTERMINATED_STMT
Definition: duktape.c:3288
DUK_EXTERNAL void * duk_steal_buffer(duk_hthread *thr, duk_idx_t idx, duk_size_t *out_size)
Definition: duktape.c:14367
#define DUK_HOBJECT_E_SLOT_IS_ACCESSOR(heap, h, i)
Definition: duktape.c:7069
DUK_INTERNAL_DECL duk_int_t duk_get_type_tval(duk_tval *tv)
Definition: duktape.c:22498
#define DUK_OP_EQ_CC
Definition: duktape.c:3500
#define DUK_STRIDX_ARRAY_BUFFER
Definition: duktape.c:1627
DUK_INTERNAL_DECL duk_ret_t duk_bi_math_object_onearg_shared(duk_context *ctx)
Definition: duktape.c:40890
#define DUK_HOBJECT_CLASS_UINT32ARRAY
Definition: duktape.c:6663
DUK_EXTERNAL duk_bool_t duk_is_null(duk_hthread *thr, duk_idx_t idx)
Definition: duktape.c:22665
DUK_INTERNAL_DECL void duk_lexer_getpoint(duk_lexer_ctx *lex_ctx, duk_lexer_point *pt)
Definition: duktape.c:86296
#define DUK_HSTRING_HAS_EVAL_OR_ARGUMENTS(x)
Definition: duktape.c:6344
#define DUK_OP_UNUSED248
Definition: duktape.c:3763
DUK_LOCAL void duk__dragon4_ctx_to_double(duk__numconv_stringify_ctx *nc_ctx, duk_double_t *x)
Definition: duktape.c:89589
#define DUK_TVAL_CHKFAST_INPLACE_SLOW(tv)
Definition: duktape.c:1355
#define DUK__MK_LBP_FLAGS(bp, flags)
Definition: duktape.c:69350
#define DUK_OP_DECLVAR_CR
Definition: duktape.c:3657
#define DUK_ASC_PERCENT
Definition: duktape.c:10795
DUK_INTERNAL_DECL duk_ret_t duk_bi_reflect_construct(duk_context *ctx)
Definition: duktape.c:36374
DUK_LOCAL duk_bool_t duk__js_equals_number(duk_double_t x, duk_double_t y)
Definition: duktape.c:82871
DUK_EXTERNAL duk_idx_t duk_push_proxy(duk_hthread *thr, duk_uint_t proxy_flags)
Definition: duktape.c:24245
#define DUK__BP_POSTFIX
Definition: duktape.c:69338
DUK_INTERNAL_DECL void duk_resolve_nonbound_function(duk_hthread *thr)
Definition: duktape.c:15680
DUK_INTERNAL_DECL void duk_xdef_prop_stridx_thrower(duk_hthread *thr, duk_idx_t obj_idx, duk_small_uint_t stridx)
Definition: duktape.c:18150
#define DUK__TOKEN_LBP_FLAG_NO_REGEXP
Definition: duktape.c:69343
#define DUK_CAT_SET_LEXENV_ACTIVE(c)
Definition: duktape.c:8115
#define DUK_HEAPHDR_SET_FLAGS(h, val)
Definition: duktape.c:4748
#define DUK_RETOK_ATOM_START_CAPTURE_GROUP
Definition: duktape.c:4142
DUK_INTERNAL_DECL duk_small_int_t duk_unicode_re_is_wordchar(duk_codepoint_t cp)
Definition: duktape.c:13818
#define DUK__HAS_VAL
Definition: duktape.c:74110
DUK_INTERNAL_DECL duk_ret_t duk_bi_textdecoder_prototype_decode(duk_context *ctx)
Definition: duktape.c:35755
#define DUK_HOBJECT_CLASS_THREAD
Definition: duktape.c:6653
#define DUK_DBG_CMD_DETACHING
Definition: duktape.c:9727
DUK_LOCAL double duk__round_fixed(double x)
Definition: duktape.c:40747
#define DUK_OP_DELVAR
Definition: duktape.c:3669
#define DUK_STRIDX_UC_THREAD
Definition: duktape.c:1675
#define DUK_CAT_HAS_LEXENV_ACTIVE(c)
Definition: duktape.c:8101
DUK_LOCAL duk_codepoint_t duk__inp_get_prev_cp(duk_re_matcher_ctx *re_ctx, const duk_uint8_t *sp)
Definition: duktape.c:91942
DUK_LOCAL void duk__lexer_parse_string_literal(duk_lexer_ctx *lex_ctx, duk_token *out_token, duk_small_int_t quote, duk_bool_t strict_mode)
Definition: duktape.c:86514
DUK_EXTERNAL duk_int_t duk_get_magic(duk_hthread *thr, duk_idx_t idx)
Definition: duktape.c:15638
#define DUK__FLD_8BIT
Definition: duktape.c:30043
#define DUK_TVAL_IS_HEAP_ALLOCATED(tv)
Definition: duktape.c:1508
#define DUK_HOBJECT_FLAG_STRICT
Definition: duktape.c:6601
DUK_INTERNAL_DECL void duk_hthread_sync_currpc(duk_hthread *thr)
Definition: duktape.c:65493
#define DUK_HSTRING_MAX_BYTELEN
Definition: duktape.c:6315
DUK_LOCAL_DECL duk_regconst_t duk__getconst(duk_compiler_ctx *comp_ctx)
Definition: duktape.c:71056
DUK_INTERNAL void duk_err_create_and_throw(duk_hthread *thr, duk_errcode_t code, const char *msg, const char *filename, duk_int_t line)
Definition: duktape.c:49879
#define DUK_RETOK_ASSERT_START
Definition: duktape.c:4127
DUK_INTERNAL_DECL duk_ret_t duk_bi_nodejs_buffer_tostring(duk_context *ctx)
Definition: duktape.c:28966
DUK_LOCAL duk_small_uint_t duk__date_get_indirect_magic(duk_hthread *thr)
Definition: duktape.c:34158
#define DUK__REPLACE_BOOL_A_BREAK(bval)
#define DUK_OP_MOD_CC
Definition: duktape.c:3566
#define DUK_HTHREAD_STRING_EVAL(thr)
Definition: duktape.c:1680
#define DUK_STRIDX_UC_SYMBOL
Definition: duktape.c:1585
#define DUK_OP_REGEXP_CR
Definition: duktape.c:3662
#define DUK__BP_LAND
Definition: duktape.c:69328
#define DUK_STRIDX_TO_STRING
Definition: duktape.c:1825
DUK_INTERNAL_DECL void duk_hthread_catcher_unwind_norz(duk_hthread *thr, duk_activation *act)
Definition: duktape.c:65535
duk_uint32_t duk_instr_t
Definition: duktape.c:3411
#define DUK_HOBJECT_CMASK_FUNCTION
Definition: duktape.c:6677
DUK_LOCAL void duk__insert_slice(duk_re_compiler_ctx *re_ctx, duk_uint32_t offset, duk_uint32_t data_offset, duk_uint32_t data_length)
Definition: duktape.c:90635
#define DUK_TVAL_SET_DOUBLE(tv, val)
Definition: duktape.c:1311
DUK_INTERNAL_DECL duk_ret_t duk_bi_date_constructor_now(duk_context *ctx)
Definition: duktape.c:34241
DUK_LOCAL_DECL void duk__json_enc_array(duk_json_enc_ctx *js_ctx)
Definition: duktape.c:39280
DUK_INTERNAL_DECL duk_ret_t duk_bi_date_prototype_value_of(duk_context *ctx)
Definition: duktape.c:34289
#define DUK_HCOMPFUNC_GET_CODE_COUNT(heap, h)
Definition: duktape.c:7646
DUK_LOCAL void duk__cbor_encode_double_fp(duk_cbor_encode_context *enc_ctx, double d)
Definition: duktape.c:30931
#define DUK__NO_EXP
Definition: duktape.c:89390
#define DUK__STRFTIME_BUF_SIZE
Definition: duktape.c:34570
DUK_INTERNAL_DECL duk_hproxy * duk_hproxy_alloc(duk_hthread *thr, duk_uint_t hobject_flags)
Definition: duktape.c:56738
DUK_LOCAL void duk__create_arguments_object(duk_hthread *thr, duk_hobject *func, duk_hobject *varenv, duk_idx_t idx_args)
Definition: duktape.c:66239
DUK_INTERNAL_DECL duk_bool_t duk_js_getvar_activation(duk_hthread *thr, duk_activation *act, duk_hstring *name, duk_bool_t throw_flag)
Definition: duktape.c:85169
#define DUK_STRIDX_UINT8_ARRAY
Definition: duktape.c:1636
#define DUK_STRIDX_LAST_INDEX
Definition: duktape.c:1720
#define DUK_OP_LDUNDEF
Definition: duktape.c:3487
#define DUK_HOBJECT_SET_HAVE_FINALIZER(h)
Definition: duktape.c:6790
#define DUK_STRIDX_START_STRICT_RESERVED
Definition: duktape.c:2083
#define DUK_STR_SOURCE_DECODE_FAILED
Definition: duktape.c:3223
#define DUK_TOK_BREAK
Definition: duktape.c:3852
DUK_LOCAL_DECL duk_regconst_t duk__exprtop_toreg(duk_compiler_ctx *comp_ctx, duk_ivalue *res, duk_small_uint_t rbp_flags)
Definition: duktape.c:74065
DUK_INTERNAL_DECL duk_ret_t duk_bi_nodejs_buffer_constructor(duk_context *ctx)
Definition: duktape.c:28400
#define DUK_GET_HOBJECT_POSIDX(thr, idx)
Definition: duktape.c:6273
DUK_LOCAL duk_double_t duk__cbor_decode_float(duk_cbor_decode_context *dec_ctx)
Definition: duktape.c:31993
DUK_LOCAL duk_bool_t duk__hstring_is_eval_or_arguments(duk_compiler_ctx *comp_ctx, duk_hstring *h)
Definition: duktape.c:69477
DUK_INTERNAL_DECL void duk_pop_n_unsafe(duk_hthread *thr, duk_idx_t count)
Definition: duktape.c:24646
#define DUK_OP_PREDECV
Definition: duktape.c:3632
#define DUK_STRIDX_UINT16_ARRAY
Definition: duktape.c:1645
DUK_LOCAL DUK_NOINLINE duk_catcher * duk__hthread_catcher_alloc_slow(duk_hthread *thr)
Definition: duktape.c:65586
DUK_LOCAL_DECL void duk__exprtop(duk_compiler_ctx *ctx, duk_ivalue *res, duk_small_uint_t rbp_flags)
Definition: duktape.c:73994
DUK_LOCAL DUK__RZ_INLINE void duk__hstring_refzero_helper(duk_hthread *thr, duk_hstring *h)
Definition: duktape.c:54735
#define DUK_OP_CALL2
Definition: duktape.c:3692
DUK_INTERNAL_DECL duk_hstring * duk_heap_strtable_intern_literal_checked(duk_hthread *thr, const duk_uint8_t *str, duk_uint32_t blen)
Definition: duktape.c:56170
DUK_INTERNAL_DECL void duk_hbuffer_refzero(duk_hthread *thr, duk_hbuffer *h)
Definition: duktape.c:54823
DUK_EXTERNAL void duk_get_finalizer(duk_hthread *thr, duk_idx_t idx)
Definition: duktape.c:18618
#define DUK_HCOMPFUNC_GET_FUNCS_BASE(heap, h)
Definition: duktape.c:7617
DUK_LOCAL_DECL void duk__json_dec_objarr_exit(duk_json_dec_ctx *js_ctx)
Definition: duktape.c:38083
#define DUK__COMPILE_ENTRY_SLOTS
Definition: duktape.c:69105
DUK_LOCAL const duk_uint16_t *const duk__re_range_lookup1[3]
Definition: duktape.c:90996
#define DUK_HOBJECT_E_GET_VALUE_PTR(heap, h, i)
Definition: duktape.c:7006
#define DUK_STR_INVALID_QUANTIFIER_VALUES
Definition: duktape.c:3297
#define DUK_HOBJECT_PROTOTYPE_CHAIN_SANITY
Definition: duktape.c:7165
DUK_LOCAL duk_small_int_t duk__dragon4_fixed_format_round(duk__numconv_stringify_ctx *nc_ctx, duk_small_int_t round_idx)
Definition: duktape.c:89318
DUK_EXTERNAL void duk_resume(duk_hthread *thr, const duk_thread_state *state)
Definition: duktape.c:17203
DUK_LOCAL duk_bool_t duk__delvar_helper(duk_hthread *thr, duk_hobject *env, duk_activation *act, duk_hstring *name)
Definition: duktape.c:85328
DUK_EXTERNAL void * duk_get_pointer(duk_hthread *thr, duk_idx_t idx)
Definition: duktape.c:20578
DUK_LOCAL duk_int_t duk__day_from_year(duk_int_t year)
Definition: duktape.c:33201
DUK_EXTERNAL void * duk_get_heapptr(duk_hthread *thr, duk_idx_t idx)
Definition: duktape.c:21102
DUK_EXTERNAL duk_bool_t duk_put_global_heapptr(duk_hthread *thr, void *ptr)
Definition: duktape.c:18499
#define DUK_TOK_RSHIFT_EQ
Definition: duktape.c:3962
DUK_INTERNAL_DECL void duk_pop_2_unsafe(duk_hthread *thr)
Definition: duktape.c:24815
#define DUK_IVAL_ARITH
Definition: duktape.c:4264
#define DUK__SYNC_AND_NULL_CURR_PC()
Definition: duktape.c:80000
DUK_INTERNAL_DECL duk_hstring * duk_to_hstring(duk_hthread *thr, duk_idx_t idx)
Definition: duktape.c:22157
#define DUK_TOK_COMMA
Definition: duktape.c:3924
DUK_EXTERNAL duk_uint_t duk_get_uint(duk_hthread *thr, duk_idx_t idx)
Definition: duktape.c:20347
DUK_INTERNAL_DECL duk_bool_t duk_double_is_anyinf(duk_double_t x)
Definition: duktape.c:100600
DUK_INTERNAL_DECL duk_bool_t duk_double_is_finite(duk_double_t x)
Definition: duktape.c:100738
DUK_LOCAL void duk__append_7bit(duk_re_compiler_ctx *re_ctx, duk_uint32_t x)
Definition: duktape.c:90597
DUK_INTERNAL_DECL void duk_lexer_parse_re_token(duk_lexer_ctx *lex_ctx, duk_re_token *out_token)
Definition: duktape.c:87530
DUK_INTERNAL_DECL duk_bool_t duk_hobject_hasprop(duk_hthread *thr, duk_tval *tv_obj, duk_tval *tv_key)
Definition: duktape.c:60957
#define DUK_STR_TEMP_LIMIT
Definition: duktape.c:3319
DUK_LOCAL_DECL void duk__mark_heaphdr_nonnull(duk_heap *heap, duk_heaphdr *h)
Definition: duktape.c:52314
DUK_LOCAL DUK_EXEC_NOINLINE_PERF void duk__handle_op_trycatch(duk_hthread *thr, duk_uint_fast32_t ins, duk_instr_t *curr_pc)
Definition: duktape.c:79400
DUK_LOCAL void duk__dragon4_generate(duk__numconv_stringify_ctx *nc_ctx)
Definition: duktape.c:89135
#define DUK__REPLACE_TOP_BC_BREAK()
#define DUK__PI_SECOND
Definition: duktape.c:32792
#define DUK_REOP_JUMP
Definition: duktape.c:4493
DUK_INTERNAL_DECL duk_uint32_t duk_raw_readinc_u32_be(const duk_uint8_t **p)
Definition: duktape.c:13933
DUK_LOCAL void duk__transform_callback_escape(duk__transform_context *tfm_ctx, const void *udata, duk_codepoint_t cp)
Definition: duktape.c:36985
DUK_LOCAL_DECL void duk__reset_labels_to_length(duk_compiler_ctx *comp_ctx, duk_size_t len)
Definition: duktape.c:71914
DUK_EXTERNAL void duk_call_prop(duk_hthread *thr, duk_idx_t obj_idx, duk_idx_t nargs)
Definition: duktape.c:15348
DUK_LOCAL void duk__utf8_decode_init(duk__decode_context *dec_ctx)
Definition: duktape.c:35299
#define DUK_BW_WRITE_ENSURE_HSTRING(thr, bw_ctx, val)
Definition: duktape.c:2832
DUK_LOCAL duk_heaphdr * duk_hobject_get_internal_value_heaphdr(duk_heap *heap, duk_hobject *obj)
Definition: duktape.c:59489
#define DUK_HSTRING_SET_STRICT_RESERVED_WORD(x)
Definition: duktape.c:6353
#define DUK_HOBJECT_CLASS_DECENV
Definition: duktape.c:6651
DUK_EXTERNAL duk_bool_t duk_has_prop(duk_hthread *thr, duk_idx_t obj_idx)
Definition: duktape.c:17984
DUK_INTERNAL_DECL void duk_heaphdr_refzero(duk_hthread *thr, duk_heaphdr *h)
Definition: duktape.c:54811
#define DUK_N2S_FLAG_FRACTION_DIGITS
Definition: duktape.c:11248
#define DUK_HOBJECT_MAX_PROPERTIES
Definition: duktape.c:7235
DUK_INTERNAL_DECL void duk_hobject_enumerator_create(duk_hthread *thr, duk_small_uint_t enum_flags)
Definition: duktape.c:57071
#define DUK_ERROR_FMT2(thr, err, fmt, arg1, arg2)
Definition: duktape.c:10128
DUK_LOCAL const duk_uint8_t duk__str2num_digits_for_radix[]
Definition: duktape.c:88193
#define DUK_RETOK_ASSERT_START_POS_LOOKAHEAD
Definition: duktape.c:4131
#define DUK_TOK_EXP
Definition: duktape.c:3938
DUK_EXTERNAL duk_bool_t duk_put_prop_literal_raw(duk_hthread *thr, duk_idx_t obj_idx, const char *key, duk_size_t key_len)
Definition: duktape.c:17859
DUK_INTERNAL_DECL duk_ret_t duk_bi_date_prototype_set_shared(duk_context *ctx)
Definition: duktape.c:34451
#define DUK_DELPROP_FLAG_FORCE
Definition: duktape.c:7453
DUK_LOCAL_DECL void duk__advance_expect(duk_compiler_ctx *comp_ctx, duk_small_int_t expect)
Definition: duktape.c:69556
DUK_INTERNAL_DECL duk_bool_t duk_float_equals(duk_float_t x, duk_float_t y)
Definition: duktape.c:100929
#define DUK_S2N_FLAG_ALLOW_EMPTY_AS_ZERO
Definition: duktape.c:11292
#define DUK__IEEE_DOUBLE_EXP_MIN
Definition: duktape.c:88174
#define DUK_BW_REMOVE_ENSURE_SLICE(thr, bw, off, len)
Definition: duktape.c:2878
DUK_EXTERNAL void duk_require_null(duk_hthread *thr, duk_idx_t idx)
Definition: duktape.c:20199
#define DUK_OP_SUB_CC
Definition: duktape.c:3551
#define DUK_OP_BASR
Definition: duktape.c:3597
#define DUK_STR_ENC_RECLIMIT
Definition: duktape.c:3241
#define DUK_TOK_INVALID
Definition: duktape.c:3976
DUK_INTERNAL_DECL void duk_dup_m4(duk_hthread *thr)
Definition: duktape.c:19835
DUK_INTERNAL_DECL void duk_numconv_stringify(duk_hthread *thr, duk_small_int_t radix, duk_small_int_t digits, duk_small_uint_t flags)
Definition: duktape.c:89934
DUK_INTERNAL_DECL duk_float_t duk_raw_read_float_be(const duk_uint8_t *p)
Definition: duktape.c:13913
DUK_INTERNAL_DECL duk_hstring * duk_to_hstring_acceptsymbol(duk_hthread *thr, duk_idx_t idx)
Definition: duktape.c:22173
DUK_LOCAL double duk__log10(double x)
Definition: duktape.c:40727
#define DUK_HOBJECT_HAS_FINALIZER_FAST(heap, h)
Definition: duktape.c:7219
DUK_EXTERNAL duk_bool_t duk_next(duk_hthread *thr, duk_idx_t enum_index, duk_bool_t get_value)
Definition: duktape.c:18276
struct duk_hbuffer_fixed duk_hbuffer_fixed
Definition: duktape.c:850
DUK_LOCAL_DECL void duk__insert_jump_entry(duk_compiler_ctx *comp_ctx, duk_int_t jump_pc)
Definition: duktape.c:70734
#define DUK_HOBJECT_IS_FUNCTION(h)
Definition: duktape.c:6729
#define duk_memcpy(dst, src, len)
Definition: duktape.c:3028
DUK_LOCAL duk_bool_t duk__tag_check(duk_hthread *thr, duk_idx_t idx, duk_small_uint_t tag)
Definition: duktape.c:22478
#define DUK__IS_TERMINAL
Definition: duktape.c:74114
#define DUK_BW_INIT_PUSHBUF(thr, bw_ctx, sz)
Definition: duktape.c:2513
DUK_INTERNAL_DECL void duk_free_hstring(duk_heap *heap, duk_hstring *h)
Definition: duktape.c:50344
DUK_INTERNAL_DECL void duk_dblunion_host_to_little(duk_double_union *u)
Definition: duktape.c:100831
#define DUK_BIDX_BOOLEAN_PROTOTYPE
Definition: duktape.c:2298
DUK_EXTERNAL void duk_push_number(duk_hthread *thr, duk_double_t val)
Definition: duktape.c:23034
#define DUK_STR_INVALID_BREAK_CONT_LABEL
Definition: duktape.c:3282
struct duk_tval_struct duk_tval
Definition: duktape.c:1219
#define DUK_DBG_IB_UNDEFINED
Definition: duktape.c:9701
DUK_EXTERNAL duk_int_t duk_eval_raw(duk_hthread *thr, const char *src_buffer, duk_size_t src_length, duk_uint_t flags)
Definition: duktape.c:16657
DUK_INTERNAL_DECL duk_bool_t duk_is_bare_object(duk_hthread *thr, duk_idx_t idx)
Definition: duktape.c:18595
#define DUK__L2()
Definition: duktape.c:85807
DUK_LOCAL_DECL void duk__json_enc_bufobj(duk_json_enc_ctx *js_ctx, duk_hbufobj *h_bufobj)
Definition: duktape.c:39012
#define DUK__HASH_UNUSED
Definition: duktape.c:57946
#define DUK_ASC_STAR
Definition: duktape.c:10800
DUK_EXTERNAL void * duk_require_pointer(duk_hthread *thr, duk_idx_t idx)
Definition: duktape.c:20597
DUK_INTERNAL_DECL duk_ret_t duk_bi_object_prototype_to_locale_string(duk_context *ctx)
Definition: duktape.c:41594
#define DUK_OP_ADD_RC
Definition: duktape.c:3545
DUK_INTERNAL_DECL duk_ret_t duk_bi_boolean_prototype_tostring_shared(duk_context *ctx)
Definition: duktape.c:27747
#define DUK__STRICT()
Definition: duktape.c:79916
DUK_LOCAL void duk__strtable_shrink_inplace(duk_heap *heap)
Definition: duktape.c:55717
#define DUK_STRIDX_EVAL
Definition: duktape.c:1678
#define DUK_OP_LABEL
Definition: duktape.c:3674
DUK_LOCAL void duk__dragon4_convert_and_push(duk__numconv_stringify_ctx *nc_ctx, duk_hthread *thr, duk_small_int_t radix, duk_small_int_t digits, duk_small_uint_t flags, duk_small_int_t neg)
Definition: duktape.c:89392
DUK_INTERNAL_DECL duk_small_int_t duk_js_string_compare(duk_hstring *h1, duk_hstring *h2)
Definition: duktape.c:83200
#define DUK_HOBJECT_SET_ENEXT(h, v)
Definition: duktape.c:7133
#define DUK_OP_POSTINCP_CR
Definition: duktape.c:3647
#define DUK_STRIDX_LC_STRING
Definition: duktape.c:1744
#define DUK__DECREF_SHARED()
Definition: duktape.c:54922
#define DUK_ASC_LC_I
Definition: duktape.c:10863
#define DUK_HBUFFER_FIXED_GET_DATA_PTR(heap, x)
Definition: duktape.c:8664
DUK_LOCAL duk_bool_t duk__cbor_decode_array(duk_cbor_decode_context *dec_ctx, duk_uint8_t ib, duk_uint8_t ai)
Definition: duktape.c:31893
#define DUK_LFUNC_LENGTH_MIN
Definition: duktape.c:1540
#define DUK__LONGJMP_RESTART
Definition: duktape.c:77934
DUK_INTERNAL_DECL void duk_err_augment_error_throw(duk_hthread *thr)
Definition: duktape.c:49570
#define DUK_STR_INVALID_BASE
Definition: duktape.c:3244
DUK_LOCAL duk_ret_t duk__parse_string(duk_hthread *thr, const char *str)
Definition: duktape.c:33090
DUK_INTERNAL_DECL duk_double_t duk_double_div(duk_double_t x, duk_double_t y)
Definition: duktape.c:100798
DUK_LOCAL const duk_uint8_t * duk__scan_forwards(const duk_uint8_t *p, const duk_uint8_t *q, duk_uint_fast32_t n)
Definition: duktape.c:55054
#define DUK_HSTRING_SET_HASH(x, v)
Definition: duktape.c:6384
DUK_INTERNAL_DECL duk_double_t duk_double_fmax(duk_double_t x, duk_double_t y)
Definition: duktape.c:100729
DUK_EXTERNAL duk_bool_t duk_check_type_mask(duk_hthread *thr, duk_idx_t idx, duk_uint_t mask)
Definition: duktape.c:22647
#define DUK_ASC_LBRACKET
Definition: duktape.c:10849
DUK_LOCAL const duk_uint8_t duk__encode_uricomponent_unescaped_table[16]
Definition: duktape.c:36674
DUK_INTERNAL_DECL duk_small_uint_t duk_bd_decode_bitpacked_string(duk_bitdecoder_ctx *bd, duk_uint8_t *out)
Definition: duktape.c:100048
#define DUK_HOBJECT_CLASS_MAX
Definition: duktape.c:6667
#define DUK__SM_T
Definition: duktape.c:32821
DUK_LOCAL const duk_int8_t duk__base64_dectab_fast[256]
Definition: duktape.c:15789
#define DUK_DBG_IB_STR2
Definition: duktape.c:9697
DUK_LOCAL const duk_uint8_t * duk__load_string_raw(duk_hthread *thr, const duk_uint8_t *p)
Definition: duktape.c:14441
DUK_EXTERNAL void * duk_opt_heapptr(duk_hthread *thr, duk_idx_t idx, void *def_value)
Definition: duktape.c:21119
DUK_EXTERNAL void duk_push_uint(duk_hthread *thr, duk_uint_t val)
Definition: duktape.c:23075
#define DUK_OP_BLSR
Definition: duktape.c:3592
#define DUK_STR_WRONG_BUFFER_TYPE
Definition: duktape.c:3221
DUK_LOCAL duk__decode_context * duk__get_textdecoder_context(duk_hthread *thr)
Definition: duktape.c:35722
#define DUK_D(x)
Definition: duktape.c:9956
DUK_INTERNAL_DECL void duk_raw_writeinc_cesu8(duk_uint8_t **p, duk_ucodepoint_t val)
Definition: duktape.c:14012
#define DUK_ASC_RCURLY
Definition: duktape.c:10883
#define DUK__L1()
Definition: duktape.c:85806
#define DUK_DBG_ERR_UNSUPPORTED
Definition: duktape.c:9716
#define DUK_BC_B_MIN
Definition: duktape.c:3462
#define DUK_OP_LE
Definition: duktape.c:3531
DUK_LOCAL const duk_uint8_t * duk__utf8_advance(duk_hthread *thr, const duk_uint8_t **ptr, const duk_uint8_t *ptr_start, const duk_uint8_t *ptr_end, duk_uint_fast32_t count)
Definition: duktape.c:91881
DUK_LOCAL void duk__handle_label(duk_hthread *thr, duk_small_uint_t lj_type)
Definition: duktape.c:78200
DUK_LOCAL_DECL duk_heaphdr * duk__get_tagged_heaphdr_raw(duk_hthread *thr, duk_idx_t idx, duk_uint_t tag)
Definition: duktape.c:20817
#define DUK_HCOMPFUNC_GET_CODE_SIZE(heap, h)
Definition: duktape.c:7638
DUK_LOCAL double duk__fabs(double x)
Definition: duktape.c:40793
DUK_INTERNAL_DECL duk_ret_t duk_bi_string_prototype_match(duk_context *ctx)
Definition: duktape.c:43939
DUK_LOCAL_DECL void duk__grow_props_for_array_item(duk_hthread *thr, duk_hobject *obj, duk_uint32_t highest_arr_idx)
Definition: duktape.c:59070
#define DUK_STRIDX_INT_TARGET
Definition: duktape.c:1867
DUK_LOCAL_DECL void duk__nud_object_literal(duk_compiler_ctx *comp_ctx, duk_ivalue *res)
Definition: duktape.c:72136
#define DUK_STR_WITH_IN_STRICT_MODE
Definition: duktape.c:3286
DUK_LOCAL duk_bool_t duk__compare_fastint(duk_bool_t retval, duk_int64_t v1, duk_int64_t v2)
Definition: duktape.c:83239
#define DUK_HOBJECT_FLAG_CALLABLE
Definition: duktape.c:6593
#define DUK_OP_MUL
Definition: duktape.c:3552
#define DUK_BW_GET_PTR(thr, bw_ctx)
Definition: duktape.c:2552
#define DUK_STR_NOT_CONFIGURABLE
Definition: duktape.c:3194
DUK_LOCAL_DECL void duk__emit_load_int32(duk_compiler_ctx *comp_ctx, duk_regconst_t reg, duk_int32_t val)
Definition: duktape.c:70691
DUK_LOCAL const duk_uint8_t duk__json_decnumber_lookup[256]
Definition: duktape.c:37520
#define DUK_HSTRING_SET_ARRIDX(x)
Definition: duktape.c:6349
#define DUK_HTHREAD_STRING_TO_JSON(thr)
Definition: duktape.c:1830
DUK_LOCAL void duk__cbor_encode_double(duk_cbor_encode_context *enc_ctx, double d)
Definition: duktape.c:31050
DUK_INTERNAL_DECL duk_bool_t duk_hobject_prototype_chain_contains(duk_hthread *thr, duk_hobject *h, duk_hobject *p, duk_bool_t ignore_loop)
Definition: duktape.c:57599
#define DUK__WEEKDAY_MOD_ADDER
Definition: duktape.c:33144
DUK_INTERNAL_DECL void duk_push_class_string_tval(duk_hthread *thr, duk_tval *tv, duk_bool_t avoid_side_effects)
Definition: duktape.c:21899
DUK_LOCAL_DECL void duk__patch_jump(duk_compiler_ctx *comp_ctx, duk_int_t jump_pc, duk_int_t target_pc)
Definition: duktape.c:70768
DUK_INTERNAL const duk_int16_t duk_hex_dectab_shift4[256]
Definition: duktape.c:14066
#define DUK_HEAP_STRINGCACHE_NOCACHE_LIMIT
Definition: duktape.c:9100
#define DUK_VALSTACK_INITIAL_SIZE
Definition: duktape.c:8040
#define DUK_TOK_WHILE
Definition: duktape.c:3877
#define DUK_HBOUNDFUNC_ASSERT_VALID(h)
Definition: duktape.c:7862
#define DUK_OP_LT_RR
Definition: duktape.c:3527
DUK_INTERNAL_DECL duk_bool_t duk_hobject_proxy_check(duk_hobject *obj, duk_hobject **out_target, duk_hobject **out_handler)
Definition: duktape.c:58379
#define DUK__RZ_INLINE
Definition: duktape.c:54730
DUK_LOCAL duk_uint32_t duk__count_used_e_keys(duk_hthread *thr, duk_hobject *obj)
Definition: duktape.c:58170
#define DUK__GT_BODY(barg, carg)
DUK_LOCAL void duk__compact_object_list(duk_heap *heap, duk_hthread *thr, duk_heaphdr *start)
Definition: duktape.c:52924
#define DUK_OP_CALL4
Definition: duktape.c:3694
#define DUK_LFUNC_FLAGS_GET_MAGIC(lf_flags)
Definition: duktape.c:1532
DUK_EXTERNAL duk_idx_t duk_push_c_function(duk_hthread *thr, duk_c_function func, duk_int_t nargs)
Definition: duktape.c:23806
#define DUK_RETOK_ATOM_NOT_DIGIT
Definition: duktape.c:4136
DUK_INTERNAL_DECL duk_small_int_t duk_raw_write_cesu8(duk_uint8_t *p, duk_ucodepoint_t val)
Definition: duktape.c:13982
DUK_LOCAL duk_ret_t duk__pcall_prop_raw(duk_hthread *thr, void *udata)
Definition: duktape.c:15446
DUK_INTERNAL_DECL duk_ret_t duk_bi_error_prototype_to_string(duk_context *ctx)
Definition: duktape.c:35830
#define DUK_STR_INVALID_REGEXP_GROUP
Definition: duktape.c:3306
#define DUK_AUGMENT_FLAG_SKIP_ONE
Definition: duktape.c:10657
DUK_INTERNAL_DECL void duk_push_symbol_descriptive_string(duk_hthread *thr, duk_hstring *h)
Definition: duktape.c:25515
#define DUK_STRIDX_INT_TRACEDATA
Definition: duktape.c:1855
DUK_LOCAL void duk__cbor_encode_uint32(duk_cbor_encode_context *enc_ctx, duk_uint32_t u, duk_uint8_t base)
Definition: duktape.c:30895
#define DUK_ASC_HT
Definition: duktape.c:10767
#define DUK__DECREF_ASSERTS()
Definition: duktape.c:54890
#define DUK__ALLOCTEMPS(comp_ctx, count)
Definition: duktape.c:69067
#define DUK_ISPEC_REGCONST
Definition: duktape.c:4270
#define DUK__STRTAB_U32_MAX_STRLEN
Definition: duktape.c:55354
#define DUK__CF_NEG
Definition: duktape.c:32829
#define DUK_HOBJECT_E_SET_FLAGS(heap, h, i, f)
Definition: duktape.c:7040
#define DUK_TOK_CONTINUE
Definition: duktape.c:3855
#define DUK__PROP_TYPE_BITS
Definition: duktape.c:64540
#define DUK_S2N_MAX_EXPONENT
Definition: duktape.c:11262
#define DUK__IDX_DBYTES
Definition: duktape.c:17339
#define DUK__BI_PRINT(name, x)
Definition: duktape.c:88233
#define DUK_CTX_ASSERT_VALID(thr)
Definition: duktape.c:8193
DUK_LOCAL_DECL void duk__reset_func_for_pass2(duk_compiler_ctx *comp_ctx)
Definition: duktape.c:69633
DUK_INTERNAL_DECL duk_ret_t duk_bi_global_object_decode_uri_component(duk_context *ctx)
Definition: duktape.c:37329
DUK_EXTERNAL void duk_require_constructor_call(duk_hthread *thr)
Definition: duktape.c:15577
#define DUK__RETHAND_FINISHED
Definition: duktape.c:77938
#define DUK_STRIDX_UINT32_ARRAY
Definition: duktape.c:1651
DUK_INTERNAL_DECL duk_bool_t duk_js_compare_helper(duk_hthread *thr, duk_tval *tv_x, duk_tval *tv_y, duk_small_uint_t flags)
Definition: duktape.c:83346
#define DUK_HOBJECT_SET_CONSTRUCTABLE(h)
Definition: duktape.c:6775
DUK_LOCAL duk_uint8_t duk__date_equivyear[14]
Definition: duktape.c:32739
DUK_INTERNAL_DECL duk_double_t duk_util_get_random_double(duk_hthread *thr)
Definition: duktape.c:14174
#define DUK_OP_CONTINUE
Definition: duktape.c:3677
DUK_INTERNAL_DECL void duk_hobject_object_get_own_property_descriptor(duk_hthread *thr, duk_idx_t obj_idx)
Definition: duktape.c:62984
#define DUK_TAG_UNDEFINED
Definition: duktape.c:1261
DUK_LOCAL_DECL void duk__exprtop_toforcedreg(duk_compiler_ctx *comp_ctx, duk_ivalue *res, duk_small_uint_t rbp_flags, duk_regconst_t forced_reg)
Definition: duktape.c:74077
#define DUK_HCOMPFUNC_GET_CONSTS_END(heap, h)
Definition: duktape.c:7621
#define DUK_S2N_FLAG_ALLOW_PLUS
Definition: duktape.c:11274
#define DUK__GE_BODY(barg, carg)
DUK_LOCAL void duk__mark_finalizable(duk_heap *heap)
Definition: duktape.c:52361
#define DUK_HEAPHDR_HAS_FINALIZED(h)
Definition: duktape.c:4796
#define DUK_DEC_BC(x)
Definition: duktape.c:3438
#define DUK__REGCONSTP_B(ins)
Definition: duktape.c:79963
DUK_LOCAL void duk__cbor_decode(duk_hthread *thr, duk_idx_t idx, duk_uint_t decode_flags)
Definition: duktape.c:32563
DUK_LOCAL_DECL void duk__emit_invalid(duk_compiler_ctx *comp_ctx)
Definition: duktape.c:70859
#define DUK_STR_INVALID_CONTEXT
Definition: duktape.c:3195
#define DUK_STRIDX_UC_ARRAY
Definition: duktape.c:1597
#define DUK_TOK_THROW
Definition: duktape.c:3871
DUK_INTERNAL_DECL duk_uint_fast32_t duk_hthread_get_act_prev_pc(duk_hthread *thr, duk_activation *act)
Definition: duktape.c:65473
#define DUK_PROPDESC_FLAGS_WC
Definition: duktape.c:6856
#define DUK__CONST_MARKER
Definition: duktape.c:69053
DUK_INTERNAL_DECL void duk_hthread_catcher_unwind_nolexenv_norz(duk_hthread *thr, duk_activation *act)
Definition: duktape.c:65565
DUK_INTERNAL DUK_COLD void duk_err_type_invalid_trap_result(duk_hthread *thr, const char *filename, duk_int_t linenumber)
Definition: duktape.c:12560
DUK_INTERNAL_DECL void duk_raw_write_float_be(duk_uint8_t *p, duk_float_t val)
Definition: duktape.c:13963
DUK_LOCAL duk_bool_t duk__abandon_array_check(duk_hthread *thr, duk_uint32_t arr_idx, duk_hobject *obj)
Definition: duktape.c:58272
#define DUK_DBLUNION_SET_LOW32(u, v)
Definition: duktape.c:386
#define DUK_HOBJECT_HAS_SPECIAL_CALL(h)
Definition: duktape.c:6772
#define DUK_HTHREAD_GET_STRING(thr, idx)
Definition: duktape.c:8147
#define DUK_ASSERT_VS_SPACE(thr)
Definition: duktape.c:10593
#define DUK_HOBJECT_IS_DECENV(h)
Definition: duktape.c:6708
#define DUK_HCOMPFUNC_SET_LEXENV(heap, h, v)
Definition: duktape.c:7597
DUK_EXTERNAL void duk_push_nan(duk_hthread *thr)
Definition: duktape.c:23105
DUK_INTERNAL_DECL duk_bool_t duk_bi_date_year_in_valid_range(duk_double_t year)
Definition: duktape.c:33167
#define DUK_STR_NOT_STRING
Definition: duktape.c:3202
#define DUK_PROPDESC_FLAG_WRITABLE
Definition: duktape.c:6836
#define DUK_HSTRING_SET_RESERVED_WORD(x)
Definition: duktape.c:6352
#define DUK_DDPRINT
Definition: duktape.c:9975
DUK_INTERNAL_DECL duk_activation * duk_hthread_get_activation_for_level(duk_hthread *thr, duk_int_t level)
Definition: duktape.c:65868
#define DUK_INLINE_PERF
Definition: duktape.c:5904
DUK_INTERNAL_DECL void duk_call_construct_postprocess(duk_hthread *thr, duk_small_uint_t proxy_invariant)
Definition: duktape.c:66568
#define DUK_TOK_LOR
Definition: duktape.c:3950
#define DUK_HEAP_GET_STRING(heap, idx)
Definition: duktape.c:9123
#define DUK_STR_INVALID_CFUNC_RC
Definition: duktape.c:3230
#define DUK_OP_IN_RC
Definition: duktape.c:3610
DUK_INTERNAL DUK_COLD void duk_err_handle_error(duk_hthread *thr, const char *filename, duk_uint_t line_and_code, const char *msg)
Definition: duktape.c:12484
#define DUK_DDDPRINT
Definition: duktape.c:9976
#define DUK_OP_GETPROP
Definition: duktape.c:3612
DUK_LOCAL const duk_tval_unused duk__const_tval_unused
Definition: duktape.c:19006
#define DUK__HASH_DELETED
Definition: duktape.c:57947
DUK_LOCAL_DECL void duk__json_enc_key_autoquote(duk_json_enc_ctx *js_ctx, duk_hstring *k)
Definition: duktape.c:38514
#define DUK_OP_POSTDECP_CC
Definition: duktape.c:3654
#define DUK_HEAP_ALLOC_FAIL_MARKANDSWEEP_LIMIT
Definition: duktape.c:9189
#define DUK_BC_LDINTX_SHIFT
Definition: duktape.c:3797
#define DUK_BC_TRYCATCH_FLAG_WITH_BINDING
Definition: duktape.c:3780
#define DUK_CAT_TYPE_TCF
Definition: duktape.c:8092
DUK_LOCAL DUK_COLD duk_size_t duk__hstring_get_charlen_slowpath(duk_hstring *h)
Definition: duktape.c:64369
#define duk_js_equals(thr, tv_x, tv_y)
Definition: duktape.c:11148
#define DUK_BIDX_THREAD_PROTOTYPE
Definition: duktape.c:2321
#define DUK_OP_BOR_CC
Definition: duktape.c:3581
#define DUK_ALLOC_CHECKED_ZEROED(thr, size)
Definition: duktape.c:9182
#define DUK_REOP_BACKREFERENCE
Definition: duktape.c:4502
DUK_EXTERNAL duk_bool_t duk_instanceof(duk_hthread *thr, duk_idx_t idx1, duk_idx_t idx2)
Definition: duktape.c:25245
DUK_LOCAL void duk__update_lineinfo_currtoken(duk_compiler_ctx *comp_ctx)
Definition: duktape.c:70241
#define DUK_ASC_LC_R
Definition: duktape.c:10872
DUK_EXTERNAL void * duk_push_buffer_raw(duk_hthread *thr, duk_size_t size, duk_small_uint_t flags)
Definition: duktape.c:24194
#define DUK_STR_PUSH_BEYOND_ALLOC_STACK
Definition: duktape.c:3197
DUK_INTERNAL_DECL duk_ret_t duk_bi_object_constructor_seal_freeze_shared(duk_context *ctx)
Definition: duktape.c:41561
DUK_EXTERNAL duk_uint_t duk_to_uint(duk_hthread *thr, duk_idx_t idx)
Definition: duktape.c:21669
#define DUK_STR_CALLSTACK_LIMIT
Definition: duktape.c:3312
#define DUK__ARRAY_MID_JOIN_LIMIT
Definition: duktape.c:26127
#define DUK__RECURSION_INCREASE(comp_ctx, thr)
Definition: duktape.c:69090
#define duk_xdef_prop_wec(thr, obj_idx)
Definition: duktape.c:6206
#define DUK_HCOMPFUNC_GET_BYTECODE(heap, h)
Definition: duktape.c:7591
struct duk_harray duk_harray
Definition: duktape.c:837
DUK_INTERNAL_DECL duk_ret_t duk_bi_object_prototype_has_own_property(duk_context *ctx)
Definition: duktape.c:41642
#define DUK_ASC_ATSIGN
Definition: duktape.c:10822
#define DUK__IDX_ESIZE
Definition: duktape.c:17334
DUK_INTERNAL_DECL duk_tval * duk_hobject_get_internal_value_tval_ptr(duk_heap *heap, duk_hobject *obj)
Definition: duktape.c:59485
DUK_EXTERNAL duk_double_t duk_random(duk_hthread *thr)
Definition: duktape.c:18682
DUK_LOCAL void duk__parse_disjunction(duk_re_compiler_ctx *re_ctx, duk_bool_t expect_eof, duk__re_disjunction_info *out_atom_info)
Definition: duktape.c:91017
#define DUK__READABLE_SUMMARY_MAXCHARS
Definition: duktape.c:25357
DUK_LOCAL void duk__add_compiler_error_line(duk_hthread *thr)
Definition: duktape.c:49396
DUK_INTERNAL_DECL duk_small_int_t duk_js_data_compare(const duk_uint8_t *buf1, const duk_uint8_t *buf2, duk_size_t len1, duk_size_t len2)
Definition: duktape.c:83169
#define DUK_OP_NEQ
Definition: duktape.c:3501
#define DUK_DCERROR_TYPE_INVALID_STATE(thr)
Definition: duktape.c:10366
DUK_EXTERNAL void * duk_realloc(duk_hthread *thr, void *ptr, duk_size_t size)
Definition: duktape.c:17594
#define DUK_ERROR_RANGE_INVALID_COUNT(thr)
Definition: duktape.c:10319
#define DUK_TVAL_GET_POINTER(tv)
Definition: duktape.c:1465
#define DUK_HOBJECT_CLASS_INT8ARRAY
Definition: duktape.c:6657
DUK_LOCAL DUK__RZ_INLINE void duk__heaphdr_refzero_helper(duk_hthread *thr, duk_heaphdr *h, duk_bool_t skip_free_pending)
Definition: duktape.c:54768
#define DUK__HEAPPTR_DEC16(heap, val)
Definition: duktape.c:55350
DUK_INTERNAL_DECL duk_bool_t duk_del_prop_stridx(duk_hthread *thr, duk_idx_t obj_idx, duk_small_uint_t stridx)
Definition: duktape.c:17968
#define DUK_RETOK_QUANTIFIER
Definition: duktape.c:4126
DUK_INTERNAL_DECL duk_hcompfunc * duk_require_hcompfunc(duk_hthread *thr, duk_idx_t idx)
Definition: duktape.c:20950
DUK_LOCAL duk_bool_t duk__get_identifier_reference(duk_hthread *thr, duk_hobject *env, duk_hstring *name, duk_activation *act, duk_bool_t parents, duk__id_lookup_result *out)
Definition: duktape.c:84775
#define DUK_STR_FUNC_LIMIT
Definition: duktape.c:3321
DUK_EXTERNAL duk_int_t duk_compile_raw(duk_hthread *thr, const char *src_buffer, duk_size_t src_length, duk_uint_t flags)
Definition: duktape.c:16776
DUK_INTERNAL_DECL duk_ret_t duk_bi_function_prototype_call(duk_context *ctx)
Definition: duktape.c:36354
#define DUK_STRIDX_LC_NUMBER
Definition: duktape.c:1741
DUK_LOCAL void duk__sweep_stringtable(duk_heap *heap, duk_size_t *out_count_keep)
Definition: duktape.c:52613
#define DUK_OP_CALL14
Definition: duktape.c:3704
DUK_INTERNAL_DECL void duk_lexer_initctx(duk_lexer_ctx *lex_ctx)
Definition: duktape.c:86278
DUK_LOCAL void duk__cbor_decode_push_aival_int(duk_cbor_decode_context *dec_ctx, duk_uint8_t ib, duk_bool_t negative)
Definition: duktape.c:31533
#define DUK_OP_IN_CC
Definition: duktape.c:3611
DUK_EXTERNAL duk_bool_t duk_is_nan(duk_hthread *thr, duk_idx_t idx)
Definition: duktape.c:22692
#define DUK_TOK_DELETE
Definition: duktape.c:3858
#define DUK_HSTRING_SET_ASCII(x)
Definition: duktape.c:6348
#define DUK_ASC_QUESTION
Definition: duktape.c:10821
DUK_LOCAL_DECL void duk__parse_for_stmt(duk_compiler_ctx *comp_ctx, duk_ivalue *res, duk_int_t pc_label_site)
Definition: duktape.c:74231
DUK_LOCAL void duk__format_parts_iso8601(duk_int_t *parts, duk_int_t tzoffset, duk_small_uint_t flags, duk_uint8_t *out_buf)
Definition: duktape.c:33681
DUK_EXTERNAL void duk_push_boolean(duk_hthread *thr, duk_bool_t val)
Definition: duktape.c:23004
#define DUK_REOP_WIPERANGE
Definition: duktape.c:4499
DUK_EXTERNAL void duk_to_primitive(duk_hthread *thr, duk_idx_t idx, duk_int_t hint)
Definition: duktape.c:21520
DUK_LOCAL const char * duk__push_string_tval_readable(duk_hthread *thr, duk_tval *tv, duk_bool_t error_aware)
Definition: duktape.c:25416
DUK_EXTERNAL duk_hthread * duk_get_context(duk_hthread *thr, duk_idx_t idx)
Definition: duktape.c:21068
#define DUK_DCERROR_UNSUPPORTED(thr)
Definition: duktape.c:10293
#define DUK__REGP_A(ins)
Definition: duktape.c:79955
#define DUK__PROP_TYPE_STRIDX
Definition: duktape.c:64546
#define DUK_TOK_ADD_EQ
Definition: duktape.c:3954
DUK_INTERNAL_DECL duk_hcompfunc * duk_get_hcompfunc(duk_hthread *thr, duk_idx_t idx)
Definition: duktape.c:20938
DUK_INTERNAL_DECL duk_hstring * duk_to_property_key_hstring(duk_hthread *thr, duk_idx_t idx)
Definition: duktape.c:21868
DUK_LOCAL_DECL void duk__lookup_active_label(duk_compiler_ctx *comp_ctx, duk_hstring *h_label, duk_bool_t is_break, duk_int_t *out_label_id, duk_int_t *out_label_catch_depth, duk_int_t *out_label_pc, duk_bool_t *out_is_closest)
Definition: duktape.c:71832
DUK_INTERNAL_DECL duk_ret_t duk_bi_array_prototype_iter_shared(duk_context *ctx)
Definition: duktape.c:27518
DUK_INTERNAL_DECL void duk_hbufobj_push_validated_read(duk_hthread *thr, duk_hbufobj *h_bufobj, duk_uint8_t *p, duk_small_uint_t elem_size)
Definition: duktape.c:28219
DUK_INTERNAL_DECL void duk_hobject_define_property_internal(duk_hthread *thr, duk_hobject *obj, duk_hstring *key, duk_small_uint_t flags)
Definition: duktape.c:62729
#define DUK__PI_MINUTE
Definition: duktape.c:32791
DUK_INTERNAL_DECL duk_int_t duk_handle_call_unprotected_nargs(duk_hthread *thr, duk_idx_t nargs, duk_small_uint_t call_flags)
Definition: duktape.c:68475
#define DUK_TOK_LBRACKET
Definition: duktape.c:3918
#define DUK_OP_INSTOF_RC
Definition: duktape.c:3605
DUK_INTERNAL_DECL duk_double_t duk_to_number_m2(duk_hthread *thr)
Definition: duktape.c:21590
#define DUK__REGCONSTP_C(ins)
Definition: duktape.c:79965
DUK_LOCAL DUK_ALWAYS_INLINE void duk__call_callstack_limit_check(duk_hthread *thr)
Definition: duktape.c:66183
DUK_LOCAL_DECL duk_regconst_t duk__alloctemp(duk_compiler_ctx *comp_ctx)
Definition: duktape.c:71044
DUK_INTERNAL_DECL duk_ret_t duk_bi_object_prototype_value_of(duk_context *ctx)
Definition: duktape.c:41608
#define DUK_STRIDX_INFINITY
Definition: duktape.c:1759
#define DUK_HOBJECT_HAS_EXOTIC_PROXYOBJ(h)
Definition: duktape.c:6768
DUK_INTERNAL_DECL duk_ret_t duk_bi_object_constructor_is_extensible(duk_context *ctx)
Definition: duktape.c:41900
#define DUK_DBG_ERR_TOOMANY
Definition: duktape.c:9717
#define DUK_TAG_OBJECT
Definition: duktape.c:1268
#define DUK_HSTRING_HAS_HIDDEN(x)
Definition: duktape.c:6341
#define DUK_HOBJECT_IS_ARRAY(h)
Definition: duktape.c:6710
DUK_LOCAL duk_ret_t duk__math_minmax(duk_hthread *thr, duk_double_t initial, duk__two_arg_func min_max)
Definition: duktape.c:40622
DUK_LOCAL void duk__bi_exp_small(duk__bigint *x, duk_small_int_t b, duk_small_int_t y, duk__bigint *t1, duk__bigint *t2)
Definition: duktape.c:88743
DUK_INTERNAL_DECL int duk_repl_isnan(double x)
Definition: duktape.c:11489
#define DUK_DBG_IB_BUF4
Definition: duktape.c:9698
#define DUK_HCOMPFUNC_GET_FUNCS(heap, h)
Definition: duktape.c:7586
#define DUK_HOBJECT_FLAG_EXOTIC_PROXYOBJ
Definition: duktape.c:6613
#define DUK_STR_INVALID_RANGE
Definition: duktape.c:3308
#define DUK__REGP_C(ins)
Definition: duktape.c:79957
DUK_LOCAL_DECL void duk__emit_1(duk_json_enc_ctx *js_ctx, duk_uint_fast8_t ch)
Definition: duktape.c:38424
DUK_LOCAL void duk__bi_sub(duk__bigint *x, duk__bigint *y, duk__bigint *z)
Definition: duktape.c:88492
#define DUK_TOK_CONST
Definition: duktape.c:3875
#define DUK_HEAPHDR_SET_TYPE_AND_FLAGS(h, tval, fval)
Definition: duktape.c:4763
#define DUK_TAG_BOOLEAN
Definition: duktape.c:1263
#define DUK_HOBJECT_CMASK_SYMBOL
Definition: duktape.c:6685
DUK_EXTERNAL duk_double_t duk_components_to_time(duk_hthread *thr, duk_time_components *comp)
Definition: duktape.c:26049
#define DUK_HOBJECT_HAS_EXOTIC_BEHAVIOR(h)
Definition: duktape.c:6738
#define DUK_RAW_WRITEINC_U32_BE(ptr, val)
Definition: duktape.c:2444
#define DUK_HEAP_STRCACHE_SIZE
Definition: duktape.c:9099
DUK_INTERNAL_DECL duk_hbuffer * duk_hbuffer_alloc(duk_heap *heap, duk_size_t size, duk_small_uint_t flags, void **out_bufdata)
Definition: duktape.c:50025
#define DUK_DBG_IB_TRUE
Definition: duktape.c:9703
#define DUK_STRIDX_JSON
Definition: duktape.c:1621
DUK_EXTERNAL duk_idx_t duk_push_c_lightfunc(duk_hthread *thr, duk_c_function func, duk_idx_t nargs, duk_idx_t length, duk_int_t magic)
Definition: duktape.c:23848
DUK_LOCAL void duk__mark_finalize_list(duk_heap *heap)
Definition: duktape.c:52423
#define DUK_ASC_UC_Z
Definition: duktape.c:10848
#define DUK_HEAP_SET_INTERRUPT_RUNNING(heap)
Definition: duktape.c:8980
#define DUK_STRIDX_OBJ_ENV
Definition: duktape.c:1663
DUK_INTERNAL_DECL duk_int_t duk_pcall_method_flags(duk_hthread *thr, duk_idx_t nargs, duk_small_uint_t call_flags)
Definition: duktape.c:15425
DUK_LOCAL const duk_uint8_t duk__escape_unescaped_table[16]
Definition: duktape.c:36711
DUK_INTERNAL_DECL duk_uint32_t duk_bd_decode_flagged(duk_bitdecoder_ctx *ctx, duk_small_int_t bits, duk_uint32_t def_value)
Definition: duktape.c:99994
DUK_LOCAL_DECL void duk__json_dec_value(duk_json_dec_ctx *js_ctx)
Definition: duktape.c:38241
#define DUK_HBUFOBJ_ELEM_UINT16
Definition: duktape.c:7899
DUK_LOCAL_DECL void duk__parse_do_stmt(duk_compiler_ctx *comp_ctx, duk_ivalue *res, duk_int_t pc_label_site)
Definition: duktape.c:74841
DUK_LOCAL duk_ret_t duk__pcall_method_raw(duk_hthread *thr, void *udata)
Definition: duktape.c:15405
DUK_LOCAL void duk__cbor_decode_error(duk_cbor_decode_context *dec_ctx)
Definition: duktape.c:31428
DUK_LOCAL const char *const duk__symbol_type_strings[4]
Definition: duktape.c:18719
#define DUK_ASSERT_TOP(ctx, n)
Definition: duktape.c:10580
#define DUK__IDX_REFC
Definition: duktape.c:17330
#define DUK__PARSE_STATEMENTS_SLOTS
Definition: duktape.c:69108
#define DUK_LJ_TYPE_RESUME
Definition: duktape.c:8997
DUK_INTERNAL_DECL duk_int_t duk_bi_date_get_local_tzoffset_gmtime(duk_double_t d)
Definition: duktape.c:34606
DUK_LOCAL_DECL void duk__ivalue_toforcedreg(duk_compiler_ctx *comp_ctx, duk_ivalue *x, duk_int_t forced_reg)
Definition: duktape.c:71586
DUK_EXTERNAL duk_bool_t duk_has_prop_string(duk_hthread *thr, duk_idx_t obj_idx, const char *key)
Definition: duktape.c:18005
#define DUK_BW_WRITE_RAW_XUTF8(thr, bw_ctx, cp)
Definition: duktape.c:2675
DUK_INTERNAL_DECL duk_tval * duk_reserve_gap(duk_hthread *thr, duk_idx_t idx_base, duk_idx_t count)
Definition: duktape.c:20156
#define DUK__EMIT_FLAG_NO_SHUFFLE_A
Definition: duktape.c:70139
#define DUK_STRIDX_IGNORE_CASE
Definition: duktape.c:1714
#define DUK_OP_CALL3
Definition: duktape.c:3693
DUK_EXTERNAL duk_ret_t duk_type_error_stash(duk_hthread *thr, const char *fmt,...)
Definition: duktape.c:25180
#define DUK_BIDX_NODEJS_BUFFER_PROTOTYPE
Definition: duktape.c:2336
#define DUK_HEAP_CLEAR_DEBUGGER_PAUSED(heap)
Definition: duktape.c:8988
DUK_LOCAL duk_ret_t duk__pcall_raw(duk_hthread *thr, void *udata)
Definition: duktape.c:15369
DUK_INTERNAL_DECL duk_double_t duk_raw_read_double_be(const duk_uint8_t *p)
Definition: duktape.c:13920
DUK_EXTERNAL duk_ret_t duk_range_error_stash(duk_hthread *thr, const char *fmt,...)
Definition: duktape.c:25168
#define DUK_HOBJECT_CMASK_POINTER
Definition: duktape.c:6688
DUK_EXTERNAL const char * duk_json_encode(duk_hthread *thr, duk_idx_t idx)
Definition: duktape.c:16586
#define DUK_STRIDX_JSON_EXT_NEGINF
Definition: duktape.c:1936
#define DUK_OP_DIV_CC
Definition: duktape.c:3561
#define DUK_TOK_EOF
Definition: duktape.c:3845
#define DUK_OP_UNUSED228
Definition: duktape.c:3743
DUK_INTERNAL const duk_uint16_t duk_unicode_re_ranges_wordchar[8]
Definition: duktape.c:13845
static const duk_uint8_t duk__buffer_proto_from_classnum[]
Definition: duktape.c:27819
#define DUK_ASC_EQUALS
Definition: duktape.c:10819
#define DUK_HOBJECT_SET_PROTOTYPE(heap, h, x)
Definition: duktape.c:7189
#define DUK_HBUFFER_EXTERNAL_GET_SIZE(x)
Definition: duktape.c:8661
DUK_INTERNAL_DECL duk_bool_t duk_hobject_define_property_helper(duk_hthread *thr, duk_uint_t defprop_flags, duk_hobject *obj, duk_hstring *key, duk_idx_t idx_value, duk_hobject *get, duk_hobject *set, duk_bool_t throw_flag)
Definition: duktape.c:63200
#define DUK_TVAL_IS_VALID_TAG(tv)
Definition: duktape.c:1272
#define DUK_OP_ADD_CR
Definition: duktape.c:3544
#define DUK_OP_PREDECP_RC
Definition: duktape.c:3643
#define DUK_HTYPE_OBJECT
Definition: duktape.c:4689
#define DUK_TOK_MINVAL
Definition: duktape.c:3842
DUK_EXTERNAL void duk_debugger_cooperate(duk_hthread *thr)
Definition: duktape.c:17049
#define DUK_HOBJECT_FLAG_EXOTIC_ARRAY
Definition: duktape.c:6609
#define DUK_HOBJECT_FLAG_EXTENSIBLE
Definition: duktape.c:6591
#define DUK_BC_CALL_FLAG_CONSTRUCT
Definition: duktape.c:3791
DUK_NORETURN(DUK_INTERNAL_DECL void duk_err_handle_error(duk_hthread *thr, const char *filename, duk_uint_t line_and_code, const char *msg))
DUK_INTERNAL_DECL duk_hstring * duk_heap_strtable_intern_u32_checked(duk_hthread *thr, duk_uint32_t val)
Definition: duktape.c:56214
#define DUK_REOP_ASSERT_START
Definition: duktape.c:4503
#define DUK_EXEC_ALWAYS_INLINE_PERF
Definition: duktape.c:5916
DUK_LOCAL DUK_ALWAYS_INLINE void duk__base64_encode_fast_3(const duk_uint8_t *src, duk_uint8_t *dst)
Definition: duktape.c:15810
DUK_LOCAL void duk__handle_proxy_for_call(duk_hthread *thr, duk_idx_t idx_func, duk_hproxy *h_proxy, duk_small_uint_t *call_flags)
Definition: duktape.c:66921
#define DUK__BP_MULTIPLICATIVE
Definition: duktape.c:69336
#define DUK_STR_INVALID_REGEXP_FLAGS
Definition: duktape.c:3302
DUK_LOCAL duk_small_uint_t duk__call_setup_act_attempt_tailcall(duk_hthread *thr, duk_small_uint_t call_flags, duk_idx_t idx_func, duk_hobject *func, duk_size_t entry_valstack_bottom_byteoff, duk_size_t entry_valstack_end_byteoff, duk_idx_t *out_nargs, duk_idx_t *out_nregs, duk_size_t *out_vs_min_bytes, duk_activation **out_act)
Definition: duktape.c:67522
DUK_LOCAL void duk__regexp_match_helper(duk_hthread *thr, duk_small_int_t force_global)
Definition: duktape.c:92510
#define DUK_HBUFOBJ_GET_SLICE_BASE(heap, h)
Definition: duktape.c:7923
#define DUK_STRIDX_INT16_ARRAY
Definition: duktape.c:1642
DUK_INTERNAL_DECL duk_small_int_t duk_memcmp_unsafe(const void *s1, const void *s2, duk_size_t len)
Definition: duktape.c:101018
DUK_INTERNAL_DECL void duk_bw_compact(duk_hthread *thr, duk_bufwriter_ctx *bw_ctx)
Definition: duktape.c:100230
#define DUK_RE_QUANTIFIER_INFINITE
Definition: duktape.c:4168
#define DUK_DBG_IB_FALSE
Definition: duktape.c:9704
#define DUK_ASC_0
Definition: duktape.c:10806
#define DUK__EMIT_HSTR(js_ctx, h)
Definition: duktape.c:38417
#define DUK_N2S_FLAG_NO_ZERO_PAD
Definition: duktape.c:11242
#define DUK__RZ_BUFFER()
Definition: duktape.c:54719
DUK_LOCAL void duk__wipe_litcache(duk_heap *heap)
Definition: duktape.c:52885
DUK_LOCAL const char * duk__get_symbol_type_string(duk_hstring *h)
Definition: duktape.c:18780
#define DUK_PROPDESC_IS_ENUMERABLE(p)
Definition: duktape.c:7085
#define DUK_HSTRING_FLAG_STRICT_RESERVED_WORD
Definition: duktape.c:6333
#define DUK_OP_MUL_CR
Definition: duktape.c:3554
DUK_LOCAL duk_hbuffer * duk__hbufobj_fixed_from_argvalue(duk_hthread *thr)
Definition: duktape.c:28314
DUK_INTERNAL_DECL duk_ret_t duk_bi_textencoder_constructor(duk_context *ctx)
Definition: duktape.c:35590
DUK_INTERNAL_DECL duk_ret_t duk_bi_reflect_object_delete_property(duk_context *ctx)
Definition: duktape.c:42370
#define DUK_HOBJECT_SET_ASIZE(h, v)
Definition: duktape.c:7139
#define DUK_ENC_OP_ABC(op, abc)
Definition: duktape.c:3442
#define DUK__CONSTP_BC(ins)
Definition: duktape.c:79962
#define DUK_DBG_CMD_PUTVAR
Definition: duktape.c:9742
DUK_EXTERNAL duk_ret_t duk_error_stash(duk_hthread *thr, duk_errcode_t err_code, const char *fmt,...)
Definition: duktape.c:25156
DUK_LOCAL duk_uint_t duk__api_coerce_d2ui(duk_hthread *thr, duk_idx_t idx, duk_uint_t def_value, duk_bool_t require)
Definition: duktape.c:18850
#define DUK_TVAL_GET_FASTINT_I32(tv)
Definition: duktape.c:1453
#define DUK_TOK_RSHIFT
Definition: duktape.c:3943
DUK_INTERNAL_DECL duk_ret_t duk_bi_date_prototype_to_json(duk_context *ctx)
Definition: duktape.c:34300
DUK_LOCAL duk_double_t duk__cbor_decode_double(duk_cbor_decode_context *dec_ctx)
Definition: duktape.c:32002
#define DUK_OP_PUTPROP_RR
Definition: duktape.c:3618
DUK_LOCAL double duk__log2(double x)
Definition: duktape.c:40719
DUK_LOCAL duk_ret_t duk__set_part_helper(duk_hthread *thr, duk_small_uint_t flags_and_maxnargs)
Definition: duktape.c:33854
#define DUK_OP_POSTDECP_CR
Definition: duktape.c:3652
DUK_EXTERNAL void duk_inspect_callstack_entry(duk_hthread *thr, duk_int_t level)
Definition: duktape.c:17498
#define DUK__PROP_TYPE_STRING
Definition: duktape.c:64545
DUK_LOCAL_DECL void duk__json_dec_pointer(duk_json_dec_ctx *js_ctx)
Definition: duktape.c:37892
#define DUK_PROPDESC_FLAGS_WEC
Definition: duktape.c:6858
DUK_EXTERNAL duk_bool_t duk_get_prop_string(duk_hthread *thr, duk_idx_t obj_idx, const char *key)
Definition: duktape.c:17675
#define DUK_STRIDX_TO_TOK(x)
Definition: duktape.c:3979
DUK_INTERNAL_DECL void duk_bw_insert_raw_slice(duk_hthread *thr, duk_bufwriter_ctx *bw, duk_size_t dst_off, duk_size_t src_off, duk_size_t len)
Definition: duktape.c:100306
#define DUK_RAW_WRITEINC_U16_BE(ptr, val)
Definition: duktape.c:2443
#define DUK_TOK_DIV
Definition: duktape.c:3936
DUK_LOCAL duk_uint8_t * duk__dump_buffer_prop(duk_hthread *thr, duk_uint8_t *p, duk_bufwriter_ctx *bw_ctx, duk_hobject *func, duk_small_uint_t stridx)
Definition: duktape.c:14517
DUK_EXTERNAL duk_idx_t duk_push_bare_object(duk_hthread *thr)
Definition: duktape.c:24530
#define DUK__CHECK_BITMASK(table, cp)
Definition: duktape.c:36659
DUK_INTERNAL_DECL void duk_hbuffer_reset(duk_hthread *thr, duk_hbuffer_dynamic *buf)
Definition: duktape.c:50228
DUK_EXTERNAL const char * duk_push_literal_raw(duk_hthread *thr, const char *str, duk_size_t len)
Definition: duktape.c:23164
DUK_INTERNAL_DECL duk_ret_t duk_bi_math_object_twoarg_shared(duk_context *ctx)
Definition: duktape.c:40903
DUK_INTERNAL_DECL void duk_concat_2(duk_hthread *thr)
Definition: duktape.c:25713
DUK_INTERNAL_DECL duk_bool_t duk_is_whole_get_int32_nonegzero(duk_double_t x, duk_int32_t *ival)
Definition: duktape.c:100762
#define DUK_RETOK_ATOM_START_NONCAPTURE_GROUP
Definition: duktape.c:4143
DUK_LOCAL duk_ret_t duk__array_pop_fastpath(duk_hthread *thr, duk_harray *h_arr)
Definition: duktape.c:26524
DUK_INTERNAL_DECL duk_small_int_t duk_unicode_is_line_terminator(duk_codepoint_t cp)
Definition: duktape.c:13276
DUK_EXTERNAL void * duk_resize_buffer(duk_hthread *thr, duk_idx_t idx, duk_size_t new_size)
Definition: duktape.c:14348
DUK_LOCAL_DECL void duk__json_enc_objarr_entry(duk_json_enc_ctx *js_ctx, duk_idx_t *entry_top)
Definition: duktape.c:39094
#define DUK_STR_NOT_BOOLEAN
Definition: duktape.c:3200
DUK_INTERNAL_DECL duk_ret_t duk_bi_array_constructor_is_array(duk_context *ctx)
Definition: duktape.c:26259
DUK_EXTERNAL const char * duk_base64_encode(duk_hthread *thr, duk_idx_t idx)
Definition: duktape.c:16337
#define DUK_ASC_LC_O
Definition: duktape.c:10869
DUK_LOCAL_DECL duk_int_t duk__get_current_pc(duk_compiler_ctx *comp_ctx)
Definition: duktape.c:70149
DUK_EXTERNAL void * duk_get_buffer(duk_hthread *thr, duk_idx_t idx, duk_size_t *out_size)
Definition: duktape.c:20675
DUK_INTERNAL DUK_COLD void duk_err_range_index(duk_hthread *thr, const char *filename, duk_int_t linenumber, duk_idx_t idx)
Definition: duktape.c:12548
DUK_INTERNAL_DECL duk_hbufobj * duk_hbufobj_alloc(duk_hthread *thr, duk_uint_t hobject_flags)
Definition: duktape.c:56625
DUK_LOCAL_DECL duk_regconst_t duk__expr_toregconst(duk_compiler_ctx *comp_ctx, duk_ivalue *res, duk_small_uint_t rbp_flags)
Definition: duktape.c:74043
DUK_LOCAL duk_bool_t duk__sort_compare_es6(duk_hstring *a, duk_hstring *b, duk__sort_key_t val_b)
Definition: duktape.c:56963
#define DUK_ACT_FLAG_CONSTRUCT_PROXY
Definition: duktape.c:8062
DUK_EXTERNAL void duk_get_prop_desc(duk_hthread *thr, duk_idx_t obj_idx, duk_uint_t flags)
Definition: duktape.c:18161
#define DUK_OP_BXOR_RC
Definition: duktape.c:3585
DUK_EXTERNAL void duk_push_pointer(duk_hthread *thr, void *val)
Definition: duktape.c:23198
DUK_LOCAL duk_uint32_t duk__tval_number_to_arr_idx(duk_tval *tv)
Definition: duktape.c:58008
#define DUK_TOK_BAND_EQ
Definition: duktape.c:3963
#define DUK_HARRAY_SET_LENGTH_WRITABLE(h)
Definition: duktape.c:8471
DUK_INTERNAL_DECL duk_ret_t duk_bi_string_prototype_replace(duk_context *ctx)
Definition: duktape.c:43204
DUK_EXTERNAL void duk_copy(duk_hthread *thr, duk_idx_t from_idx, duk_idx_t to_idx)
Definition: duktape.c:19959
#define DUK_DBG_IB_REPLY
Definition: duktape.c:9690
DUK_EXTERNAL void duk_new(duk_hthread *thr, duk_idx_t nargs)
Definition: duktape.c:15522
#define DUK_STRIDX_INT_VARENV
Definition: duktape.c:1891
#define DUK_DBLUNION_BSWAP64(u)
Definition: duktape.c:571
#define DUK_TVAL_GET_LIGHTFUNC(tv, out_fp, out_flags)
Definition: duktape.c:1466
#define DUK_HEAPHDR_INCREF(thr, h)
Definition: duktape.c:5044
#define DUK_STRIDX_JSON_EXT_NAN
Definition: duktape.c:1930
#define DUK_DBG_CMD_DELBREAK
Definition: duktape.c:9740
DUK_EXTERNAL void duk_set_length(duk_hthread *thr, duk_idx_t idx, duk_size_t len)
Definition: duktape.c:21383
#define DUK_ALLOC_ZEROED(heap, size)
Definition: duktape.c:9169
DUK_LOCAL_DECL void duk__parse_break_or_continue_stmt(duk_compiler_ctx *comp_ctx, duk_ivalue *res)
Definition: duktape.c:74903
DUK_INTERNAL_DECL duk_ret_t duk_bi_math_object_min(duk_context *ctx)
Definition: duktape.c:40922
#define DUK_OP_IN_CR
Definition: duktape.c:3609
#define DUK_STR_CONST_LIMIT
Definition: duktape.c:3320
#define DUK__IDX_TYPE
Definition: duktape.c:17328
#define DUK_STR_INVALID_GETSET_NAME
Definition: duktape.c:3291
#define duk_push_size_t(thr, val)
Definition: duktape.c:5999
DUK_INTERNAL_DECL duk_ret_t duk_bi_thread_constructor(duk_context *ctx)
Definition: duktape.c:44480
#define duk_push_u32(thr, val)
Definition: duktape.c:5993
DUK_LOCAL void duk__base64_encode_helper(const duk_uint8_t *src, duk_size_t srclen, duk_uint8_t *dst)
Definition: duktape.c:15855
DUK_LOCAL DUK_EXEC_ALWAYS_INLINE_PERF void duk__vm_arith_add(duk_hthread *thr, duk_tval *tv_x, duk_tval *tv_y, duk_small_uint_fast_t idx_z)
Definition: duktape.c:77235
DUK_INTERNAL_DECL void duk_heaphdr_refcount_finalize_norz(duk_heap *heap, duk_heaphdr *hdr)
Definition: duktape.c:54385
#define DUK_STRIDX_FLOAT64_ARRAY
Definition: duktape.c:1657
#define DUK_HEAPHDR_IS_OBJECT(h)
Definition: duktape.c:4839
#define duk_js_strict_equals(tv_x, tv_y)
Definition: duktape.c:11149
#define DUK_STRIDX_INPUT
Definition: duktape.c:1903
#define DUK_BIDX_REGEXP_PROTOTYPE
Definition: duktape.c:2304
DUK_INTERNAL_DECL duk_hobjenv * duk_hobjenv_alloc(duk_hthread *thr, duk_uint_t hobject_flags)
Definition: duktape.c:56725
#define DUK_ASSERT_BIDX_VALID(val)
Definition: duktape.c:8214
#define DUK__MAX_CONSTS
Definition: duktape.c:69079
#define DUK_RETOK_ATOM_WHITE
Definition: duktape.c:4137
DUK_INTERNAL_DECL const char * duk_push_string_tval_readable(duk_hthread *thr, duk_tval *tv)
Definition: duktape.c:25500
#define DUK_BIDX_OBJECT_CONSTRUCTOR
Definition: duktape.c:2288
DUK_LOCAL_DECL duk_bool_t duk__handle_put_array_length(duk_hthread *thr, duk_hobject *obj)
Definition: duktape.c:61377
DUK_INTERNAL_DECL duk_tval * duk_hobject_find_array_entry_tval_ptr(duk_heap *heap, duk_hobject *obj, duk_uarridx_t i)
Definition: duktape.c:59381
#define DUK_CALL_FLAG_CALLED_AS_EVAL
Definition: duktape.c:11097
#define DUK_HOBJECT_CLASS_UINT16ARRAY
Definition: duktape.c:6661
DUK_LOCAL duk_uint32_t duk__push_this_obj_len_u32(duk_hthread *thr)
Definition: duktape.c:26140
DUK_LOCAL_DECL void duk__json_dec_array(duk_json_dec_ctx *js_ctx)
Definition: duktape.c:38173
#define DUK__BITPACK_LETTER_LIMIT
Definition: duktape.c:100035
DUK_EXTERNAL duk_idx_t duk_push_error_object_raw(duk_hthread *thr, duk_errcode_t err_code, const char *filename, duk_int_t line, const char *fmt,...)
Definition: duktape.c:24164
#define DUK_OP_GETPROPC_CR
Definition: duktape.c:3724
DUK_LOCAL void duk__putvar_helper(duk_hthread *thr, duk_hobject *env, duk_activation *act, duk_hstring *name, duk_tval *val, duk_bool_t strict)
Definition: duktape.c:85190
#define DUK_HOBJECT_HAS_NEWENV(h)
Definition: duktape.c:6760
DUK_INTERNAL_DECL duk_bool_t duk_js_declvar_activation(duk_hthread *thr, duk_activation *act, duk_hstring *name, duk_tval *val, duk_small_uint_t prop_flags, duk_bool_t is_func_decl)
Definition: duktape.c:85671
DUK_LOCAL void duk__cbor_encode_buffer(duk_cbor_encode_context *enc_ctx)
Definition: duktape.c:31300
#define DUK_OP_RETCONST
Definition: duktape.c:3672
#define DUK_OP_POSTDECP_RC
Definition: duktape.c:3653
DUK_EXTERNAL duk_idx_t duk_push_object(duk_hthread *thr)
Definition: duktape.c:23545
DUK_INTERNAL const duk_uint8_t duk_strings_data[972]
Definition: duktape.c:11607
#define DUK_HOBJECT_CLEAR_ARRAY_PART(h)
Definition: duktape.c:6809
#define DUK_STRIDX_LC_SYMBOL
Definition: duktape.c:1747
#define DUK_HSTRING_HAS_ARRIDX(x)
Definition: duktape.c:6339
DUK_LOCAL_DECL void duk__emit_abc(duk_compiler_ctx *comp_ctx, duk_small_uint_t op, duk_regconst_t abc)
Definition: duktape.c:70632
DUK_LOCAL_DECL duk_int_t duk__cleanup_varmap(duk_compiler_ctx *comp_ctx)
Definition: duktape.c:69660
#define DUK_STRIDX_MINUS_ZERO
Definition: duktape.c:1765
DUK_EXTERNAL const char * duk_get_lstring(duk_hthread *thr, duk_idx_t idx, duk_size_t *out_len)
Definition: duktape.c:20395
#define DUK_OP_GT
Definition: duktape.c:3516
#define DUK_STRIDX_STACK
Definition: duktape.c:1846
#define DUK_HSTRING_ASSERT_VALID(h)
Definition: duktape.c:6466
DUK_LOCAL void duk__free_allocated(duk_heap *heap)
Definition: duktape.c:50450
#define DUK_OP_PUTPROP_CC
Definition: duktape.c:3621
#define DUK_STRIDX_INT_PC2LINE
Definition: duktape.c:1885
#define DUK_STR_FUNC_NAME_REQUIRED
Definition: duktape.c:3292
#define DUK_DBLUNION_IS_ANYINF(u)
Definition: duktape.c:560
#define DUK_VALSTACK_API_ENTRY_MINIMUM
Definition: duktape.c:8051
#define DUK_RAW_WRITEINC_FLOAT_BE(ptr, val)
Definition: duktape.c:2445
DUK_INTERNAL_DECL void duk_raw_write_u16_be(duk_uint8_t *p, duk_uint16_t val)
Definition: duktape.c:13951
DUK_INTERNAL_DECL duk_ret_t duk_bi_typedarray_bytelength_getter(duk_context *ctx)
Definition: duktape.c:30679
DUK_LOCAL_DECL void duk__parse_return_stmt(duk_compiler_ctx *comp_ctx, duk_ivalue *res)
Definition: duktape.c:74974
DUK_INTERNAL void duk_error_throw_from_negative_rc(duk_hthread *thr, duk_ret_t rc)
Definition: duktape.c:49998
#define DUK_HSTRING_SET_PINNED_LITERAL(x)
Definition: duktape.c:6356
#define DUK_OP_SNEQ_CC
Definition: duktape.c:3515
#define DUK_OP_BAND_CR
Definition: duktape.c:3574
DUK_LOCAL void duk__throw_error_from_stash(duk_hthread *thr, duk_errcode_t err_code, const char *fmt, va_list ap)
Definition: duktape.c:25131
#define DUK_HBUFFER_EXTERNAL_SET_DATA_PTR(heap, x, v)
Definition: duktape.c:8704
DUK_LOCAL void duk__push_hstring_readable_unicode(duk_hthread *thr, duk_hstring *h_input, duk_small_uint_t maxchars)
Definition: duktape.c:25366
DUK_INTERNAL_DECL duk_ret_t duk_bi_cbor_decode(duk_context *ctx)
Definition: duktape.c:32637
#define DUK_DBG_CMD_DUMPHEAP
Definition: duktape.c:9747
DUK_INTERNAL_DECL int duk_repl_isfinite(double x)
Definition: duktape.c:11478
DUK_EXTERNAL void duk_push_current_function(duk_hthread *thr)
Definition: duktape.c:23334
#define DUK_TOK_INSTANCEOF
Definition: duktape.c:3866
DUK_LOCAL const duk_small_uint_t duk__object_keys_enum_flags[4]
Definition: duktape.c:41929
#define DUK_LJ_TYPE_BREAK
Definition: duktape.c:8998
#define DUK_LFUNC_NARGS_MIN
Definition: duktape.c:1538
DUK_INTERNAL_DECL duk_small_uint_t duk_double_signbit(duk_double_t x)
Definition: duktape.c:100695
#define DUK_OP_SEQ_RR
Definition: duktape.c:3507
void *(* duk_mem_getptr)(duk_heap *heap, void *ud)
Definition: duktape.c:9166
DUK_EXTERNAL const char * duk_require_string(duk_hthread *thr, duk_idx_t idx)
Definition: duktape.c:20533
#define DUK_PROPDESC_FLAG_ENUMERABLE
Definition: duktape.c:6837
DUK_INTERNAL_DECL duk_uint32_t duk_bd_decode_varuint(duk_bitdecoder_ctx *ctx)
Definition: duktape.c:100008
DUK_EXTERNAL duk_idx_t duk_push_array(duk_hthread *thr)
Definition: duktape.c:23555
const duk_uint16_t duk_unicode_re_canon_lookup[65536]
Definition: duktape.c:94080
DUK_EXTERNAL duk_ret_t duk_generic_error_stash(duk_hthread *thr, const char *fmt,...)
Definition: duktape.c:25160
#define DUK__SNEQ_BODY(barg, carg)
DUK_EXTERNAL duk_bool_t duk_is_array(duk_hthread *thr, duk_idx_t idx)
Definition: duktape.c:22786
DUK_INTERNAL_DECL void duk_push_hstring(duk_hthread *thr, duk_hstring *h)
Definition: duktape.c:24540
DUK_INTERNAL_DECL void duk_pop_undefined(duk_hthread *thr)
Definition: duktape.c:24752
#define DUK_ISPEC_VALUE
Definition: duktape.c:4269
#define DUK_HOBJECT_HAS_BUFOBJ(h)
Definition: duktape.c:6752
DUK_INTERNAL_DECL duk_uint32_t duk_heap_hashstring(duk_heap *heap, const duk_uint8_t *str, duk_size_t len)
Definition: duktape.c:52015
DUK_LOCAL void duk__array_sort_swap(duk_hthread *thr, duk_int_t l, duk_int_t r)
Definition: duktape.c:26838
#define DUK_HCOMPFUNC_SET_BYTECODE(heap, h, v)
Definition: duktape.c:7592
DUK_EXTERNAL void duk_set_finalizer(duk_hthread *thr, duk_idx_t idx)
Definition: duktape.c:18628
#define DUK_STR_FUNC_STMT_NOT_ALLOWED
Definition: duktape.c:3287
DUK_INTERNAL_DECL duk_ret_t duk_bi_array_prototype_reduce_shared(duk_context *ctx)
Definition: duktape.c:27643
DUK_INTERNAL_DECL void duk_hstring_refzero(duk_hthread *thr, duk_hstring *h)
Definition: duktape.c:54819
DUK_INTERNAL_DECL duk_ret_t duk_bi_global_object_encode_uri(duk_context *ctx)
Definition: duktape.c:37335
#define DUK_DBLUNION_GET_SIGNBIT(u)
Definition: duktape.c:624
#define DUK_STRIDX_INT8_ARRAY
Definition: duktape.c:1633
#define DUK_HEAPHDR_CLEAR_REACHABLE(h)
Definition: duktape.c:4783
DUK_INTERNAL_DECL void * duk_get_buffer_data_raw(duk_hthread *thr, duk_idx_t idx, duk_size_t *out_size, void *def_ptr, duk_size_t def_len, duk_bool_t throw_flag, duk_bool_t *out_isbuffer)
Definition: duktape.c:20714
DUK_INTERNAL_DECL int duk_repl_fpclassify(double x)
Definition: duktape.c:11438
DUK_EXTERNAL duk_bool_t duk_is_ecmascript_function(duk_hthread *thr, duk_idx_t idx)
Definition: duktape.c:22856
#define DUK__SM_MINUS
Definition: duktape.c:32820
#define DUK_OP_GE_CR
Definition: duktape.c:3523
#define DUK_PROPDESC_IS_ACCESSOR(p)
Definition: duktape.c:7087
#define DUK_HEAP_ALLOC_FAIL_MARKANDSWEEP_EMERGENCY_LIMIT
Definition: duktape.c:9192
DUK_LOCAL duk_uint32_t duk__to_property_key(duk_hthread *thr, duk_idx_t idx, duk_hstring **out_h)
Definition: duktape.c:58057
#define DUK_TVAL_GET_BOOLEAN(tv)
Definition: duktape.c:1448
DUK_LOCAL duk_bool_t duk__base64_decode_helper(const duk_uint8_t *src, duk_size_t srclen, duk_uint8_t *dst, duk_uint8_t **out_dst_final)
Definition: duktape.c:15990
#define DUK_OP_MOD_RC
Definition: duktape.c:3565
DUK_INTERNAL_DECL duk_ret_t duk_bi_nodejs_buffer_is_buffer(duk_context *ctx)
Definition: duktape.c:29869
#define DUK_OP_BASL_CR
Definition: duktape.c:3589
DUK_INTERNAL_DECL duk_hstring * duk_push_this_coercible_to_string(duk_hthread *thr)
Definition: duktape.c:23276
#define DUK_OP_CALL5
Definition: duktape.c:3695
#define DUK_ASC_LC_E
Definition: duktape.c:10859
DUK_LOCAL void duk__regexp_emit_range(duk_re_compiler_ctx *re_ctx, duk_codepoint_t r1, duk_codepoint_t r2)
Definition: duktape.c:90808
#define DUK__DELPROP_BODY(barg, carg)
#define DUK_TOK_SUB_EQ
Definition: duktape.c:3955
DUK_LOCAL void duk__handle_safe_call_shared_unwind(duk_hthread *thr, duk_idx_t idx_retbase, duk_idx_t num_stack_rets, duk_int_t entry_call_recursion_depth, duk_hthread *entry_curr_thread, duk_instr_t **entry_ptr_curr_pc)
Definition: duktape.c:68661
static duk_uint16_t duk__buffer_elemtype_copy_compatible[9]
Definition: duktape.c:27861
#define DUK_STRIDX_UC_POINTER
Definition: duktape.c:1672
#define DUK__PARSE_EXPR_SLOTS
Definition: duktape.c:69109
#define DUK_HCOMPFUNC_GET_CODE_BASE(heap, h)
Definition: duktape.c:7619
#define DUK_OP_CSREG
Definition: duktape.c:3684
DUK_EXTERNAL duk_bool_t duk_get_prop_lstring(duk_hthread *thr, duk_idx_t obj_idx, const char *key, duk_size_t key_len)
Definition: duktape.c:17684
DUK_LOCAL_DECL void duk__parse_throw_stmt(duk_compiler_ctx *comp_ctx, duk_ivalue *res)
Definition: duktape.c:75077
#define DUK_DBG_ERR_NOTFOUND
Definition: duktape.c:9718
DUK_LOCAL void duk__init_object_parts(duk_heap *heap, duk_uint_t hobject_flags, duk_hobject *obj)
Definition: duktape.c:56496
DUK_LOCAL void duk__mark_hobject(duk_heap *heap, duk_hobject *h)
Definition: duktape.c:52079
DUK_INTERNAL_DECL duk_ret_t duk_bi_error_prototype_linenumber_setter(duk_context *ctx)
Definition: duktape.c:36178
DUK_LOCAL DUK_INLINE void duk__refcount_refzero_hobject(duk_heap *heap, duk_hobject *obj, duk_bool_t skip_free_pending)
Definition: duktape.c:54490
DUK_LOCAL DUK_INLINE void duk__refcount_refzero_hbuffer(duk_heap *heap, duk_hbuffer *buf)
Definition: duktape.c:54637
DUK_INTERNAL_DECL void * duk_heap_mem_alloc(duk_heap *heap, duk_size_t size)
Definition: duktape.c:53631
#define DUK_BC_DECLVAR_FLAG_FUNC_DECL
Definition: duktape.c:3785
#define DUK_RE_FLAG_IGNORE_CASE
Definition: duktape.c:4510
DUK_LOCAL duk_uint32_t duk__cbor_decode_read_u32(duk_cbor_decode_context *dec_ctx)
Definition: duktape.c:31477
DUK_INTERNAL_DECL void * duk_hbuffer_get_dynalloc_ptr(duk_heap *heap, void *ud)
Definition: duktape.c:50141
DUK_INTERNAL_DECL duk_bool_t duk_double_is_nan_or_zero(duk_double_t x)
Definition: duktape.c:100628
DUK_LOCAL_DECL void duk__check_arguments_map_for_delete(duk_hthread *thr, duk_hobject *obj, duk_hstring *key, duk_propdesc *temp_desc)
Definition: duktape.c:59707
DUK_INTERNAL_DECL void duk_hobject_realloc_props(duk_hthread *thr, duk_hobject *obj, duk_uint32_t new_e_size, duk_uint32_t new_a_size, duk_uint32_t new_h_size, duk_bool_t abandon_array)
Definition: duktape.c:58529
DUK_INTERNAL_DECL duk_ret_t duk_bi_error_prototype_filename_getter(duk_context *ctx)
Definition: duktape.c:36103
#define duk_memset(dst, val, len)
Definition: duktape.c:3072
DUK_INTERNAL_DECL duk_ret_t duk_bi_date_prototype_get_shared(duk_context *ctx)
Definition: duktape.c:34366
#define DUK_STRIDX_TO_ISO_STRING
Definition: duktape.c:1705
#define DUK_BW_WRITE_ENSURE_U8_2(thr, bw_ctx, val1, val2)
Definition: duktape.c:2775
#define DUK__ITER_FILTER
Definition: duktape.c:27511
#define DUK_OP_UNUSED243
Definition: duktape.c:3758
#define DUK_PROPDESC_IS_WRITABLE(p)
Definition: duktape.c:7084
#define DUK_DBG_CMD_BASICINFO
Definition: duktape.c:9731
#define DUK_HOBJECT_E_SET_VALUE_GETTER(heap, h, i, v)
Definition: duktape.c:7032
DUK_LOCAL double duk__acos(double x)
Definition: duktape.c:40796
DUK_LOCAL duk_codepoint_t duk__inp_get_cp(duk_re_matcher_ctx *re_ctx, const duk_uint8_t **sp)
Definition: duktape.c:91924
#define DUK_HOBJECT_IS_PROXY(h)
Definition: duktape.c:6721
#define DUK_BW_INSERT_ENSURE_SLICE(thr, bw, dst_off, src_off, len)
Definition: duktape.c:2873
#define DUK_TVAL_SET_BOOLEAN(tv, val)
Definition: duktape.c:1302
DUK_LOCAL_DECL void duk__convert_to_func_template(duk_compiler_ctx *comp_ctx)
Definition: duktape.c:69710
DUK_INTERNAL_DECL duk_ret_t duk_bi_regexp_prototype_flags(duk_context *ctx)
Definition: duktape.c:42585
DUK_INTERNAL_DECL void duk_push_c_function_builtin(duk_hthread *thr, duk_c_function func, duk_int_t nargs)
Definition: duktape.c:23821
#define DUK_HBUFFER_GET_DATA_PTR(heap, x)
Definition: duktape.c:8727
#define DUK_HOBJECT_INCREF(thr, h)
Definition: duktape.c:5051
#define DUK_TOK_TYPEOF
Definition: duktape.c:3873
DUK_INTERNAL_DECL duk_uint8_t * duk_bw_insert_raw_area(duk_hthread *thr, duk_bufwriter_ctx *bw, duk_size_t off, duk_size_t len)
Definition: duktape.c:100362
DUK_INTERNAL_DECL void duk_seal_freeze_raw(duk_hthread *thr, duk_idx_t obj_idx, duk_bool_t is_freeze)
Definition: duktape.c:18284
#define DUK_TVAL_STRING_IS_SYMBOL(tv)
Definition: duktape.c:1526
#define DUK_STR_CONSTRUCT_ONLY
Definition: duktape.c:3190
DUK_LOCAL void duk__cbor_decode_value(duk_cbor_decode_context *dec_ctx)
Definition: duktape.c:32404
#define DUK_ASC_GRAVE
Definition: duktape.c:10854
#define DUK_BW_WRITE_ENSURE_BYTES(thr, bw_ctx, valptr, valsz)
Definition: duktape.c:2812
DUK_LOCAL duk_codepoint_t duk__hexval(duk_codepoint_t x)
Definition: duktape.c:86333
#define DUK_OP_BAND_RR
Definition: duktape.c:3573
#define DUK_S2N_FLAG_ALLOW_INF
Definition: duktape.c:11280
#define DUK_REALLOC(heap, ptr, newsize)
Definition: duktape.c:9170
DUK_INTERNAL_DECL duk_bool_t duk_is_whole_get_int32(duk_double_t x, duk_int32_t *ival)
Definition: duktape.c:100783
#define DUK_HOBJECT_E_GET_VALUE_BASE(heap, h)
Definition: duktape.c:6941
#define DUK_STRIDX_CONFIGURABLE
Definition: duktape.c:1687
DUK_INTERNAL_DECL duk_ret_t duk_bi_typedarray_constructor(duk_context *ctx)
Definition: duktape.c:28461
DUK_EXTERNAL void duk_suspend(duk_hthread *thr, duk_thread_state *state)
Definition: duktape.c:17158
#define DUK_STR_INVALID_THROW
Definition: duktape.c:3285
#define DUK_STR_INVALID_LVALUE
Definition: duktape.c:3276
#define DUK_ACT_GET_FUNC(act)
Definition: duktape.c:8065
DUK_INTERNAL const duk_c_function duk_bi_native_functions[185]
Definition: duktape.c:11662
#define DUK__INTERNAL_ERROR(msg)
Definition: duktape.c:79982
DUK_EXTERNAL duk_c_function duk_get_c_function(duk_hthread *thr, duk_idx_t idx)
Definition: duktape.c:20988
#define DUK_OP_MPUTARR
Definition: duktape.c:3712
#define DUK__EMIT_FLAG_A_IS_SOURCE
Definition: duktape.c:70142
#define DUK_HSTRING_SET_BYTELEN(x, v)
Definition: duktape.c:6411
DUK_INTERNAL_DECL duk_ret_t duk_bi_object_constructor_create(duk_context *ctx)
Definition: duktape.c:41451
#define DUK_OP_PREINCP_RC
Definition: duktape.c:3638
DUK_LOCAL void duk__comp_recursion_decrease(duk_compiler_ctx *comp_ctx)
Definition: duktape.c:69471
#define DUK__BP_MEMBER
Definition: duktape.c:69340
#define DUK_STRIDX_INT_BYTECODE
Definition: duktape.c:1873
DUK_LOCAL duk_double_t duk__toint32_touint32_helper(duk_double_t x, duk_bool_t is_toint32)
Definition: duktape.c:82764
DUK_LOCAL void duk__reconfig_valstack_ecma_catcher(duk_hthread *thr, duk_activation *act)
Definition: duktape.c:77980
#define DUK_HBUFFER_FLAG_DYNAMIC
Definition: duktape.c:8584
#define DUK_TVAL_SET_LIGHTFUNC(tv, fp, flags)
Definition: duktape.c:1400
DUK_EXTERNAL void duk_insert(duk_hthread *thr, duk_idx_t to_idx)
Definition: duktape.c:19840
DUK_INTERNAL_DECL duk_double_t duk_js_tonumber(duk_hthread *thr, duk_tval *tv)
Definition: duktape.c:82646
DUK_INTERNAL_DECL duk_idx_t duk_unpack_array_like(duk_hthread *thr, duk_idx_t idx)
Definition: duktape.c:24909
#define DUK__PM_TZMINUTE
Definition: duktape.c:32806
#define DUK_TOK_BOR
Definition: duktape.c:3945
#define DUK_TVAL_CHKFAST_INPLACE_FAST(tv)
Definition: duktape.c:1345
DUK_INTERNAL_DECL void * duk_push_fixed_buffer_zero(duk_hthread *thr, duk_size_t len)
Definition: duktape.c:24228
DUK_LOCAL duk_ret_t duk__construct_from_codepoints(duk_hthread *thr, duk_bool_t nonbmp)
Definition: duktape.c:42839
DUK_LOCAL void duk__handle_yield(duk_hthread *thr, duk_hthread *resumer, duk_tval *tv_val_unstable)
Definition: duktape.c:78234
#define DUK_HOBJECT_E_GET_VALUE(heap, h, i)
Definition: duktape.c:7005
#define DUK_HOBJECT_SET_NAMEBINDING(h)
Definition: duktape.c:6788
#define DUK_OP_CALL6
Definition: duktape.c:3696
DUK_LOCAL_DECL void duk__check_arguments_map_for_put(duk_hthread *thr, duk_hobject *obj, duk_hstring *key, duk_propdesc *temp_desc, duk_bool_t throw_flag)
Definition: duktape.c:59660
DUK_INTERNAL_DECL void duk_push_lightfunc_name_raw(duk_hthread *thr, duk_c_function func, duk_small_uint_t lf_flags)
Definition: duktape.c:25268
DUK_LOCAL void duk__append_range_atom_matcher(duk_re_compiler_ctx *re_ctx, duk_small_uint_t re_op, const duk_uint16_t *ranges, duk_small_uint_t count)
Definition: duktape.c:91003
#define DUK_TOK_NEQ
Definition: duktape.c:3930
#define DUK_TOK_ARSHIFT
Definition: duktape.c:3942
DUK_INTERNAL_DECL duk_ret_t duk_bi_global_object_escape(duk_context *ctx)
Definition: duktape.c:37346
DUK_LOCAL void duk__sweep_heap(duk_heap *heap, duk_small_uint_t flags, duk_size_t *out_count_keep)
Definition: duktape.c:52703
#define DUK_NUM_BUILTINS
Definition: duktape.c:2337
DUK_EXTERNAL duk_int_t duk_pcall_prop(duk_hthread *thr, duk_idx_t obj_idx, duk_idx_t nargs)
Definition: duktape.c:15465
#define DUK_OP_UNUSED247
Definition: duktape.c:3762
#define DUK_HSTRING_SET_HIDDEN(x)
Definition: duktape.c:6351
#define DUK_HSTRING_HAS_STRICT_RESERVED_WORD(x)
Definition: duktape.c:6343
DUK_INTERNAL_DECL void duk_pop_3_nodecref_unsafe(duk_hthread *thr)
Definition: duktape.c:24843
#define DUK_TOK_PERIOD
Definition: duktape.c:3922
#define DUK_HOBJECT_ASSERT_VALID(h)
Definition: duktape.c:6877
#define DUK__BP_EOF
Definition: duktape.c:69321
#define DUK_STR_INVALID_DESCRIPTOR
Definition: duktape.c:3249
#define DUK_TVAL_SET_UNDEFINED_UPDREF
Definition: duktape.c:5418
#define DUK_STRIDX_INT_MAP
Definition: duktape.c:1888
#define DUK_ASC_TILDE
Definition: duktape.c:10884
#define DUK_HTHREAD_STRING_EMPTY_STRING(thr)
Definition: duktape.c:1626
#define DUK_HEAPHDR_FLAG_FINALIZABLE
Definition: duktape.c:4683
#define DUK_STR_REGEXP_COMPILER_RECURSION_LIMIT
Definition: duktape.c:3322
#define DUK_STR_NOT_NUMBER
Definition: duktape.c:3201
DUK_LOCAL_DECL duk_bool_t duk__expr_is_empty(duk_compiler_ctx *comp_ctx)
Definition: duktape.c:72412
DUK_LOCAL double duk__tan(double x)
Definition: duktape.c:40826
DUK_EXTERNAL void duk_pop_2(duk_hthread *thr)
Definition: duktape.c:24804
#define DUK_HOBJECT_SET_HSIZE(h, v)
Definition: duktape.c:7145
DUK_EXTERNAL void duk_concat(duk_hthread *thr, duk_idx_t count)
Definition: duktape.c:25701
#define DUK_STRIDX_CALLEE
Definition: duktape.c:1783
DUK_INTERNAL DUK_COLD void duk_default_fatal_handler(void *udata, const char *msg)
Definition: duktape.c:12599
DUK_LOCAL_DECL void duk__parse_var_decl(duk_compiler_ctx *comp_ctx, duk_ivalue *res, duk_small_uint_t expr_flags, duk_regconst_t *out_reg_varbind, duk_regconst_t *out_rc_varname)
Definition: duktape.c:74134
#define DUK_CAT_HAS_CATCH_ENABLED(c)
Definition: duktape.c:8098
#define DUK_HTHREAD_STATE_YIELDED
Definition: duktape.c:8155
DUK_INTERNAL_DECL void duk_push_this_check_object_coercible(duk_hthread *thr)
Definition: duktape.c:23259
#define DUK_HOBJECT_HASHIDX_DELETED
Definition: duktape.c:7090
#define DUK_ASSERT_LJSTATE_UNSET(heap)
Definition: duktape.c:9256
#define DUK_OP_UNUSED220
Definition: duktape.c:3735
#define DUK_BC_B_MAX
Definition: duktape.c:3463
DUK_LOCAL_DECL void duk__ivalue_toplain_raw(duk_compiler_ctx *comp_ctx, duk_ivalue *x, duk_regconst_t forced_reg)
Definition: duktape.c:71315
#define DUK_CALL_FLAG_TAILCALL
Definition: duktape.c:11095
DUK_LOCAL_DECL void duk__json_dec_object(duk_json_dec_ctx *js_ctx)
Definition: duktape.c:38091
DUK_INTERNAL const duk_uint16_t duk_hex_enctab[256]
Definition: duktape.c:14102
DUK_EXTERNAL duk_ret_t duk_syntax_error_stash(duk_hthread *thr, const char *fmt,...)
Definition: duktape.c:25176
#define DUK__EMIT_FLAG_B_IS_TARGET
Definition: duktape.c:70143
DUK_LOCAL_DECL void duk__emit_load_int32_noshuffle(duk_compiler_ctx *comp_ctx, duk_regconst_t reg, duk_int32_t val)
Definition: duktape.c:70703
DUK_LOCAL duk_hstring * duk__internbuffer(duk_lexer_ctx *lex_ctx, duk_idx_t valstack_idx)
Definition: duktape.c:86266
DUK_LOCAL DUK_EXEC_ALWAYS_INLINE_PERF void duk__vm_arith_unary_op(duk_hthread *thr, duk_uint_fast_t idx_src, duk_uint_fast_t idx_dst, duk_small_uint_fast_t opcode)
Definition: duktape.c:77638
DUK_LOCAL duk_uint8_t duk__days_in_month[12]
Definition: duktape.c:33129
DUK_LOCAL void duk__bi_twoexp(duk__bigint *x, duk_small_int_t y)
Definition: duktape.c:88731
#define DUK__IDX_PBYTES
Definition: duktape.c:17333
DUK_EXTERNAL const char * duk_push_sprintf(duk_hthread *thr, const char *fmt,...)
Definition: duktape.c:23487
#define DUK_TVAL_GET_NUMBER(tv)
Definition: duktape.c:1459
DUK_LOCAL duk_double_t duk__make_day(duk_double_t year, duk_double_t month, duk_double_t day)
Definition: duktape.c:33246
DUK_EXTERNAL duk_ret_t duk_eval_error_stash(duk_hthread *thr, const char *fmt,...)
Definition: duktape.c:25164
DUK_EXTERNAL void duk_push_true(duk_hthread *thr)
Definition: duktape.c:23015
#define DUK_DBG_IB_POINTER
Definition: duktape.c:9707
#define DUK_HOBJECT_GET_CLASS_NUMBER(h)
Definition: duktape.c:6619
#define duk_xdef_prop_index_wec(thr, obj_idx, arr_idx)
Definition: duktape.c:6207
#define DUK_UNICODE_CP_REPLACEMENT_CHARACTER
Definition: duktape.c:10744
DUK_EXTERNAL void duk_push_undefined(duk_hthread *thr)
Definition: duktape.c:22983
#define DUK_OP_NEQ_RR
Definition: duktape.c:3502
#define DUK_OP_BASR_CC
Definition: duktape.c:3601
#define DUK_LFUNC_FLAGS_GET_NARGS(lf_flags)
Definition: duktape.c:1534
#define DUK_ASC_UC_N
Definition: duktape.c:10836
DUK_INTERNAL_DECL void duk_set_top_unsafe(duk_hthread *thr, duk_idx_t idx)
Definition: duktape.c:19201
DUK_LOCAL duk_uint32_t duk__to_new_array_length_checked(duk_hthread *thr, duk_tval *tv)
Definition: duktape.c:61126
DUK_LOCAL void duk__dragon4_scale(duk__numconv_stringify_ctx *nc_ctx)
Definition: duktape.c:89030
DUK_INTERNAL_DECL duk_hobject * duk_hobject_get_varmap(duk_hthread *thr, duk_hobject *obj)
Definition: duktape.c:59539
DUK_LOCAL void duk__preallocate_env_entries(duk_hthread *thr, duk_hobject *varmap, duk_hobject *env)
Definition: duktape.c:84422
#define DUK__PACK_ARGS(classnum, protobidx, elemtype, elemshift, istypedarray)
Definition: duktape.c:23913
#define DUK_LFUNC_FLAGS_GET_LENGTH(lf_flags)
Definition: duktape.c:1533
#define DUK_LJ_TYPE_NORMAL
Definition: duktape.c:9001
#define DUK__MAX_RE_DECESC_DIGITS
Definition: duktape.c:85786
#define DUK_ASC_4
Definition: duktape.c:10810
#define DUK_FREE_RAW(heap, ptr)
Definition: duktape.c:9135
#define DUK_BIDX_NATIVE_FUNCTION_PROTOTYPE
Definition: duktape.c:2292
#define DUK_HOBJECT_CLEAR_CONSTRUCTABLE(h)
Definition: duktape.c:6800
#define DUK_OP_CSVAR_RC
Definition: duktape.c:3688
static duk_uint16_t duk__date_magics[]
Definition: duktape.c:34036
#define DUK__EMIT_FLAG_RESERVE_JUMPSLOT
Definition: duktape.c:70146
DUK_INTERNAL_DECL void duk_insert_undefined(duk_hthread *thr, duk_idx_t idx)
Definition: duktape.c:19877
#define DUK__REPLACE_TOP_A_BREAK()
#define DUK_ASC_UC_F
Definition: duktape.c:10828
DUK_LOCAL duk_bool_t duk__abandon_array_slow_check_required(duk_uint32_t arr_idx, duk_uint32_t old_size)
Definition: duktape.c:58243
#define DUK_OP_GETPROP_CR
Definition: duktape.c:3614
#define DUK_TOK_MOD_EQ
Definition: duktape.c:3958
DUK_LOCAL void duk__arraybuffer_plain_slice(duk_hthread *thr, duk_hbuffer *h_val)
Definition: duktape.c:29666
DUK_INTERNAL_DECL duk_ucodepoint_t duk_hstring_char_code_at_raw(duk_hthread *thr, duk_hstring *h, duk_uint_t pos, duk_bool_t surrogate_aware)
Definition: duktape.c:64280
DUK_LOCAL duk_int_t duk__hobject_alloc_entry_checked(duk_hthread *thr, duk_hobject *obj, duk_hstring *key)
Definition: duktape.c:59406
DUK_LOCAL double duk__cbrt(double x)
Definition: duktape.c:40695
DUK_LOCAL_DECL void duk__json_enc_fastint_tval(duk_json_enc_ctx *js_ctx, duk_tval *tv)
Definition: duktape.c:38763
#define DUK_OP_PUTPROP_CR
Definition: duktape.c:3619
#define DUK_TOK_RETURN
Definition: duktape.c:3868
DUK_INTERNAL_DECL void duk_push_lightfunc_name(duk_hthread *thr, duk_tval *tv)
Definition: duktape.c:25289
#define DUK_ERROR_RANGE_INVALID_LENGTH(thr)
Definition: duktape.c:10328
DUK_EXTERNAL duk_uint_t duk_opt_uint(duk_hthread *thr, duk_idx_t idx, duk_uint_t def_value)
Definition: duktape.c:20386
DUK_INTERNAL_DECL duk_codepoint_t duk_unicode_re_canonicalize_char(duk_hthread *thr, duk_codepoint_t cp)
Definition: duktape.c:13783
#define DUK_CALL_FLAG_DIRECT_EVAL
Definition: duktape.c:11099
#define DUK_TVAL_GET_HEAPHDR(tv)
Definition: duktape.c:1476
#define DUK_STRIDX_ENV
Definition: duktape.c:1912
#define DUK_HTHREAD_STRING_HEX(thr)
Definition: duktape.c:1917
#define DUK_TVAL_DECREF_NORZ(thr, tv)
Definition: duktape.c:5043
DUK_LOCAL_DECL duk_bool_t duk__handle_put_array_length_smaller(duk_hthread *thr, duk_hobject *obj, duk_uint32_t old_len, duk_uint32_t new_len, duk_bool_t force_flag, duk_uint32_t *out_result_len)
Definition: duktape.c:61184
#define DUK_STRIDX_VALUE_OF
Definition: duktape.c:1699
DUK_EXTERNAL duk_bool_t duk_put_global_lstring(duk_hthread *thr, const char *key, duk_size_t key_len)
Definition: duktape.c:18466
DUK_LOCAL void duk__append_u16_list(duk_re_compiler_ctx *re_ctx, const duk_uint16_t *values, duk_uint32_t count)
Definition: duktape.c:90628
#define DUK_STRIDX_END_RESERVED
Definition: duktape.c:2084
DUK_INTERNAL_DECL duk_bool_t duk_double_same_sign(duk_double_t x, duk_double_t y)
Definition: duktape.c:100711
#define DUK_RAW_WRITEINC_XUTF8(ptr, val)
Definition: duktape.c:2447
DUK_LOCAL void duk__set_parts_from_args(duk_hthread *thr, duk_double_t *dparts, duk_idx_t nargs)
Definition: duktape.c:33979
DUK_LOCAL duk_hobject * duk__resolve_target_func_and_this_binding(duk_hthread *thr, duk_idx_t idx_func, duk_small_uint_t *call_flags)
Definition: duktape.c:67259
#define DUK__READABLE_STRING_MAXCHARS
Definition: duktape.c:25358
DUK_INTERNAL_DECL duk_ret_t duk_bi_date_prototype_tostring_shared(duk_context *ctx)
Definition: duktape.c:34284
DUK_INTERNAL_DECL duk_ret_t duk_bi_object_prototype_to_string(duk_context *ctx)
Definition: duktape.c:41365
#define DUK_STRIDX_LC_OBJECT
Definition: duktape.c:1750
#define DUK_CALL_FLAG_CONSTRUCT
Definition: duktape.c:11096
#define DUK_OP_CALL1
Definition: duktape.c:3691
#define DUK__FUNC_FLAG_USE_PREVTOKEN
Definition: duktape.c:69303
DUK_INTERNAL_DECL void duk_heap_insert_into_heap_allocated(duk_heap *heap, duk_heaphdr *hdr)
Definition: duktape.c:53979
#define DUK_OP_LDCONST
Definition: duktape.c:3483
DUK_LOCAL void duk__decref_tvals_norz(duk_hthread *thr, duk_tval *tv, duk_idx_t count)
Definition: duktape.c:54194
DUK_LOCAL_DECL void duk__settemp_checkmax(duk_compiler_ctx *comp_ctx, duk_regconst_t temp_next)
Definition: duktape.c:71048
#define DUK_ASC_UNDERSCORE
Definition: duktape.c:10853
#define DUK_BC_CALL_FLAG_CALLED_AS_EVAL
Definition: duktape.c:3792
#define DUK_DBG_CMD_GETHEAPOBJINFO
Definition: duktape.c:9750
DUK_INTERNAL_DECL duk_bool_t duk_unicode_is_utf8_compatible(const duk_uint8_t *buf, duk_size_t len)
Definition: duktape.c:13048
#define DUK_TAG_MIN
Definition: duktape.c:1256
#define DUK_HOBJECT_E_GET_FLAGS(heap, h, i)
Definition: duktape.c:7013
#define DUK_TVAL_SET_I32_UPDREF
Definition: duktape.c:5429
DUK_LOCAL DUK_EXEC_NOINLINE_PERF void duk__handle_op_initenum(duk_hthread *thr, duk_uint_fast32_t ins)
Definition: duktape.c:79776
#define DUK_LFUNC_MAGIC_MAX
Definition: duktape.c:1543
#define DUK_HOBJECT_HAS_NATFUNC(h)
Definition: duktape.c:6750
DUK_LOCAL void duk__clear_finalize_list_flags(duk_heap *heap)
Definition: duktape.c:52591
struct duk_strtab_entry duk_strtab_entry
Definition: duktape.c:866
DUK_EXTERNAL void duk_push_new_target(duk_hthread *thr)
Definition: duktape.c:23294
#define DUK_RETOK_ASSERT_END
Definition: duktape.c:4128
DUK_LOCAL void duk__dragon4_prepare(duk__numconv_stringify_ctx *nc_ctx)
Definition: duktape.c:88880
#define DUK_STRIDX_TO_JSON
Definition: duktape.c:1828
#define DUK_REOP_ASSERT_NOT_WORD_BOUNDARY
Definition: duktape.c:4506
DUK_LOCAL DUK_ALWAYS_INLINE void duk__call_c_recursion_limit_check(duk_hthread *thr)
Definition: duktape.c:66145
#define DUK_RAW_READ_U16_BE(ptr)
Definition: duktape.c:2451
DUK_INTERNAL_DECL void duk_hthread_catcher_free(duk_hthread *thr, duk_catcher *cat)
Definition: duktape.c:65614
#define DUK_OP_LE_RC
Definition: duktape.c:3534
#define DUK__PI_DAY
Definition: duktape.c:32789
#define DUK_RETOK_ATOM_BACKREFERENCE
Definition: duktape.c:4141
DUK_INTERNAL_DECL void duk_heap_strtable_unlink_prev(duk_heap *heap, duk_hstring *h, duk_hstring *prev)
Definition: duktape.c:56289
DUK_INTERNAL_DECL duk_ret_t duk_bi_native_function_length(duk_context *ctx)
Definition: duktape.c:36568
DUK_EXTERNAL duk_uint16_t duk_to_uint16(duk_hthread *thr, duk_idx_t idx)
Definition: duktape.c:21710
DUK_INTERNAL_DECL duk_hobject * duk_require_hobject(duk_hthread *thr, duk_idx_t idx)
Definition: duktape.c:20882
#define DUK_OP_REGEXP
Definition: duktape.c:3660
#define DUK_HTHREAD_DECREF_NORZ(thr, h)
Definition: duktape.c:5069
DUK_INTERNAL_DECL duk_ret_t duk_bi_array_constructor(duk_context *ctx)
Definition: duktape.c:26223
#define DUK_OP_GT_RC
Definition: duktape.c:3519
DUK_INTERNAL const duk_uint8_t duk_unicode_xutf8_markers[7]
Definition: duktape.c:12723
#define DUK_ASC_RPAREN
Definition: duktape.c:10799
#define DUK_CAT_CLEAR_LEXENV_ACTIVE(c)
Definition: duktape.c:8132
#define DUK_STRIDX_PROTOTYPE
Definition: duktape.c:1729
DUK_EXTERNAL duk_bool_t duk_get_prop(duk_hthread *thr, duk_idx_t obj_idx)
Definition: duktape.c:17652
#define DUK__IDX_CLASS
Definition: duktape.c:17332
#define DUK_OP_GETPROPC
Definition: duktape.c:3722
#define DUK_HOBJECT_E_GET_VALUE_GETTER(heap, h, i)
Definition: duktape.c:7009
DUK_INTERNAL_DECL void duk_heap_remove_from_heap_allocated(duk_heap *heap, duk_heaphdr *hdr)
Definition: duktape.c:53999
#define DUK_OP_BASR_RC
Definition: duktape.c:3600
DUK_LOCAL_DECL duk_regconst_t duk__ivalue_toregconst(duk_compiler_ctx *comp_ctx, duk_ivalue *x)
Definition: duktape.c:71591
DUK_INTERNAL_DECL void duk_heap_strcache_string_remove(duk_heap *heap, duk_hstring *h)
Definition: duktape.c:55029
#define DUK_OP_DECLVAR_CC
Definition: duktape.c:3659
#define DUK_ASC_LC_F
Definition: duktape.c:10860
#define DUK_ASSERT_DOUBLE_IS_NORMALIZED(dval)
Definition: duktape.c:10590
DUK_LOCAL_DECL void duk__json_enc_pointer(duk_json_enc_ctx *js_ctx, void *ptr)
Definition: duktape.c:38974
DUK_INTERNAL_DECL void * duk_hthread_get_valstack_ptr(duk_heap *heap, void *ud)
Definition: duktape.c:64520
#define DUK_JSON_FLAG_EXT_COMPATIBLE
Definition: duktape.c:11029
DUK_INTERNAL_DECL duk_ret_t duk_bi_object_constructor_get_own_property_descriptor(duk_context *ctx)
Definition: duktape.c:41884
#define DUK_HOBJECT_CLEAR_EXTENSIBLE(h)
Definition: duktape.c:6799
#define DUK_HEAPHDR_DECREF_ALLOWNULL(thr, h)
Definition: duktape.c:5109
DUK_INTERNAL_DECL void duk_bw_insert_raw_bytes(duk_hthread *thr, duk_bufwriter_ctx *bw, duk_size_t dst_off, const duk_uint8_t *buf, duk_size_t len)
Definition: duktape.c:100268
#define DUK_BC_BC_MIN
Definition: duktape.c:3466
#define DUK_ASSERT_LJSTATE_SET(heap)
Definition: duktape.c:9264
#define DUK__GETPROPC_BODY(barg, carg)
DUK_LOCAL_DECL void duk__parse_func_formals(duk_compiler_ctx *comp_ctx)
Definition: duktape.c:76581
DUK_INTERNAL_DECL duk_harray * duk_harray_alloc(duk_hthread *thr, duk_uint_t hobject_flags)
Definition: duktape.c:56699
DUK_LOCAL duk_double_t duk__to_int_uint_helper(duk_hthread *thr, duk_idx_t idx, duk__toint_coercer coerce_func)
Definition: duktape.c:21632
#define DUK__LOOKUP(lex_ctx, idx)
Definition: duktape.c:85797
DUK_LOCAL duk_bool_t duk__proxy_check_prop(duk_hthread *thr, duk_hobject *obj, duk_small_uint_t stridx_trap, duk_tval *tv_key, duk_hobject **out_target)
Definition: duktape.c:58431
#define DUK__RETHAND_RESTART
Definition: duktape.c:77937
DUK_INTERNAL_DECL void duk_util_tinyrandom_prepare_seed(duk_hthread *thr)
Definition: duktape.c:101066
#define DUK_ERROR_RANGE_INDEX(thr, idx)
Definition: duktape.c:10302
#define DUK_BIDX_RANGE_ERROR_PROTOTYPE
Definition: duktape.c:2310
#define DUK_TOK_LCURLY
Definition: duktape.c:3916
#define DUK_HOBJECT_IS_BUFOBJ(h)
Definition: duktape.c:6715
DUK_LOCAL_DECL void duk__parse_switch_stmt(duk_compiler_ctx *comp_ctx, duk_ivalue *res, duk_int_t pc_label_site)
Definition: duktape.c:74597
DUK_EXTERNAL duk_bool_t duk_is_function(duk_hthread *thr, duk_idx_t idx)
Definition: duktape.c:22798
DUK_INTERNAL_DECL duk_ret_t duk_bi_object_getprototype_shared(duk_context *ctx)
Definition: duktape.c:41659
#define DUK_HEAPHDR_NEEDS_REFCOUNT_UPDATE(h)
Definition: duktape.c:4896
DUK_EXTERNAL void duk_compact(duk_hthread *thr, duk_idx_t obj_idx)
Definition: duktape.c:18248
DUK_LOCAL DUK_EXEC_ALWAYS_INLINE_PERF void duk__prepost_incdec_var_helper(duk_hthread *thr, duk_small_uint_t idx_dst, duk_tval *tv_id, duk_small_uint_t op, duk_small_uint_t is_strict)
Definition: duktape.c:77858
#define DUK__LOOKUP_INDIRECT(idx)
Definition: duktape.c:80014
DUK_INTERNAL_DECL duk_float_t duk_double_to_float_t(duk_double_t x)
Definition: duktape.c:100539
#define DUK_S2N_FLAG_TRIM_WHITE
Definition: duktape.c:11265
DUK_LOCAL int duk__bi_compare(duk__bigint *x, duk__bigint *y)
Definition: duktape.c:88307
#define DUK_OP_CALL8
Definition: duktape.c:3698
#define DUK_OP_GETPROP_RC
Definition: duktape.c:3615
DUK_INTERNAL_DECL void duk_bi_json_stringify_helper(duk_hthread *thr, duk_idx_t idx_value, duk_idx_t idx_replacer, duk_idx_t idx_space, duk_small_uint_t flags)
Definition: duktape.c:40244
#define DUK_PAUSE_FLAG_CAUGHT_ERROR
Definition: duktape.c:9220
#define DUK_BW_PUSH_AS_STRING(thr, bw_ctx)
Definition: duktape.c:2526
#define DUK_HBUFOBJ_ELEM_FLOAT32
Definition: duktape.c:7903
#define DUK__BUFOBJ_FLAG_PROMOTE
Definition: duktape.c:27911
#define DUK_CAT_TYPE_LABEL
Definition: duktape.c:8093
#define DUK_OP_PREINCV
Definition: duktape.c:3631
DUK_LOCAL void duk__free_finalize_list(duk_heap *heap)
Definition: duktape.c:50468
DUK_EXTERNAL const char * duk_safe_to_lstring(duk_hthread *thr, duk_idx_t idx, duk_size_t *out_len)
Definition: duktape.c:21781
DUK_LOCAL void duk__create_escaped_source(duk_hthread *thr, int idx_pattern)
Definition: duktape.c:91580
#define DUK_HSTRING_FLAG_SYMBOL
Definition: duktape.c:6329
DUK_LOCAL duk_bool_t duk__putprop_fastpath_bufobj_tval(duk_hthread *thr, duk_hobject *obj, duk_tval *tv_key, duk_tval *tv_val)
Definition: duktape.c:60400
DUK_LOCAL void duk__cbor_encode_error(duk_cbor_encode_context *enc_ctx)
Definition: duktape.c:30797
DUK_INTERNAL_DECL void duk_free_hbuffer(duk_heap *heap, duk_hbuffer *h)
Definition: duktape.c:50332
#define DUK_STR_NOT_BUFFER
Definition: duktape.c:3205
DUK_INTERNAL_DECL void duk_raw_write_double_be(duk_uint8_t *p, duk_double_t val)
Definition: duktape.c:13970
DUK_INTERNAL_DECL duk_ret_t duk_bi_object_constructor_assign(duk_context *ctx)
Definition: duktape.c:41409
DUK_INTERNAL_DECL duk_ret_t duk_bi_global_object_decode_uri(duk_context *ctx)
Definition: duktape.c:37325
DUK_INTERNAL_DECL duk_hcompfunc * duk_known_hcompfunc(duk_hthread *thr, duk_idx_t idx)
Definition: duktape.c:21371
#define DUK_DOUBLE_LOG10E
Definition: duktape.c:2376
#define DUK_STRIDX_COMPILE
Definition: duktape.c:1900
#define DUK_ERROR_RAW_FMT3(thr, file, line, err, fmt, arg1, arg2, arg3)
Definition: duktape.c:10169
DUK_INTERNAL_DECL duk_ret_t duk_bi_json_object_stringify(duk_context *ctx)
Definition: duktape.c:40580
DUK_LOCAL_DECL void duk__ivalue_plain_fromstack(duk_compiler_ctx *comp_ctx, duk_ivalue *x)
Definition: duktape.c:70990
#define DUK__PROP_TYPE_DOUBLE
Definition: duktape.c:64544
DUK_INTERNAL_DECL duk_uint8_t * duk_bw_insert_ensure_area(duk_hthread *thr, duk_bufwriter_ctx *bw, duk_size_t off, duk_size_t len)
Definition: duktape.c:100380
DUK_EXTERNAL const char * duk_push_string(duk_hthread *thr, const char *str)
Definition: duktape.c:23151
#define DUK_ASC_LC_Q
Definition: duktape.c:10871
#define DUK_HEAP_SWITCH_THREAD(heap, newthr)
Definition: duktape.c:9037
#define DUK_DBG_PROPFLAG_HIDDEN
Definition: duktape.c:9758
DUK_LOCAL duk_size_t duk__heap_free_activation_freelist(duk_heap *heap)
Definition: duktape.c:50394
#define DUK_TOK_IN
Definition: duktape.c:3865
DUK_LOCAL DUK_INLINE void duk__refcount_refzero_hstring(duk_heap *heap, duk_hstring *str)
Definition: duktape.c:54622
DUK_LOCAL duk_small_int_t duk__uni_range_match(const duk_uint8_t *unitab, duk_size_t unilen, duk_codepoint_t cp)
Definition: duktape.c:13159
DUK_LOCAL duk_uint8_t * duk__dump_hstring_raw(duk_uint8_t *p, duk_hstring *h)
Definition: duktape.c:14462
#define DUK_ASC_COMMA
Definition: duktape.c:10802
#define DUK_BC_A_MIN
Definition: duktape.c:3460
DUK_LOCAL const duk_uint8_t duk__encode_uriunescaped_table[16]
Definition: duktape.c:36662
DUK_INTERNAL_DECL duk_hobject * duk_get_hobject(duk_hthread *thr, duk_idx_t idx)
Definition: duktape.c:20877
#define DUK_HTHREAD_STRING_LENGTH(thr)
Definition: duktape.c:1842
DUK_LOCAL_DECL void duk__mark_tvals(duk_heap *heap, duk_tval *tv, duk_idx_t count)
Definition: duktape.c:52298
#define DUK_BW_WRITE_ENSURE_CSTRING(thr, bw_ctx, val)
Definition: duktape.c:2822
DUK_LOCAL duk_uint32_t duk__cbor_decode_aival_uint32(duk_cbor_decode_context *dec_ctx, duk_uint8_t ib)
Definition: duktape.c:31661
DUK_LOCAL DUK_NOINLINE void duk__cbor_encode_ensure_slowpath(duk_cbor_encode_context *enc_ctx, duk_size_t len)
Definition: duktape.c:30836
#define DUK_HOBJECT_GET_ESIZE(h)
Definition: duktape.c:7127
#define DUK__CP_ERROR
Definition: duktape.c:35284
#define DUK_OP_IFFALSE_R
Definition: duktape.c:3540
DUK_INTERNAL_DECL duk_bool_t duk_hobject_get_own_propdesc(duk_hthread *thr, duk_hobject *obj, duk_hstring *key, duk_propdesc *out_desc, duk_small_uint_t flags)
Definition: duktape.c:60107
#define DUK_HBUFFER_SET_SIZE(x, v)
Definition: duktape.c:8639
#define DUK_IVAL_PROP
Definition: duktape.c:4265
#define DUK_HEAPHDR_HAS_FINALIZABLE(h)
Definition: duktape.c:4792
#define DUK_TVAL_SET_UNDEFINED(tv)
Definition: duktape.c:1281
#define DUK_OP_CSVAR_CC
Definition: duktape.c:3689
#define DUK_OP_POSTDECV
Definition: duktape.c:3634
#define DUK_STR_NOT_UNDEFINED
Definition: duktape.c:3198
#define DUK_TOK_TRY
Definition: duktape.c:3872
#define DUK_STRIDX_UC_ERROR
Definition: duktape.c:1615
DUK_LOCAL DUK_NOINLINE_PERF DUK_COLD void * duk__heap_mem_realloc_slowpath(duk_heap *heap, void *ptr, duk_size_t newsize)
Definition: duktape.c:53732
DUK_LOCAL void duk__push_stash(duk_hthread *thr)
Definition: duktape.c:23364
#define DUK_STR_UNEXPECTED_TYPE
Definition: duktape.c:3206
#define DUK_ASC_LC_W
Definition: duktape.c:10877
DUK_INTERNAL_DECL duk_bool_t duk_has_prop_stridx(duk_hthread *thr, duk_idx_t obj_idx, duk_small_uint_t stridx)
Definition: duktape.c:18051
#define DUK_OP_UNUSED212
Definition: duktape.c:3727
#define DUK_PROPDESC_IS_CONFIGURABLE(p)
Definition: duktape.c:7086
DUK_LOCAL duk_size_t duk__dragon4_format_uint32(duk_uint8_t *buf, duk_uint32_t x, duk_small_int_t radix)
Definition: duktape.c:88846
DUK_INTERNAL_DECL const char * duk_require_string_notsymbol(duk_hthread *thr, duk_idx_t idx)
Definition: duktape.c:20539
DUK_LOCAL void duk__compact_objects(duk_heap *heap)
Definition: duktape.c:52971
#define DUK_RETOK_ASSERT_START_NEG_LOOKAHEAD
Definition: duktape.c:4132
#define DUK_ASC_UC_A
Definition: duktape.c:10823
DUK_INTERNAL DUK_COLD void duk_err_error_internal(duk_hthread *thr, const char *filename, duk_int_t linenumber)
Definition: duktape.c:12536
#define DUK_ERROR_ALLOC_FAILED(thr)
Definition: duktape.c:10285
#define DUK_HEAPHDR_GET_NEXT(heap, h)
Definition: duktape.c:4700
#define DUK_STR_NOT_COMPFUNC
Definition: duktape.c:3208
#define DUK_RE_MAX_ATOM_COPIES
Definition: duktape.c:4479
#define DUK_ASC_DOLLAR
Definition: duktape.c:10794
#define DUK_HOBJECT_SET_SPECIAL_CALL(h)
Definition: duktape.c:6797
#define DUK_HSTRING_FLAG_ARRIDX
Definition: duktape.c:6328
#define duk_memmove(dst, src, len)
Definition: duktape.c:3050
DUK_LOCAL duk_uint16_t duk__cbor_decode_read_u16(duk_cbor_decode_context *dec_ctx)
Definition: duktape.c:31465
DUK_EXTERNAL duk_idx_t duk_normalize_index(duk_hthread *thr, duk_idx_t idx)
Definition: duktape.c:18910
#define DUK__BITPACK_SWITCH1
Definition: duktape.c:100038
#define DUK_STR_HEX_DECODE_FAILED
Definition: duktape.c:3226
#define DUK_HTHREAD_STATE_TERMINATED
Definition: duktape.c:8156
DUK_EXTERNAL void duk_dup(duk_hthread *thr, duk_idx_t from_idx)
Definition: duktape.c:19777
#define DUK_ERROR_RANGE_PUSH_BEYOND(thr)
Definition: duktape.c:10306
#define DUK__NEQ_BODY(barg, carg)
DUK_INTERNAL_DECL void duk_remove_n_unsafe(duk_hthread *thr, duk_idx_t idx, duk_idx_t count)
Definition: duktape.c:20070
#define DUK_TVAL_GET_FASTINT(tv)
Definition: duktape.c:1451
#define DUK_JSON_DEC_REQSTACK
Definition: duktape.c:11035
const duk_uint8_t duk_unicode_caseconv_lc[706]
Definition: duktape.c:94039
#define DUK_HSTRING_CLEAR_PINNED_LITERAL(x)
Definition: duktape.c:6366
#define DUK_HBUFFER_DYNAMIC_SET_SIZE(x, v)
Definition: duktape.c:8657
DUK_LOCAL duk_hbufobj * duk__autospawn_arraybuffer(duk_hthread *thr, duk_hbuffer *h_buf)
Definition: duktape.c:30599
DUK_INTERNAL_DECL void duk_pop_3_unsafe(duk_hthread *thr)
Definition: duktape.c:24838
DUK_LOCAL double duk__cos(double x)
Definition: duktape.c:40808
#define DUK_BC_C_MIN
Definition: duktape.c:3464
#define DUK_HOBJECT_HAS_BOUNDFUNC(h)
Definition: duktape.c:6748
DUK_INTERNAL_DECL duk_small_int_t duk_unicode_is_letter(duk_codepoint_t cp)
Definition: duktape.c:13455
#define DUK_HOBJECT_HAS_EXTENSIBLE(h)
Definition: duktape.c:6745
DUK_INTERNAL_DECL void duk_push_lightfunc_tostring(duk_hthread *thr, duk_tval *tv)
Definition: duktape.c:25300
#define duk_get_prop_stridx_short(thr, obj_idx, stridx)
Definition: duktape.c:6139
DUK_LOCAL_DECL void duk__copy_ivalue(duk_compiler_ctx *comp_ctx, duk_ivalue *src, duk_ivalue *dst)
Definition: duktape.c:71014
#define DUK_STRIDX_MULTILINE
Definition: duktape.c:1717
#define DUK_OP_UNUSED235
Definition: duktape.c:3750
DUK_INTERNAL_DECL duk_hnatfunc * duk_require_hnatfunc(duk_hthread *thr, duk_idx_t idx)
Definition: duktape.c:20975
DUK_LOCAL duk_uint32_t duk__get_default_h_size(duk_uint32_t e_size)
Definition: duktape.c:58121
#define DUK_HTHREAD_STRING_GET(thr)
Definition: duktape.c:1800
#define DUK_HBUFFER_SET_DYNAMIC(x)
Definition: duktape.c:8590
DUK_EXTERNAL duk_idx_t duk_push_error_object_stash(duk_hthread *thr, duk_errcode_t err_code, const char *fmt,...)
Definition: duktape.c:24177
DUK_LOCAL duk_uint8_t * duk__dump_varmap(duk_hthread *thr, duk_uint8_t *p, duk_bufwriter_ctx *bw_ctx, duk_hobject *func)
Definition: duktape.c:14559
#define DUK_DBLUNION_IS_NAN(u)
Definition: duktape.c:550
DUK_LOCAL DUK_EXEC_ALWAYS_INLINE_PERF void duk__vm_arith_binary_op(duk_hthread *thr, duk_tval *tv_x, duk_tval *tv_y, duk_uint_fast_t idx_z, duk_small_uint_fast_t opcode)
Definition: duktape.c:77345
DUK_LOCAL void duk__cbor_encode_req_stack(duk_cbor_encode_context *enc_ctx)
Definition: duktape.c:30801
#define DUK_HOBJECT_H_GET_BASE(heap, h)
Definition: duktape.c:6950
DUK_LOCAL duk_small_uint_t duk__handle_longjmp(duk_hthread *thr, duk_activation *entry_act, volatile duk_bool_t *out_delayed_catch_setup)
Definition: duktape.c:78256
DUK_INTERNAL_DECL void duk_be_finish(duk_bitencoder_ctx *ctx)
Definition: duktape.c:100127
#define DUK_S2N_FLAG_ALLOW_LEADING_ZERO
Definition: duktape.c:11295
#define DUK_DBG_ERR_APPLICATION
Definition: duktape.c:9719
#define DUK_HOBJECT_CLASS_STRING
Definition: duktape.c:6647
#define DUK_HBUFFER_HAS_EXTERNAL(x)
Definition: duktape.c:8588
DUK_LOCAL void duk__cbor_encode_sizet_uint32_check(duk_cbor_encode_context *enc_ctx, duk_size_t len)
Definition: duktape.c:30830
#define DUK_GET_THIS_TVAL_PTR(thr)
Definition: duktape.c:6276
DUK_EXTERNAL duk_bool_t duk_put_prop_lstring(duk_hthread *thr, duk_idx_t obj_idx, const char *key, duk_size_t key_len)
Definition: duktape.c:17849
#define DUK_HEAP_MARK_AND_SWEEP_TRIGGER_MULT
Definition: duktape.c:9075
#define DUK_TOK_EXP_EQ
Definition: duktape.c:3959
DUK_EXTERNAL void duk_put_number_list(duk_hthread *thr, duk_idx_t obj_idx, const duk_number_list_entry *numbers)
Definition: duktape.c:18370
DUK_INTERNAL_DECL duk_ret_t duk_bi_global_object_eval(duk_context *ctx)
Definition: duktape.c:37058
#define DUK_HTYPE_STRING
Definition: duktape.c:4688
DUK_INTERNAL_DECL duk_uint16_t duk_raw_readinc_u16_be(const duk_uint8_t **p)
Definition: duktape.c:13927
DUK_LOCAL duk_int_t duk__handle_call_raw(duk_hthread *thr, duk_idx_t idx_func, duk_small_uint_t call_flags)
Definition: duktape.c:68014
DUK_EXTERNAL duk_bool_t duk_is_buffer(duk_hthread *thr, duk_idx_t idx)
Definition: duktape.c:22728
#define DUK_REOP_SPLIT1
Definition: duktape.c:4494
#define DUK_REOP_CHAR
Definition: duktape.c:4489
DUK_EXTERNAL void duk_to_object(duk_hthread *thr, duk_idx_t idx)
Definition: duktape.c:22345
DUK_INTERNAL_DECL void duk_raw_writeinc_xutf8(duk_uint8_t **p, duk_ucodepoint_t val)
Definition: duktape.c:14007
DUK_LOCAL const duk_uint8_t duk__base64_enctab_fast[64]
Definition: duktape.c:15774
#define DUK_OP_NEWTARGET
Definition: duktape.c:3717
#define DUK_ASC_CARET
Definition: duktape.c:10852
#define DUK_TAG_BUFFER
Definition: duktape.c:1269
#define DUK_STR_UNTERMINATED_COMMENT
Definition: duktape.c:3260
DUK_INTERNAL duk_uint8_t duk_class_number_to_stridx[32]
Definition: duktape.c:14276
#define DUK_HBUFFER_HAS_DYNAMIC(x)
Definition: duktape.c:8587
#define DUK_TAG_FASTINT
Definition: duktape.c:1259
#define DUK_HOBJECT_CLASS_ARRAYBUFFER
Definition: duktape.c:6655
#define DUK_BIDX_DUKTAPE
Definition: duktape.c:2320
#define DUK_ASC_UC_U
Definition: duktape.c:10843
#define DUK_PAUSE_FLAG_FUNC_ENTRY
Definition: duktape.c:9218
#define DUK_GETDESC_FLAG_IGNORE_PROTOLOOP
Definition: duktape.c:6862
DUK_LOCAL void duk__emit_u16_direct_ranges(duk_lexer_ctx *lex_ctx, duk_re_range_callback gen_range, void *userdata, const duk_uint16_t *ranges, duk_small_int_t num)
Definition: duktape.c:87902
#define DUK_OP_UNUSED223
Definition: duktape.c:3738
#define DUK__BITPACK_LOOKUP1
Definition: duktape.c:100036
#define DUK__UNEMIT_1(js_ctx)
Definition: duktape.c:38422
#define DUK_STR_NOT_POINTER
Definition: duktape.c:3204
#define DUK__UPDATE_RND(rnd)
Definition: duktape.c:101058
#define DUK_OP_UNUSED218
Definition: duktape.c:3733
DUK_LOCAL_DECL duk_ret_t duk__set_this_timeval_from_dparts(duk_hthread *thr, duk_double_t *dparts, duk_small_uint_t flags)
Definition: duktape.c:33662
#define DUK_OP_POSTINCV
Definition: duktape.c:3633
#define DUK_CAT_CLEAR_FINALLY_ENABLED(c)
Definition: duktape.c:8124
#define DUK_OP_LDNULL
Definition: duktape.c:3488
DUK_EXTERNAL duk_c_function duk_opt_c_function(duk_hthread *thr, duk_idx_t idx, duk_c_function def_value)
Definition: duktape.c:21012
#define DUK_HBUFOBJ_ELEM_UINT8
Definition: duktape.c:7896
#define DUK_HOBJECT_PROHIBITS_FASTREFS(h)
Definition: duktape.c:6828
DUK_INTERNAL DUK_COLD void duk_err_range(duk_hthread *thr, const char *filename, duk_int_t linenumber, const char *message)
Definition: duktape.c:12545
DUK_INTERNAL_DECL void duk_heap_mem_free(duk_heap *heap, void *ptr)
Definition: duktape.c:53958
#define DUK_OP_GETPROP_CC
Definition: duktape.c:3616
DUK_INTERNAL_DECL duk_ret_t duk_bi_regexp_prototype_shared_getter(duk_context *ctx)
Definition: duktape.c:42614
DUK_LOCAL duk_size_t duk__heap_free_catcher_freelist(duk_heap *heap)
Definition: duktape.c:50413
#define DUK_HOBJECT_HAS_STRICT(h)
Definition: duktape.c:6758
#define DUK_ASC_PERIOD
Definition: duktape.c:10804
DUK_EXTERNAL duk_bool_t duk_put_prop(duk_hthread *thr, duk_idx_t obj_idx)
Definition: duktape.c:17831
DUK_EXTERNAL duk_bool_t duk_require_boolean(duk_hthread *thr, duk_idx_t idx)
Definition: duktape.c:20243
#define DUK__RE_INITIAL_BUFSIZE
Definition: duktape.c:90529
#define DUK_ERRCODE_FLAG_NOBLAME_FILELINE
Definition: duktape.c:5927
#define DUK_HTHREAD_THIS_PTR(thr)
Definition: duktape.c:8221
#define DUK_HTHREAD_STRING_INT_MAP(thr)
Definition: duktape.c:1890
#define DUK_STR_INVALID_RETURN
Definition: duktape.c:3283
double(* duk__one_arg_func)(double)
Definition: duktape.c:40619
#define DUK_S2N_FLAG_ALLOW_EXP
Definition: duktape.c:11268
#define DUK_DBG_CMD_DETACH
Definition: duktape.c:9746
#define DUK_HOBJECT_CMASK_ARRAY
Definition: duktape.c:6673
DUK_INTERNAL_DECL duk_uint32_t duk_bd_decode(duk_bitdecoder_ctx *ctx, duk_small_int_t bits)
Definition: duktape.c:99942
#define DUK_OP_IFTRUE_C
Definition: duktape.c:3538
DUK_LOCAL DUK_COLD DUK_NOINLINE duk_bool_t duk__valstack_grow(duk_hthread *thr, duk_size_t min_bytes, duk_bool_t throw_on_error)
Definition: duktape.c:19509
DUK_EXTERNAL void duk_cbor_encode(duk_hthread *thr, duk_idx_t idx, duk_uint_t encode_flags)
Definition: duktape.c:32613
#define DUK_STR_INVALID_NUMBER_LITERAL
Definition: duktape.c:3264
DUK_LOCAL void duk__cbor_encode_lightfunc(duk_cbor_encode_context *enc_ctx)
Definition: duktape.c:31342
#define DUK_BW_ENSURE_GETPTR(thr, bw_ctx, sz)
Definition: duktape.c:2592
DUK_EXTERNAL void duk_pop_n(duk_hthread *thr, duk_idx_t count)
Definition: duktape.c:24627
#define DUK_BC_LDINT_BIAS
Definition: duktape.c:3796
DUK_INTERNAL_DECL duk_idx_t duk_get_top_require_min(duk_hthread *thr, duk_idx_t min_top)
Definition: duktape.c:19081
DUK_INTERNAL_DECL duk_tval * duk_get_tval(duk_hthread *thr, duk_idx_t idx)
Definition: duktape.c:18973
#define DUK_HOBJECT_CLASS_DATAVIEW
Definition: duktape.c:6656
DUK_INTERNAL_DECL duk_ret_t duk_bi_string_prototype_indexof_shared(duk_context *ctx)
Definition: duktape.c:43159
#define DUK_STRIDX_INT_SOURCE
Definition: duktape.c:1882
DUK_LOCAL void duk__push_double(duk_hthread *thr, duk_bitdecoder_ctx *bd)
Definition: duktape.c:64707
#define duk_push_uarridx(thr, val)
Definition: duktape.c:5998
#define DUK_HOBJECT_P_ALLOC_SIZE(h)
Definition: duktape.c:7000
#define DUK_BC_C_MAX
Definition: duktape.c:3465
#define DUK_HBUFFER_DYNAMIC_SET_DATA_PTR_NULL(heap, x)
Definition: duktape.c:8683
DUK_LOCAL_DECL duk_double_t duk__push_this_get_timeval_tzoffset(duk_hthread *thr, duk_small_uint_t flags, duk_int_t *out_tzoffset)
Definition: duktape.c:33611
struct duk_lexer_codepoint duk_lexer_codepoint
Definition: duktape.c:880
DUK_INTERNAL_DECL void duk_lexer_parse_re_ranges(duk_lexer_ctx *lex_ctx, duk_re_range_callback gen_range, void *userdata)
Definition: duktape.c:87919
#define DUK_STR_DUPLICATE_LABEL
Definition: duktape.c:3269
#define DUK_ASC_LC_S
Definition: duktape.c:10873
#define DUK_OP_THROW
Definition: duktape.c:3682
DUK_LOCAL duk_ret_t duk__array_push_fastpath(duk_hthread *thr, duk_harray *h_arr)
Definition: duktape.c:26598
DUK_LOCAL duk_uint8_t * duk__dump_uint32_prop(duk_hthread *thr, duk_uint8_t *p, duk_bufwriter_ctx *bw_ctx, duk_hobject *func, duk_small_uint_t stridx, duk_uint32_t def_value)
Definition: duktape.c:14539
#define DUK_OP_EXP
Definition: duktape.c:3567
#define DUK_DBG_IB_REQUEST
Definition: duktape.c:9689
DUK_INTERNAL_DECL duk_bool_t duk_xget_owndataprop_stridx(duk_hthread *thr, duk_idx_t obj_idx, duk_small_uint_t stridx)
Definition: duktape.c:17787
DUK_EXTERNAL void duk_base64_decode(duk_hthread *thr, duk_idx_t idx)
Definition: duktape.c:16373
DUK_LOCAL_DECL void duk__expr(duk_compiler_ctx *comp_ctx, duk_ivalue *res, duk_small_uint_t rbp_flags)
Definition: duktape.c:73932
#define DUK__BP_INVALID
Definition: duktape.c:69320
DUK_EXTERNAL const char * duk_safe_to_stacktrace(duk_hthread *thr, duk_idx_t idx)
Definition: duktape.c:21844
DUK_INTERNAL_DECL void duk_regexp_match_force_global(duk_hthread *thr)
Definition: duktape.c:92850
DUK_INTERNAL_DECL duk_bool_t duk_valstack_grow_check_nothrow(duk_hthread *thr, duk_size_t min_bytes)
Definition: duktape.c:19574
#define DUK_HTYPE_BUFFER
Definition: duktape.c:4690
#define DUK_STR_INVALID_OBJECT_LITERAL
Definition: duktape.c:3272
DUK_LOCAL duk_bool_t duk__obj_flag_any_default_false(duk_hthread *thr, duk_idx_t idx, duk_uint_t flag_mask)
Definition: duktape.c:22486
#define DUK_STR_UNEXPECTED_CLOSING_PAREN
Definition: duktape.c:3299
DUK_INTERNAL_DECL duk_hobject * duk_hobject_alloc(duk_hthread *thr, duk_uint_t hobject_flags)
Definition: duktape.c:56566
#define DUK_HOBJECT_HAS_NOTAIL(h)
Definition: duktape.c:6759
#define DUK_ERROR_TYPE_INVALID_TRAP_RESULT(thr)
Definition: duktape.c:10371
DUK_EXTERNAL void duk_enum(duk_hthread *thr, duk_idx_t obj_idx, duk_uint_t enum_flags)
Definition: duktape.c:18268
DUK_INTERNAL_DECL void duk_unicode_case_convert_string(duk_hthread *thr, duk_bool_t uppercase)
Definition: duktape.c:13719
#define DUK_OP_ENDCATCH
Definition: duktape.c:3680
DUK_LOCAL_DECL duk_uint8_t duk__json_dec_get_nonwhite(duk_json_dec_ctx *js_ctx)
Definition: duktape.c:37604
DUK_INTERNAL_DECL duk_tval * duk_hobject_find_entry_tval_ptr(duk_heap *heap, duk_hobject *obj, duk_hstring *key)
Definition: duktape.c:59335
DUK_LOCAL DUK_ALWAYS_INLINE duk_bool_t duk__get_boolean_raw(duk_hthread *thr, duk_idx_t idx, duk_bool_t def_value)
Definition: duktape.c:20212
DUK_LOCAL duk_bool_t duk__init_heap_strings(duk_heap *heap)
Definition: duktape.c:50724
DUK_INTERNAL_DECL void duk_valstack_grow_check_throw(duk_hthread *thr, duk_size_t min_bytes)
Definition: duktape.c:19556
DUK_LOCAL_DECL duk_idx_t duk__push_c_function_raw(duk_hthread *thr, duk_c_function func, duk_idx_t nargs, duk_uint_t flags, duk_small_uint_t proto_bidx)
Definition: duktape.c:23760
DUK_INTERNAL_DECL void duk_hobject_set_prototype_updref(duk_hthread *thr, duk_hobject *h, duk_hobject *p)
Definition: duktape.c:57634
#define DUK_HOBJECT_SET_PROTOTYPE_INIT_INCREF(thr, h, proto)
Definition: duktape.c:7201
DUK_LOCAL DUK_EXEC_ALWAYS_INLINE_PERF duk_double_t duk__compute_exp(duk_double_t d1, duk_double_t d2)
Definition: duktape.c:77230
#define DUK_HOBJECT_SET_NEWENV(h)
Definition: duktape.c:6787
#define DUK__SER_NUMBER
Definition: duktape.c:14433
DUK_INTERNAL_DECL void duk_valstack_shrink_check_nothrow(duk_hthread *thr, duk_bool_t snug)
Definition: duktape.c:19589
DUK_INTERNAL_DECL void duk_heap_remove_from_finalize_list(duk_heap *heap, duk_heaphdr *hdr)
Definition: duktape.c:54061
#define DUK__INCREF_SHARED()
Definition: duktape.c:54917
DUK_LOCAL duk_bool_t duk__putprop_shallow_fastpath_array_tval(duk_hthread *thr, duk_hobject *obj, duk_tval *tv_key, duk_tval *tv_val)
Definition: duktape.c:60275
#define DUK_HOBJECT_SET_CLASS_NUMBER(h, v)
Definition: duktape.c:6621
#define DUK_HOBJECT_E_SLOT_SET_ACCESSOR(heap, h, i)
Definition: duktape.c:7075
DUK_EXTERNAL duk_bool_t duk_get_global_literal_raw(duk_hthread *thr, const char *key, duk_size_t key_len)
Definition: duktape.c:18421
DUK_INTERNAL_DECL duk_ret_t duk_bi_date_prototype_set_time(duk_context *ctx)
Definition: duktape.c:34456
#define DUK_RAW_READ_U32_BE(ptr)
Definition: duktape.c:2452
DUK_LOCAL_DECL duk_regconst_t duk__lookup_active_register_binding(duk_compiler_ctx *comp_ctx)
Definition: duktape.c:71611
DUK_LOCAL void duk__resolve_offset_opt_length(duk_hthread *thr, duk_hbufobj *h_bufarg, duk_idx_t idx_offset, duk_idx_t idx_length, duk_uint_t *out_offset, duk_uint_t *out_length, duk_bool_t throw_flag)
Definition: duktape.c:28018
#define DUK_HEAP_DBG_RATELIMIT_MILLISECS
Definition: duktape.c:9212
#define DUK_OP_UNUSED240
Definition: duktape.c:3755
#define DUK_OP_GETPROPC_CC
Definition: duktape.c:3726
DUK_LOCAL duk_bool_t duk__is_hex_digit(duk_codepoint_t x)
Definition: duktape.c:86344
#define DUK_STR_REGEXP_EXECUTOR_RECURSION_LIMIT
Definition: duktape.c:3323
const duk_uint8_t duk_unicode_re_canon_bitmap[256]
Definition: duktape.c:99915
#define DUK__EMIT_FLAG_C_IS_TARGET
Definition: duktape.c:70144
DUK_LOCAL duk_uint8_t * duk__utf8_emit_repl(duk_uint8_t *ptr)
Definition: duktape.c:35292
DUK_INTERNAL_DECL duk_bool_t duk_hobject_find_entry(duk_heap *heap, duk_hobject *obj, duk_hstring *key, duk_int_t *e_idx, duk_int_t *h_idx)
Definition: duktape.c:59255
DUK_INTERNAL_DECL duk_bool_t duk_put_prop_stridx_short_raw(duk_hthread *thr, duk_uint_t packed_args)
Definition: duktape.c:17895
DUK_INTERNAL_DECL void duk_bw_init_pushbuf(duk_hthread *thr, duk_bufwriter_ctx *bw_ctx, duk_size_t buf_size)
Definition: duktape.c:100179
#define DUK_JSON_FLAG_ASCII_ONLY
Definition: duktape.c:11026
#define DUK_HOBJECT_DECREF_NORZ(thr, h)
Definition: duktape.c:5053
#define DUK_HBUFOBJ_ELEM_MAX
Definition: duktape.c:7905
DUK_LOCAL void duk__fill_lexer_buffer(duk_lexer_ctx *lex_ctx, duk_small_uint_t start_offset_bytes)
Definition: duktape.c:85885
#define DUK_REOP_SQMINIMAL
Definition: duktape.c:4496
#define DUK_STR_UNTERMINATED_REGEXP
Definition: duktape.c:3261
#define DUK_STRIDX_NEWLINE_4SPACE
Definition: duktape.c:1771
#define DUK__MKESC(nybbles, esc1, esc2)
Definition: duktape.c:38457
DUK_INTERNAL_DECL void duk_dup_m2(duk_hthread *thr)
Definition: duktape.c:19827
DUK_INTERNAL_DECL duk_double_t duk_time_get_ecmascript_time_nofrac(duk_hthread *thr)
Definition: duktape.c:25986
DUK_INTERNAL_DECL void duk_heap_insert_into_finalize_list(duk_heap *heap, duk_heaphdr *hdr)
Definition: duktape.c:54042
DUK_INTERNAL_DECL void duk_js_execute_bytecode(duk_hthread *exec_thr)
Definition: duktape.c:80087
#define DUK_TAG_MAX
Definition: duktape.c:1270
#define DUK_RAW_READINC_U16_BE(ptr)
Definition: duktape.c:2456
#define DUK_ASC_LC_A
Definition: duktape.c:10855
DUK_LOCAL duk_uint32_t duk__insert_u32(duk_re_compiler_ctx *re_ctx, duk_uint32_t offset, duk_uint32_t x)
Definition: duktape.c:90583
#define DUK_OP_RETREG
Definition: duktape.c:3670
#define DUK_EQUALS_FLAG_STRICT
Definition: duktape.c:11106
DUK_INTERNAL_DECL void duk_regexp_create_instance(duk_hthread *thr)
Definition: duktape.c:91762
#define DUK_HSTRING_GET_ARRIDX_SLOW(h)
Definition: duktape.c:6440
DUK_EXTERNAL void duk_set_top(duk_hthread *thr, duk_idx_t idx)
Definition: duktape.c:19098
#define DUK_TVAL_GET_DOUBLE(tv)
Definition: duktape.c:1450
#define DUK_BIDX_DATE_PROTOTYPE
Definition: duktape.c:2302
DUK_INTERNAL_DECL duk_hstring * duk_heap_strtable_intern_checked(duk_hthread *thr, const duk_uint8_t *str, duk_uint32_t len)
Definition: duktape.c:56141
DUK_LOCAL_DECL void duk__json_enc_double(duk_json_enc_ctx *js_ctx)
Definition: duktape.c:38701
DUK_EXTERNAL duk_bool_t duk_put_prop_heapptr(duk_hthread *thr, duk_idx_t obj_idx, void *ptr)
Definition: duktape.c:17878
#define DUK_OP_UNUSED245
Definition: duktape.c:3760
DUK_LOCAL void duk__err_augment_user(duk_hthread *thr, duk_small_uint_t stridx_cb)
Definition: duktape.c:49035
#define DUK_STR_ALLOC_FAILED
Definition: duktape.c:3220
DUK_LOCAL duk_bool_t duk__hstring_is_eval_or_arguments_in_strict_mode(duk_compiler_ctx *comp_ctx, duk_hstring *h)
Definition: duktape.c:69483
DUK_EXTERNAL void duk_join(duk_hthread *thr, duk_idx_t count)
Definition: duktape.c:25752
DUK_LOCAL void duk__utf8_encode_char(void *udata, duk_codepoint_t codepoint)
Definition: duktape.c:35395
#define DUK_HOBJECT_INCREF_ALLOWNULL(thr, h)
Definition: duktape.c:5121
DUK_INTERNAL_DECL duk_double_t duk_bi_date_get_timeval_from_dparts(duk_double_t *dparts, duk_small_uint_t flags)
Definition: duktape.c:33464
#define DUK__PROP_TYPE_BOOLEAN_FALSE
Definition: duktape.c:64550
DUK_INTERNAL const duk_int8_t duk_is_idchar_tab[128]
Definition: duktape.c:12655
#define DUK_HCOMPFUNC_GET_CODE_END(heap, h)
Definition: duktape.c:7626
#define DUK__PROP_TYPE_BOOLEAN_TRUE
Definition: duktape.c:64549
DUK_INTERNAL_DECL duk_uint_t duk_double_to_uint_t(duk_double_t x)
Definition: duktape.c:100503
DUK_LOCAL_DECL duk_bool_t duk__json_enc_allow_into_proplist(duk_tval *tv)
Definition: duktape.c:39608
#define DUK_OP_UNUSED234
Definition: duktape.c:3749
#define DUK_OP_EQ
Definition: duktape.c:3496
#define DUK_BC_A_MAX
Definition: duktape.c:3461
DUK_EXTERNAL duk_int_t duk_get_int(duk_hthread *thr, duk_idx_t idx)
Definition: duktape.c:20341
#define DUK_HTHREAD_STRING_CALLER(thr)
Definition: duktape.c:1788
#define DUK_HTHREAD_STRING_JC(thr)
Definition: duktape.c:1926
DUK_EXTERNAL duk_double_t duk_get_number(duk_hthread *thr, duk_idx_t idx)
Definition: duktape.c:20298
DUK_LOCAL DUK_EXEC_ALWAYS_INLINE_PERF void duk__vm_bitwise_not(duk_hthread *thr, duk_uint_fast_t idx_src, duk_uint_fast_t idx_dst)
Definition: duktape.c:77718
#define DUK__PM_HOUR
Definition: duktape.c:32801
#define DUK_ASC_LC_V
Definition: duktape.c:10876
#define DUK__DRAGON4_OUTPUT_PREINC(nc_ctx, preinc_idx, x)
Definition: duktape.c:88839
#define DUK_OP_GETVAR
Definition: duktape.c:3491
#define DUK__VALSTACK_SPACE
Definition: duktape.c:57952
DUK_INTERNAL_DECL duk_ret_t duk_bi_duktape_object_info(duk_context *ctx)
Definition: duktape.c:35114
#define DUK_HSTRING_FLAG_HIDDEN
Definition: duktape.c:6330
#define DUK_TVAL_SET_I32(tv, val)
Definition: duktape.c:1335
DUK_INTERNAL_DECL duk_harray * duk_hobject_get_formals(duk_hthread *thr, duk_hobject *obj)
Definition: duktape.c:59528
#define DUK__OUTPUT_TYPE_TRACEBACK
Definition: duktape.c:35895
DUK_INTERNAL_DECL duk_hobject * duk_push_object_helper_proto(duk_hthread *thr, duk_uint_t hobject_flags_and_class, duk_hobject *proto)
Definition: duktape.c:23534
DUK_INTERNAL_DECL duk_ret_t duk_bi_thread_yield(duk_context *ctx)
Definition: duktape.c:44686
DUK_INTERNAL_DECL duk_heap * duk_heap_alloc(duk_alloc_function alloc_func, duk_realloc_function realloc_func, duk_free_function free_func, void *heap_udata, duk_fatal_function fatal_func)
Definition: duktape.c:51050
DUK_LOCAL DUK_ALWAYS_INLINE void duk__pop_2_unsafe_raw(duk_hthread *thr)
Definition: duktape.c:24779
#define DUK__NARGS_BITS
Definition: duktape.c:64539
#define DUK__RND_BIT(rnd)
Definition: duktape.c:101064
DUK_INTERNAL_DECL duk_int_t duk_to_int_clamped_raw(duk_hthread *thr, duk_idx_t idx, duk_int_t minval, duk_int_t maxval, duk_bool_t *out_clamped)
Definition: duktape.c:21983
#define DUK__PM_MILLISECOND
Definition: duktape.c:32804
#define DUK_ASC_LC_T
Definition: duktape.c:10874
#define DUK_BIDX_INT16ARRAY_PROTOTYPE
Definition: duktape.c:2330
#define DUK_DEC_ABC(x)
Definition: duktape.c:3439
#define DUK_RETOK_ASSERT_NOT_WORD_BOUNDARY
Definition: duktape.c:4130
#define DUK__REGP_BC(ins)
Definition: duktape.c:79958
#define DUK_HOBJECT_E_SLOT_IS_CONFIGURABLE(heap, h, i)
Definition: duktape.c:7067
DUK_INTERNAL_DECL duk_ret_t duk_bi_object_prototype_lookupaccessor(duk_context *ctx)
Definition: duktape.c:42079
DUK_INTERNAL_DECL duk_ret_t duk_bi_number_prototype_to_fixed(duk_context *ctx)
Definition: duktape.c:41216
DUK_INTERNAL_DECL duk_ret_t duk_bi_string_prototype_trim(duk_context *ctx)
Definition: duktape.c:44019
#define DUK_OP_GE_CC
Definition: duktape.c:3525
#define DUK_OP_DELPROP_RC
Definition: duktape.c:3625
DUK_EXTERNAL void * duk_to_pointer(duk_hthread *thr, duk_idx_t idx)
Definition: duktape.c:22263
DUK_INTERNAL_DECL duk_ret_t duk_bi_global_object_is_nan(duk_context *ctx)
Definition: duktape.c:37305
#define DUK__REGP_B(ins)
Definition: duktape.c:79956
DUK_INTERNAL_DECL duk_ret_t duk_bi_function_prototype_bind(duk_context *ctx)
Definition: duktape.c:36386
DUK_LOCAL void duk__compute_a_stats(duk_hthread *thr, duk_hobject *obj, duk_uint32_t *out_used, duk_uint32_t *out_min_size)
Definition: duktape.c:58192
#define DUK_IVAL_NONE
Definition: duktape.c:4262
DUK_INTERNAL_DECL duk_uint8_t duk_to_uint8clamped(duk_hthread *thr, duk_idx_t idx)
Definition: duktape.c:21728
DUK_LOCAL duk_double_t duk__timeclip(duk_double_t x)
Definition: duktape.c:33171
#define DUK_TVAL_SET_STRING(tv, hptr)
Definition: duktape.c:1409
#define DUK_PROPDESC_FLAGS_W
Definition: duktape.c:6852
DUK_LOCAL DUK_INLINE duk_tval * duk__obtain_arridx_slot(duk_hthread *thr, duk_uint32_t arr_idx, duk_hobject *obj)
Definition: duktape.c:58366
#define DUK_OP_GETPROPC_RC
Definition: duktape.c:3725
#define DUK_OP_LT_CC
Definition: duktape.c:3530
DUK_INTERNAL_DECL duk_ucodepoint_t duk_unicode_decode_xutf8_checked(duk_hthread *thr, const duk_uint8_t **ptr, const duk_uint8_t *ptr_start, const duk_uint8_t *ptr_end)
Definition: duktape.c:12920
DUK_LOCAL_DECL duk_uint_fast32_t duk__json_dec_decode_hex_escape(duk_json_dec_ctx *js_ctx, duk_small_uint_t n)
Definition: duktape.c:37610
#define DUK_OP_UNUSED232
Definition: duktape.c:3747
DUK_EXTERNAL duk_bool_t duk_has_prop_index(duk_hthread *thr, duk_idx_t obj_idx, duk_uarridx_t arr_idx)
Definition: duktape.c:18035
#define DUK_STR_BASE64_DECODE_FAILED
Definition: duktape.c:3225
DUK_INTERNAL_DECL duk_bool_t duk_hobject_enumerator_next(duk_hthread *thr, duk_bool_t get_value)
Definition: duktape.c:57443
DUK_EXTERNAL void duk_debugger_attach(duk_hthread *thr, duk_debug_read_function read_cb, duk_debug_write_function write_cb, duk_debug_peek_function peek_cb, duk_debug_read_flush_function read_flush_cb, duk_debug_write_flush_function write_flush_cb, duk_debug_request_function request_cb, duk_debug_detached_function detached_cb, void *udata)
Definition: duktape.c:17021
#define DUK_STRIDX_CALLER
Definition: duktape.c:1786
DUK_EXTERNAL duk_int32_t duk_to_int32(duk_hthread *thr, duk_idx_t idx)
Definition: duktape.c:21678
DUK_LOCAL const duk_uint8_t duk__re_range_lookup2[3]
Definition: duktape.c:90999
#define DUK__GET_STRTABLE(heap)
Definition: duktape.c:55351
DUK_INTERNAL_DECL duk_ret_t duk_bi_number_prototype_to_locale_string(duk_context *ctx)
Definition: duktape.c:41203
#define DUK_OP_DEBUGGER
Definition: duktape.c:3718
#define DUK_BC_ABC_MAX
Definition: duktape.c:3469
#define DUK__EMIT_1(js_ctx, ch)
Definition: duktape.c:38415
DUK_INTERNAL_DECL void duk_raw_writeinc_u32_be(duk_uint8_t **p, duk_uint32_t val)
Definition: duktape.c:13992
DUK_LOCAL duk_uint32_t duk__cbor_double_to_uint32(double d)
Definition: duktape.c:30787
#define DUK_STR_INVALID_NEWTARGET
Definition: duktape.c:3277
#define DUK_ERROR_FMT1(thr, err, fmt, arg1)
Definition: duktape.c:10103
DUK_EXTERNAL void duk_push_thread_stash(duk_hthread *thr, duk_hthread *target_thr)
Definition: duktape.c:23393
DUK_LOCAL double duk__sqrt(double x)
Definition: duktape.c:40823
#define DUK_CALL_FLAG_DEFAULT_INSTANCE_UPDATED
Definition: duktape.c:11101
DUK_INTERNAL_DECL duk_bool_t duk_hobject_putprop(duk_hthread *thr, duk_tval *tv_obj, duk_tval *tv_key, duk_tval *tv_val, duk_bool_t throw_flag)
Definition: duktape.c:61478
#define DUK_CANON_BITMAP_BLKSHIFT
Definition: duktape.c:10963
#define DUK_TOK_FUNCTION
Definition: duktape.c:3863
DUK_EXTERNAL duk_bool_t duk_debugger_notify(duk_hthread *thr, duk_idx_t nvalues)
Definition: duktape.c:17055
#define DUK__RE_BUFLEN(re_ctx)
Definition: duktape.c:90531
#define DUK_OP_GE
Definition: duktape.c:3521
DUK_INTERNAL_DECL duk_ret_t duk_bi_reflect_object_has(duk_context *ctx)
Definition: duktape.c:42412
DUK_INTERNAL_DECL duk_ret_t duk_bi_proxy_constructor(duk_context *ctx)
Definition: duktape.c:42351
#define DUK_OP_DECLVAR_RR
Definition: duktape.c:3656
DUK_LOCAL duk_int_t duk__div_floor(duk_int_t a, duk_int_t b)
Definition: duktape.c:33187
#define DUK__BP_EQUALITY
Definition: duktape.c:69332
DUK_EXTERNAL duk_bool_t duk_get_global_heapptr(duk_hthread *thr, void *ptr)
Definition: duktape.c:18437
#define DUK_UNICODE_MAX_XUTF8_LENGTH
Definition: duktape.c:10730
#define DUK_TOK_SEQ
Definition: duktape.c:3931
DUK_LOCAL void duk__push_func_from_lightfunc(duk_hthread *thr, duk_c_function func, duk_small_uint_t lf_flags)
Definition: duktape.c:22313
#define DUK_STR_QUANTIFIER_TOO_MANY_COPIES
Definition: duktape.c:3298
DUK_LOCAL duk_bool_t duk__parse_string_iso8601_subset(duk_hthread *thr, const char *str)
Definition: duktape.c:32889
#define DUK_HCOMPFUNC_GET_LEXENV(heap, h)
Definition: duktape.c:7596
#define DUK_SYMBOL_TYPE_GLOBAL
Definition: duktape.c:6454
DUK_EXTERNAL void * duk_require_buffer_data(duk_hthread *thr, duk_idx_t idx, duk_size_t *out_size)
Definition: duktape.c:20807
#define DUK_HEAP_REMOVE_FROM_HEAP_ALLOCATED(heap, hdr)
Definition: duktape.c:9105
#define DUK__IDX_TSTATE
Definition: duktape.c:17340
#define DUK__EMIT_FLAG_NO_SHUFFLE_C
Definition: duktape.c:70141
#define DUK_OP_REGEXP_RC
Definition: duktape.c:3663
DUK_EXTERNAL duk_bool_t duk_is_number(duk_hthread *thr, duk_idx_t idx)
Definition: duktape.c:22675
DUK_EXTERNAL const char * duk_opt_lstring(duk_hthread *thr, duk_idx_t idx, duk_size_t *out_len, const char *def_ptr, duk_size_t def_len)
Definition: duktape.c:20456
#define DUK__PI_MILLISECOND
Definition: duktape.c:32793
#define DUK_STR_INVALID_BACKREFS
Definition: duktape.c:3304
DUK_INTERNAL_DECL duk_hstring * duk_to_hstring_m1(duk_hthread *thr)
Definition: duktape.c:22168
DUK_EXTERNAL duk_bool_t duk_get_prop_index(duk_hthread *thr, duk_idx_t obj_idx, duk_uarridx_t arr_idx)
Definition: duktape.c:17705
#define DUK_OP_IFTRUE_R
Definition: duktape.c:3537
#define DUK_TVAL_IS_BOOLEAN(tv)
Definition: duktape.c:1483
#define DUK_STRIDX_GET
Definition: duktape.c:1798
#define DUK__DOUBLE_INT_CAST1(tname, minval, maxval)
Definition: duktape.c:100444
#define DUK_BIDX_UINT16ARRAY_PROTOTYPE
Definition: duktape.c:2331
DUK_INTERNAL_DECL duk_bool_t duk_js_toboolean(duk_tval *tv)
Definition: duktape.c:82518
DUK_INTERNAL_DECL void duk_hbufobj_promote_plain(duk_hthread *thr, duk_idx_t idx)
Definition: duktape.c:28172
#define DUK__APPENDBUFFER(lex_ctx, x)
Definition: duktape.c:85801
#define DUK__RECURSION_DECREASE(comp_ctx, thr)
Definition: duktape.c:69096
DUK_LOCAL DUK_EXEC_NOINLINE_PERF duk_small_uint_t duk__handle_op_endfin(duk_hthread *thr, duk_uint_fast32_t ins, duk_activation *entry_act)
Definition: duktape.c:79672
#define DUK_TVAL_SET_NUMBER(tv, val)
Definition: duktape.c:1344
#define DUK_HARRAY_LENGTH_WRITABLE(h)
Definition: duktape.c:8469
DUK_INTERNAL_DECL duk_small_int_t duk_unicode_decode_xutf8(duk_hthread *thr, const duk_uint8_t **ptr, const duk_uint8_t *ptr_start, const duk_uint8_t *ptr_end, duk_ucodepoint_t *out_cp)
Definition: duktape.c:12823
DUK_INTERNAL_DECL void duk_hobject_object_seal_freeze_helper(duk_hthread *thr, duk_hobject *obj, duk_bool_t is_freeze)
Definition: duktape.c:64133
DUK_EXTERNAL duk_bool_t duk_get_global_string(duk_hthread *thr, const char *key)
Definition: duktape.c:18392
DUK_LOCAL_DECL void duk__emit_a_b(duk_compiler_ctx *comp_ctx, duk_small_uint_t op_flags, duk_regconst_t a, duk_regconst_t b)
Definition: duktape.c:70535
DUK_INTERNAL_DECL void duk_bw_write_raw_slice(duk_hthread *thr, duk_bufwriter_ctx *bw, duk_size_t src_off, duk_size_t len)
Definition: duktape.c:100242
DUK_INTERNAL_DECL duk_small_uint_t duk_js_typeof_stridx(duk_tval *tv_x)
Definition: duktape.c:83713
DUK_INTERNAL_DECL duk_ret_t duk_bi_object_prototype_is_prototype_of(duk_context *ctx)
Definition: duktape.c:41616
#define DUK_CALL_FLAG_CONSTRUCT_PROXY
Definition: duktape.c:11100
DUK_INTERNAL_DECL duk_bool_t duk_double_is_safe_integer(duk_double_t x)
Definition: duktape.c:100750
#define DUK_DBG_PROPFLAG_SYMBOL
Definition: duktape.c:9757
#define DUK_HBUFFER_GET_SIZE(x)
Definition: duktape.c:8638
#define DUK__BP_CLOSING
Definition: duktape.c:69322
#define DUK_ASC_UC_E
Definition: duktape.c:10827
DUK_INTERNAL_DECL duk_bool_t duk_double_is_nan_zero_inf(duk_double_t x)
Definition: duktape.c:100655
#define DUK_TOK_RPAREN
Definition: duktape.c:3921
#define DUK_TVAL_GET_LIGHTFUNC_FLAGS(tv)
Definition: duktape.c:1472
DUK_EXTERNAL duk_int_t duk_get_type(duk_hthread *thr, duk_idx_t idx)
Definition: duktape.c:22537
DUK_INTERNAL_DECL duk_harray * duk_push_harray_with_size(duk_hthread *thr, duk_uint32_t size)
Definition: duktape.c:23621
#define DUK_HTHREAD_STRING_SET_PROTOTYPE_OF(thr)
Definition: duktape.c:1821
#define DUK_OP_BLSR_RC
Definition: duktape.c:3595
#define DUK_ASC_3
Definition: duktape.c:10809
DUK_INTERNAL_DECL duk_ret_t duk_bi_array_prototype_splice(duk_context *ctx)
Definition: duktape.c:27026
#define DUK__PROP_TYPE_UNDEFINED
Definition: duktape.c:64548
DUK_LOCAL_DECL duk_regconst_t duk__alloctemps(duk_compiler_ctx *comp_ctx, duk_small_int_t num)
Definition: duktape.c:71025
#define DUK_BW_WRITE_ENSURE_XUTF8(thr, bw_ctx, cp)
Definition: duktape.c:2800
#define DUK_DOUBLE_LOG2E
Definition: duktape.c:2375
DUK_LOCAL const duk_uint8_t * duk__inp_backtrack(duk_re_matcher_ctx *re_ctx, const duk_uint8_t **sp, duk_uint_fast32_t count)
Definition: duktape.c:91937
DUK_LOCAL_DECL duk_int_t duk__parse_func_like_fnum(duk_compiler_ctx *comp_ctx, duk_small_uint_t flags)
Definition: duktape.c:76750
DUK_LOCAL duk_uint32_t duk__push_this_obj_len_u32_limited(duk_hthread *thr)
Definition: duktape.c:26153
DUK_LOCAL duk_bool_t duk__executor_handle_call(duk_hthread *thr, duk_idx_t idx, duk_idx_t nargs, duk_small_uint_t call_flags)
Definition: duktape.c:79853
DUK_INTERNAL_DECL duk_bool_t duk_hobject_has_finalizer_fast_raw(duk_hobject *obj)
Definition: duktape.c:62952
DUK_INTERNAL_DECL duk_bool_t duk_get_prop_stridx_short_raw(duk_hthread *thr, duk_uint_t packed_args)
Definition: duktape.c:17730
#define DUK_OP_RETUNDEF
Definition: duktape.c:3671
#define DUK__LE_BODY(barg, carg)
#define DUK_RAW_READINC_U8(ptr)
Definition: duktape.c:2455
#define DUK__SM_Z
Definition: duktape.c:32825
DUK_LOCAL int duk__protected_compact_object(duk_hthread *thr, void *udata)
Definition: duktape.c:52906
DUK_INTERNAL_DECL duk_hobject * duk_hobject_alloc_unchecked(duk_heap *heap, duk_uint_t hobject_flags)
Definition: duktape.c:56544
DUK_LOCAL duk_hbufobj * duk__hbufobj_promote_this(duk_hthread *thr)
Definition: duktape.c:27893
#define DUK_HOBJECT_CLASS_FLOAT64ARRAY
Definition: duktape.c:6665
#define DUK_TOK_VOID
Definition: duktape.c:3876
#define DUK_AUGMENT_FLAG_NOBLAME_FILELINE
Definition: duktape.c:10656
#define DUK_OP_LE_CC
Definition: duktape.c:3535
DUK_LOCAL DUK_NOINLINE void duk__numconv_stringify_raw(duk_hthread *thr, duk_small_int_t radix, duk_small_int_t digits, duk_small_uint_t flags)
Definition: duktape.c:89735
DUK_INTERNAL_DECL const char * duk_get_string_notsymbol(duk_hthread *thr, duk_idx_t idx)
Definition: duktape.c:20520
DUK_INTERNAL_DECL duk_double_t duk_js_tointeger_number(duk_double_t x)
Definition: duktape.c:82723
#define DUK_VALSTACK_INTERNAL_EXTRA
Definition: duktape.c:8045
#define DUK_ASC_HASH
Definition: duktape.c:10793
DUK_LOCAL_DECL void duk__parse_while_stmt(duk_compiler_ctx *comp_ctx, duk_ivalue *res, duk_int_t pc_label_site)
Definition: duktape.c:74869
#define DUK_OP_UNUSED253
Definition: duktape.c:3768
DUK_INTERNAL_DECL void duk_dblunion_little_to_host(duk_double_union *u)
Definition: duktape.c:100860
DUK_INTERNAL_DECL void duk_hthread_copy_builtin_objects(duk_hthread *thr_from, duk_hthread *thr_to)
Definition: duktape.c:65403
DUK_EXTERNAL duk_codepoint_t duk_char_code_at(duk_hthread *thr, duk_idx_t idx, duk_size_t char_offset)
Definition: duktape.c:25950
#define DUK_HCOMPFUNC_GET_CONSTS_BASE(heap, h)
Definition: duktape.c:7615
DUK_INTERNAL_DECL duk_ret_t duk_bi_regexp_prototype_exec(duk_context *ctx)
Definition: duktape.c:42546
#define DUK_STR_UTF8_DECODE_FAILED
Definition: duktape.c:3224
DUK_INTERNAL_DECL void duk_xdef_prop_stridx(duk_hthread *thr, duk_idx_t obj_idx, duk_small_uint_t stridx, duk_small_uint_t desc_flags)
Definition: duktape.c:18101
DUK_INTERNAL_DECL void * duk_default_realloc_function(void *udata, void *ptr, duk_size_t newsize)
Definition: duktape.c:14328
DUK_EXTERNAL duk_int_t duk_require_int(duk_hthread *thr, duk_idx_t idx)
Definition: duktape.c:20365
DUK_EXTERNAL duk_idx_t duk_push_thread_raw(duk_hthread *thr, duk_uint_t flags)
Definition: duktape.c:23643
#define DUK_HOBJECT_FLAG_ARRAY_PART
Definition: duktape.c:6600
#define DUK_BW_WRITE_ENSURE_CESU8(thr, bw_ctx, cp)
Definition: duktape.c:2805
#define DUK_S2N_FLAG_ALLOW_GARBAGE
Definition: duktape.c:11271
#define DUK_ERROR_RAW(thr, file, line, err, msg)
Definition: duktape.c:10094
DUK_INTERNAL_DECL void duk_heap_free_heaphdr_raw(duk_heap *heap, duk_heaphdr *hdr)
Definition: duktape.c:50361
DUK_LOCAL void duk__transform_callback_unescape(duk__transform_context *tfm_ctx, const void *udata, duk_codepoint_t cp)
Definition: duktape.c:37025
#define DUK_BC_OP_MIN
Definition: duktape.c:3458
DUK_LOCAL void duk__json_enc_buffer_data(duk_json_enc_ctx *js_ctx, duk_uint8_t *buf_data, duk_size_t buf_len)
Definition: duktape.c:38865
#define DUK_DBG_CMD_EVAL
Definition: duktape.c:9745
#define DUK_TAG_UNUSED
Definition: duktape.c:1266
DUK_INTERNAL_DECL duk_tval * duk_push_harray_with_size_outptr(duk_hthread *thr, duk_uint32_t size)
Definition: duktape.c:23633
DUK_LOCAL const duk_uint8_t * duk__scan_backwards(const duk_uint8_t *p, const duk_uint8_t *q, duk_uint_fast32_t n)
Definition: duktape.c:55070
DUK_EXTERNAL duk_double_t duk_get_number_default(duk_hthread *thr, duk_idx_t idx, duk_double_t def_value)
Definition: duktape.c:20303
#define DUK_STRIDX_UC_FUNCTION
Definition: duktape.c:1594
#define DUK__BUFOBJ_FLAG_THROW
Definition: duktape.c:27910
DUK_EXTERNAL void duk_substring(duk_hthread *thr, duk_idx_t idx, duk_size_t start_offset, duk_size_t end_offset)
Definition: duktape.c:25825
#define DUK_HEAPHDR_CLEAR_TEMPROOT(h)
Definition: duktape.c:4787
DUK_LOCAL void duk__push_string(duk_hthread *thr, duk_bitdecoder_ctx *bd)
Definition: duktape.c:64685
#define DUK_HOBJECT_HAS_NAMEBINDING(h)
Definition: duktape.c:6761
#define DUK_STR_NATIVE_STACK_LIMIT
Definition: duktape.c:3315
#define DUK__OUTPUT_TYPE_FILENAME
Definition: duktape.c:35896
DUK_INTERNAL_DECL duk_ret_t duk_bi_string_prototype_locale_compare(duk_context *ctx)
Definition: duktape.c:44129
#define DUK_TAG_LIGHTFUNC
Definition: duktape.c:1265
#define duk_get_hobject_promote_lfunc(thr, idx)
Definition: duktape.c:6030
#define DUK_RETOK_ATOM_CHAR
Definition: duktape.c:4134
DUK_LOCAL DUK_NOINLINE_PERF DUK_COLD void * duk__heap_mem_realloc_indirect_slowpath(duk_heap *heap, duk_mem_getptr cb, void *ud, duk_size_t newsize)
Definition: duktape.c:53834
DUK_EXTERNAL duk_double_t duk_get_now(duk_hthread *thr)
Definition: duktape.c:26003
DUK_LOCAL void duk__push_this_helper(duk_hthread *thr, duk_small_uint_t check_object_coercible)
Definition: duktape.c:23219
DUK_INTERNAL_DECL duk_ret_t duk_bi_uint8array_allocplain(duk_context *ctx)
Definition: duktape.c:28926
#define DUK_HOBJECT_HAS_FASTREFS(h)
Definition: duktape.c:6756
DUK_LOCAL_DECL void duk__emit_a_b_c(duk_compiler_ctx *comp_ctx, duk_small_uint_t op_flags, duk_regconst_t a, duk_regconst_t b, duk_regconst_t c)
Definition: duktape.c:70265
#define DUK_BC_CALL_FLAG_TAILCALL
Definition: duktape.c:3790
DUK_LOCAL_DECL void duk__emit_if_true_skip(duk_compiler_ctx *comp_ctx, duk_regconst_t regconst)
Definition: duktape.c:70852
#define DUK_NUM_ALL_BUILTINS
Definition: duktape.c:2339
DUK_LOCAL_DECL void duk__js_execute_bytecode_inner(duk_hthread *entry_thread, duk_activation *entry_act)
Definition: duktape.c:80221
#define DUK_STRIDX_JSON_EXT_POSINF
Definition: duktape.c:1933
DUK_LOCAL duk_bool_t duk__objlit_load_key(duk_compiler_ctx *comp_ctx, duk_ivalue *res, duk_token *tok, duk_regconst_t reg_temp)
Definition: duktape.c:72117
DUK_EXTERNAL duk_bool_t duk_get_global_lstring(duk_hthread *thr, const char *key, duk_size_t key_len)
Definition: duktape.c:18406
#define DUK_HDECENV_ASSERT_VALID(h)
Definition: duktape.c:8525
DUK_LOCAL DUK_NOINLINE void duk__call_c_recursion_limit_check_slowpath(duk_hthread *thr)
Definition: duktape.c:66127
DUK_LOCAL_DECL void duk__mark_tval(duk_heap *heap, duk_tval *tv)
Definition: duktape.c:52284
DUK_INTERNAL_DECL void duk_regexp_compile(duk_hthread *thr)
Definition: duktape.c:91641
DUK_INTERNAL_DECL duk_hobject * duk_push_this_coercible_to_object(duk_hthread *thr)
Definition: duktape.c:23265
DUK_INTERNAL_DECL duk_ret_t duk_bi_pointer_prototype_tostring_shared(duk_context *ctx)
Definition: duktape.c:42185
DUK_INTERNAL_DECL duk_ret_t duk_bi_string_prototype_to_string(duk_context *ctx)
Definition: duktape.c:42910
#define DUK_OP_UNUSED219
Definition: duktape.c:3734
#define DUK_HTHREAD_DECREF(thr, h)
Definition: duktape.c:5068
#define DUK_STRIDX_JSON_EXT_FUNCTION1
Definition: duktape.c:1939
DUK_INTERNAL_DECL duk_uint_t duk_hbufobj_clamp_bytelength(duk_hbufobj *h_bufobj, duk_uint_t len)
Definition: duktape.c:50239
#define DUK_HCOMPFUNC_SET_DATA(heap, h, v)
Definition: duktape.c:7582
#define DUK_BW_INSERT_ENSURE_AREA(thr, bw, off, len)
Definition: duktape.c:2875
#define DUK_OP_CALL11
Definition: duktape.c:3701
#define DUK_OP_BREAK
Definition: duktape.c:3676
DUK_INTERNAL const duk_uint16_t duk_unicode_re_ranges_white[22]
Definition: duktape.c:13838
DUK_EXTERNAL duk_bool_t duk_is_buffer_data(duk_hthread *thr, duk_idx_t idx)
Definition: duktape.c:22734
#define DUK_STRIDX_UC_BUFFER
Definition: duktape.c:1669
#define DUK_SYMBOL_TYPE_LOCAL
Definition: duktape.c:6455
#define DUK_SYMBOL_TYPE_HIDDEN
Definition: duktape.c:6453
DUK_LOCAL duk_uint8_t * duk__dump_hbuffer_raw(duk_hthread *thr, duk_uint8_t *p, duk_hbuffer *h)
Definition: duktape.c:14477
DUK_INTERNAL_DECL void duk_dup_0(duk_hthread *thr)
Definition: duktape.c:19815
DUK_EXTERNAL duk_bool_t duk_to_boolean(duk_hthread *thr, duk_idx_t idx)
Definition: duktape.c:21531
#define DUK_STR_PROXY_REJECTED
Definition: duktape.c:3246
DUK_INTERNAL_DECL duk_ret_t duk_bi_pointer_constructor(duk_context *ctx)
Definition: duktape.c:42153
DUK_LOCAL_DECL void duk__json_enc_newline_indent(duk_json_enc_ctx *js_ctx, duk_uint_t depth)
Definition: duktape.c:39041
#define DUK_OP_CALL12
Definition: duktape.c:3702
#define DUK_TVAL_SET_U32_UPDREF
Definition: duktape.c:5430
#define DUK_DATE_FLAG_SUB1900
Definition: duktape.h:1421
#define DUK_BUFOBJ_UINT8ARRAY
Definition: duktape.h:783
#define DUK_DEFPROP_SET_WEC
Definition: duktape.h:417
#define DUK_COMPILE_SHEBANG
Definition: duktape.h:372
#define DUK_ERR_TYPE_ERROR
Definition: duktape.h:446
#define DUK_ENUM_ARRAY_INDICES_ONLY
Definition: duktape.h:361
#define DUK_TYPE_NONE
Definition: duktape.h:324
#define DUK_DEFPROP_SET_ENUMERABLE
Definition: duktape.h:393
duk_ret_t(* duk_safe_call_function)(duk_context *ctx, void *udata)
Definition: duktape.h:253
#define DUK_GC_COMPACT
Definition: duktape.h:437
#define DUK_DATE_IDX_DAY
Definition: duktape.h:1392
duk_size_t(* duk_debug_read_function)(void *udata, char *buffer, duk_size_t length)
Definition: duktape.h:254
#define DUK_DATE_IDX_SECOND
Definition: duktape.h:1395
#define DUK_TYPE_MASK_STRING
Definition: duktape.h:342
#define DUK_DEFPROP_HAVE_GETTER
Definition: duktape.h:388
void *(* duk_alloc_function)(void *udata, duk_size_t size)
Definition: duktape.h:247
#define DUK_ENUM_SORT_ARRAY_INDICES
Definition: duktape.h:363
#define DUK_VARARGS
Definition: duktape.h:315
#define duk_require_callable(ctx, idx)
Definition: duktape.h:967
#define duk_fatal(ctx, err_msg)
Definition: duktape.h:541
void(* duk_debug_detached_function)(duk_context *ctx, void *udata)
Definition: duktape.h:260
#define DUK_DATE_IDX_YEAR
Definition: duktape.h:1390
#define DUK_TYPE_LIGHTFUNC
Definition: duktape.h:333
#define DUK_BUF_FLAG_NOZERO
Definition: duktape.h:766
#define duk_push_thread(ctx)
Definition: duktape.h:740
#define duk_throw(ctx)
Definition: duktape.h:538
#define DUK_ENUM_NO_PROXY_BEHAVIOR
Definition: duktape.h:364
#define DUK_COMPILE_SAFE
Definition: duktape.h:373
void(* duk_debug_write_flush_function)(void *udata)
Definition: duktape.h:258
#define DUK_DATE_FLAG_TOSTRING_DATE
Definition: duktape.h:1422
#define DUK_DEBUG_PROTOCOL_VERSION
Definition: duktape.h:304
#define duk_is_null_or_undefined(ctx, idx)
Definition: duktape.h:819
#define DUK_TYPE_BOOLEAN
Definition: duktape.h:327
#define DUK_DATE_MSEC_100M_DAYS
Definition: duktape.h:1370
#define DUK_DATE_FLAG_EQUIVYEAR
Definition: duktape.h:1419
#define DUK_DATE_IDX_HOUR
Definition: duktape.h:1393
#define DUK_TYPE_POINTER
Definition: duktape.h:332
#define duk_is_primitive(ctx, idx)
Definition: duktape.h:852
#define duk_push_fixed_buffer(ctx, size)
Definition: duktape.h:772
#define DUK_TYPE_UNDEFINED
Definition: duktape.h:325
#define duk_require_object_coercible(ctx, idx)
Definition: duktape.h:974
#define DUK_TYPE_MASK_OBJECT
Definition: duktape.h:343
#define duk_put_prop_literal(ctx, obj_idx, key)
Definition: duktape.h:1087
duk_codepoint_t(* duk_map_char_function)(void *udata, duk_codepoint_t codepoint)
Definition: duktape.h:252
#define DUK_BUF_MODE_DONTCARE
Definition: duktape.h:1009
#define DUK_DATE_IDX_MONTH
Definition: duktape.h:1391
#define DUK_DATE_MSEC_100M_DAYS_LEEWAY
Definition: duktape.h:1371
#define DUK_BUF_MODE_DYNAMIC
Definition: duktape.h:1008
#define DUK_DEFPROP_HAVE_VALUE
Definition: duktape.h:387
#define DUK_DATE_IDX_WEEKDAY
Definition: duktape.h:1397
#define DUK_DATE_MIN_ECMA_YEAR
Definition: duktape.h:1379
#define DUK_BUF_FLAG_DYNAMIC
Definition: duktape.h:764
#define DUK_DATE_MSEC_MINUTE
Definition: duktape.h:1361
void(* duk_free_function)(void *udata, void *ptr)
Definition: duktape.h:249
void(* duk_debug_read_flush_function)(void *udata)
Definition: duktape.h:257
#define DUK_COMPILE_NORESULT
Definition: duktape.h:374
void *(* duk_realloc_function)(void *udata, void *ptr, duk_size_t size)
Definition: duktape.h:248
#define DUK_TYPE_MASK_BUFFER
Definition: duktape.h:344
#define DUK_RET_TYPE_ERROR
Definition: duktape.h:455
#define DUK_GIT_DESCRIBE
Definition: duktape.h:193
#define DUK_DATE_FLAG_LOCALTIME
Definition: duktape.h:1420
#define DUK_DATE_FLAG_TIMESETTER
Definition: duktape.h:1425
#define DUK_DEFPROP_FORCE
Definition: duktape.h:390
#define duk_get_prop_literal(ctx, obj_idx, key)
Definition: duktape.h:1076
#define DUK_TYPE_MASK_LIGHTFUNC
Definition: duktape.h:346
#define DUK_TYPE_NULL
Definition: duktape.h:326
#define DUK_VERSION
Definition: duktape.h:185
#define DUK_DEFPROP_CONFIGURABLE
Definition: duktape.h:383
#define DUK_BUF_FLAG_EXTERNAL
Definition: duktape.h:765
#define DUK_DATE_FLAG_TOSTRING_LOCALE
Definition: duktape.h:1424
void(* duk_fatal_function)(void *udata, const char *msg)
Definition: duktape.h:250
#define DUK_DATE_FLAG_TOSTRING_TIME
Definition: duktape.h:1423
#define DUK_TYPE_MASK_NONE
Definition: duktape.h:337
#define DUK_ERR_NONE
Definition: duktape.h:440
#define DUK_EXEC_SUCCESS
Definition: duktape.h:459
#define duk_to_fixed_buffer(ctx, idx, out_size)
Definition: duktape.h:1013
#define DUK_TYPE_STRING
Definition: duktape.h:329
#define DUK_DEFPROP_HAVE_WRITABLE
Definition: duktape.h:384
#define DUK_COMPILE_FUNCTION
Definition: duktape.h:370
#define DUK_DATE_MSEC_SECOND
Definition: duktape.h:1360
duk_idx_t(* duk_debug_request_function)(duk_context *ctx, void *udata, duk_idx_t nvalues)
Definition: duktape.h:259
#define DUK_TYPE_MAX
Definition: duktape.h:334
#define DUK_TYPE_MASK_NULL
Definition: duktape.h:339
#define DUK_COMPILE_NOSOURCE
Definition: duktape.h:375
#define DUK_TYPE_MASK_NUMBER
Definition: duktape.h:341
#define DUK_ERR_EVAL_ERROR
Definition: duktape.h:442
#define DUK_ENUM_OWN_PROPERTIES_ONLY
Definition: duktape.h:360
#define DUK_DATE_MSEC_HOUR
Definition: duktape.h:1362
duk_size_t(* duk_debug_peek_function)(void *udata)
Definition: duktape.h:256
#define DUK_ERR_SYNTAX_ERROR
Definition: duktape.h:445
#define DUK_DATE_IDX_MINUTE
Definition: duktape.h:1394
#define DUK_INVALID_INDEX
Definition: duktape.h:310
#define DUK_ERR_RANGE_ERROR
Definition: duktape.h:443
#define DUK_TYPE_MASK_PROMOTE
Definition: duktape.h:348
#define duk_push_buffer(ctx, size, dynamic)
Definition: duktape.h:770
#define DUK_TYPE_MASK_BOOLEAN
Definition: duktape.h:340
#define DUK_DATE_FLAG_NAN_TO_RANGE_ERROR
Definition: duktape.h:1417
#define DUK_HINT_NUMBER
Definition: duktape.h:353
#define duk_push_literal(ctx, cstring)
Definition: duktape.h:719
#define DUK_DATE_IDX_MILLISECOND
Definition: duktape.h:1396
#define DUK_TYPE_MASK_THROW
Definition: duktape.h:347
#define duk_safe_to_string(ctx, idx)
Definition: duktape.h:1022
duk_size_t(* duk_debug_write_function)(void *udata, const char *buffer, duk_size_t length)
Definition: duktape.h:255
#define DUK_DEFPROP_SET_WRITABLE
Definition: duktape.h:391
#define DUK_DEFPROP_HAVE_SETTER
Definition: duktape.h:389
#define DUK_TYPE_MIN
Definition: duktape.h:323
#define DUK_COMPILE_STRLEN
Definition: duktape.h:376
#define DUK_TYPE_OBJECT
Definition: duktape.h:330
duk_ret_t(* duk_c_function)(duk_context *ctx)
Definition: duktape.h:246
#define DUK_DEFPROP_HAVE_CONFIGURABLE
Definition: duktape.h:386
#define DUK_TYPE_BUFFER
Definition: duktape.h:331
#define DUK_TYPE_NUMBER
Definition: duktape.h:328
#define DUK_DEFPROP_ENUMERABLE
Definition: duktape.h:382
#define DUK_HINT_STRING
Definition: duktape.h:352
#define DUK_THREAD_NEW_GLOBAL_ENV
Definition: duktape.h:434
#define DUK_TYPE_MASK_POINTER
Definition: duktape.h:345
#define DUK_BUF_MODE_FIXED
Definition: duktape.h:1007
#define duk_to_buffer(ctx, idx, out_size)
Definition: duktape.h:1011
#define DUK_ERR_REFERENCE_ERROR
Definition: duktape.h:444
#define DUK_DEFPROP_HAVE_ENUMERABLE
Definition: duktape.h:385
#define DUK_INTERNAL_SYMBOL(x)
Definition: duktape.h:488
#define DUK_DATE_IDX_NUM_PARTS
Definition: duktape.h:1398
#define DUK_EXEC_ERROR
Definition: duktape.h:460
#define DUK_ENUM_INCLUDE_SYMBOLS
Definition: duktape.h:358
#define duk_push_dynamic_buffer(ctx, size)
Definition: duktape.h:774
#define duk_type_error
Definition: duktape.h:603
#define DUK_COMPILE_NOFILENAME
Definition: duktape.h:377
#define DUK_ERR_ERROR
Definition: duktape.h:441
#define DUK_DATE_MSEC_DAY
Definition: duktape.h:1363
#define DUK_HINT_NONE
Definition: duktape.h:351
#define DUK_DEFPROP_SET_CONFIGURABLE
Definition: duktape.h:395
#define DUK_DATE_FLAG_YEAR_FIXUP
Definition: duktape.h:1426
#define DUK_ENUM_INCLUDE_HIDDEN
Definition: duktape.h:357
#define DUK_DATE_FLAG_NAN_TO_ZERO
Definition: duktape.h:1416
#define DUK_TYPE_MASK_UNDEFINED
Definition: duktape.h:338
#define DUK_ENUM_EXCLUDE_STRINGS
Definition: duktape.h:359
#define DUK_DEFPROP_WRITABLE
Definition: duktape.h:381
#define DUK_DATE_FLAG_SEP_T
Definition: duktape.h:1427
#define duk_is_callable(ctx, idx)
Definition: duktape.h:840
void(* duk_decode_char_function)(void *udata, duk_codepoint_t codepoint)
Definition: duktape.h:251
#define duk_require_type_mask(ctx, idx, mask)
Definition: duktape.h:949
#define DUK_COMPILE_FUNCEXPR
Definition: duktape.h:378
#define duk_push_error_object
Definition: duktape.h:754
#define duk_is_error(ctx, idx)
Definition: duktape.h:871
#define DUK_COMPILE_STRICT
Definition: duktape.h:371
#define DUK_DATE_FLAG_ONEBASED
Definition: duktape.h:1418
#define DUK_ERR_URI_ERROR
Definition: duktape.h:447
#define DUK_COMPILE_EVAL
Definition: duktape.h:369
#define duk_eval_string_noresult(ctx, src)
Definition: duktape.h:1267
#define DUK_BUFOBJ_ARRAYBUFFER
Definition: duktape.h:779
#define DUK_DATE_MAX_ECMA_YEAR
Definition: duktape.h:1380
#define DUK_ENUM_INCLUDE_NONENUMERABLE
Definition: duktape.h:356
#define DUK_DATE_FLAG_VALUE_SHIFT
Definition: duktape.h:1428
static struct directory * root
Definition: filename.c:55
const char * type
Definition: filetype.cpp:44
@ base
Definition: punycode.c:19
Interface to utility string handling.
duk_uint32_t v[DUK__BI_MAX_PARTS]
Definition: duktape.c:88239
duk_small_int_t n
Definition: duktape.c:88238
duk_size_t src_length
Definition: duktape.c:16651
const duk_uint8_t * src_buffer
Definition: duktape.c:16652
duk_lexer_point lex_pt_alloc
Definition: duktape.c:69117
duk_small_uint_t flags
Definition: duktape.c:69115
duk_compiler_ctx comp_ctx_alloc
Definition: duktape.c:69116
duk_uint8_t bom_handled
Definition: duktape.c:35273
duk_uint8_t fatal
Definition: duktape.c:35276
duk_uint8_t upper
Definition: duktape.c:35270
duk_codepoint_t codepoint
Definition: duktape.c:35269
duk_uint8_t ignore_bom
Definition: duktape.c:35277
duk_uint8_t lower
Definition: duktape.c:35271
duk_uint8_t needed
Definition: duktape.c:35272
duk_uint8_t * out
Definition: duktape.c:35263
duk_codepoint_t lead
Definition: duktape.c:35264
duk_int16_t upper
Definition: duktape.c:88201
duk_hobject * env
Definition: duktape.c:83956
duk_hobject * holder
Definition: duktape.c:83957
duk_bool_t has_this
Definition: duktape.c:83960
duk_small_int_t req_digits
Definition: duktape.c:88820
duk_small_int_t is_fixed
Definition: duktape.c:88819
duk_uint8_t digits[DUK__MAX_OUTPUT_DIGITS]
Definition: duktape.c:88831
duk_small_int_t abs_pos
Definition: duktape.c:88821
duk_small_int_t is_s2n
Definition: duktape.c:88818
duk_small_int_t unequal_gaps
Definition: duktape.c:88828
duk_small_int_t count
Definition: duktape.c:88832
duk_small_int_t low_ok
Definition: duktape.c:88826
duk_small_int_t high_ok
Definition: duktape.c:88827
duk_regconst_t reg_obj
Definition: duktape.c:72089
duk_small_uint_t num_total_pairs
Definition: duktape.c:72092
duk_regconst_t temp_start
Definition: duktape.c:72090
duk_small_uint_t num_pairs
Definition: duktape.c:72091
duk_small_uint_t call_flags
Definition: duktape.c:15231
duk_idx_t nargs
Definition: duktape.c:15230
duk_small_uint_t call_flags
Definition: duktape.c:15225
duk_small_uint_t call_flags
Definition: duktape.c:15219
const duk_uint8_t * p_start
Definition: duktape.c:36728
const duk_uint8_t * p_end
Definition: duktape.c:36729
const duk_uint8_t * p
Definition: duktape.c:36727
duk_bufwriter_ctx bw
Definition: duktape.c:36726
duk_hthread * thr
Definition: duktape.c:36724
duk_hstring * h_str
Definition: duktape.c:36725
duk_small_uint_t flags
Definition: duktape.c:8288
duk_hobject * lex_env
Definition: duktape.c:8235
duk_activation * parent
Definition: duktape.c:8233
duk_hobject * var_env
Definition: duktape.c:8234
duk_hobject * func
Definition: duktape.c:8231
duk_catcher * cat
Definition: duktape.c:8236
duk_size_t reserve_byteoff
Definition: duktape.c:8282
duk_size_t retval_byteoff
Definition: duktape.c:8270
duk_size_t bottom_byteoff
Definition: duktape.c:8258
duk_instr_t * curr_pc
Definition: duktape.c:8245
duk_tval tv_func
Definition: duktape.c:8230
duk_size_t length
Definition: duktape.c:2403
duk_size_t offset
Definition: duktape.c:2402
duk_small_int_t currbits
Definition: duktape.c:2405
duk_uint32_t currval
Definition: duktape.c:2404
const duk_uint8_t * data
Definition: duktape.c:2401
duk_uint32_t currval
Definition: duktape.c:2418
duk_small_int_t truncated
Definition: duktape.c:2420
duk_uint8_t * data
Definition: duktape.c:2415
duk_small_int_t currbits
Definition: duktape.c:2419
duk_size_t length
Definition: duktape.c:2417
duk_size_t offset
Definition: duktape.c:2416
duk_uint32_t line
Definition: duktape.c:9225
duk_hstring * filename
Definition: duktape.c:9224
duk_hbuffer_dynamic * buf
Definition: duktape.c:2500
duk_uint8_t * p_limit
Definition: duktape.c:2499
duk_uint8_t * p_base
Definition: duktape.c:2498
duk_uint8_t * p
Definition: duktape.c:2497
duk_uint32_t flags
Definition: duktape.c:8297
duk_catcher * parent
Definition: duktape.c:8292
duk_size_t idx_base
Definition: duktape.c:8296
duk_hstring * h_varname
Definition: duktape.c:8293
duk_instr_t * pc_base
Definition: duktape.c:8295
duk_uint_t recursion_limit
Definition: duktape.c:30777
const duk_uint8_t * buf
Definition: duktape.c:30773
duk_hthread * thr
Definition: duktape.c:30772
duk_uint_t recursion_depth
Definition: duktape.c:30776
duk_uint_t recursion_depth
Definition: duktape.c:30767
duk_uint8_t * buf
Definition: duktape.c:30763
duk_uint_t recursion_limit
Definition: duktape.c:30768
duk_uint8_t * ptr
Definition: duktape.c:30762
duk_uint8_t * buf_end
Definition: duktape.c:30764
duk_hthread * thr
Definition: duktape.c:30761
duk_compiler_func curr_func
Definition: duktape.c:4457
duk_idx_t tok11_idx
Definition: duktape.c:4444
duk_int_t recursion_limit
Definition: duktape.c:4451
duk_hstring * h_filename
Definition: duktape.c:4436
duk_hthread * thr
Definition: duktape.c:4433
duk_int_t recursion_depth
Definition: duktape.c:4450
duk_idx_t tok21_idx
Definition: duktape.c:4446
duk_idx_t tok12_idx
Definition: duktape.c:4445
duk_token curr_token
Definition: duktape.c:4443
duk_int_t emit_jumpslot_pc
Definition: duktape.c:4454
duk_idx_t tok22_idx
Definition: duktape.c:4447
duk_token prev_token
Definition: duktape.c:4442
duk_lexer_ctx lex
Definition: duktape.c:4439
duk_regconst_t reg_stmt_value
Definition: duktape.c:4404
duk_int_t paren_level
Definition: duktape.c:4392
duk_int_t stmt_next
Definition: duktape.c:4397
duk_uint8_t is_setget
Definition: duktape.c:4416
duk_idx_t varmap_idx
Definition: duktape.c:4377
duk_idx_t argnames_idx
Definition: duktape.c:4376
duk_hbuffer_dynamic * h_labelinfos
Definition: duktape.c:4365
duk_hobject * h_argnames
Definition: duktape.c:4366
duk_int_t led_count
Definition: duktape.c:4391
duk_int_t label_next
Definition: duktape.c:4398
duk_regconst_t shuffle2
Definition: duktape.c:4386
duk_uint8_t may_direct_eval
Definition: duktape.c:4421
duk_hobject * h_consts
Definition: duktape.c:4356
duk_uint8_t is_strict
Definition: duktape.c:4417
duk_regconst_t temp_max
Definition: duktape.c:4382
duk_hobject * h_varmap
Definition: duktape.c:4367
duk_idx_t funcs_idx
Definition: duktape.c:4372
duk_idx_t consts_idx
Definition: duktape.c:4371
duk_uint8_t is_arguments_shadowed
Definition: duktape.c:4425
duk_uint8_t is_namebinding
Definition: duktape.c:4414
duk_uint8_t needs_shuffle
Definition: duktape.c:4426
duk_uint8_t in_scanning
Definition: duktape.c:4420
duk_uint8_t id_access_arguments
Definition: duktape.c:4422
duk_bool_t allow_in
Definition: duktape.c:4394
duk_uint8_t id_access_slow_own
Definition: duktape.c:4424
duk_hstring * h_name
Definition: duktape.c:4354
duk_uint8_t is_eval
Definition: duktape.c:4412
duk_regconst_t temp_first
Definition: duktape.c:4380
duk_regconst_t shuffle3
Definition: duktape.c:4387
duk_int_t catch_depth
Definition: duktape.c:4399
duk_bool_t expr_lhs
Definition: duktape.c:4393
duk_hobject * h_decls
Definition: duktape.c:4360
duk_regconst_t shuffle1
Definition: duktape.c:4385
duk_uint8_t id_access_slow
Definition: duktape.c:4423
duk_regconst_t temp_next
Definition: duktape.c:4381
duk_hobject * h_funcs
Definition: duktape.c:4357
duk_bufwriter_ctx bw_code
Definition: duktape.c:4352
duk_int_t num_formals
Definition: duktape.c:4402
duk_uint8_t is_notail
Definition: duktape.c:4418
duk_hobject * h_labelnames
Definition: duktape.c:4364
duk_uint8_t is_global
Definition: duktape.c:4413
duk_int_t nud_count
Definition: duktape.c:4390
duk_idx_t labelnames_idx
Definition: duktape.c:4374
duk_uint8_t reject_regexp_in_adv
Definition: duktape.c:4428
duk_uint8_t is_function
Definition: duktape.c:4411
duk_uint8_t in_directive_prologue
Definition: duktape.c:4419
duk_uint8_t allow_regexp_in_adv
Definition: duktape.c:4429
duk_int_t fnum_next
Definition: duktape.c:4401
duk_idx_t decls_idx
Definition: duktape.c:4373
duk_int_t with_depth
Definition: duktape.c:4400
duk_idx_t labelinfos_idx
Definition: duktape.c:4375
duk_uint8_t is_constructable
Definition: duktape.c:4415
duk_uint32_t line
Definition: duktape.c:4313
duk_instr_t ins
Definition: duktape.c:4311
Definition: duktape.h:277
const char * key
Definition: duktape.h:278
duk_idx_t nargs
Definition: duktape.h:280
duk_c_function value
Definition: duktape.h:279
duk_uint32_t length
Definition: duktape.c:8490
duk_bool_t length_nonwritable
Definition: duktape.c:8501
duk_hobject obj
Definition: duktape.c:8482
duk_tval target
Definition: duktape.c:7874
duk_tval * args
Definition: duktape.c:7880
duk_tval this_binding
Definition: duktape.c:7877
duk_idx_t nargs
Definition: duktape.c:7881
duk_hobject obj
Definition: duktape.c:7869
duk_size_t size
Definition: duktape.c:8859
duk_heaphdr hdr
Definition: duktape.c:8854
duk_size_t size
Definition: duktape.c:8888
duk_heaphdr hdr
Definition: duktape.c:8883
duk_double_t dummy_for_align8_1
Definition: duktape.c:8815
duk_heaphdr hdr
Definition: duktape.c:8805
union duk_hbuffer_fixed::@129 u
struct duk_hbuffer_fixed::@129::@130 s
duk_size_t size
Definition: duktape.c:8809
duk_size_t size
Definition: duktape.c:8761
duk_heaphdr hdr
Definition: duktape.c:8751
duk_uint8_t elem_type
Definition: duktape.c:8001
duk_uint_t length
Definition: duktape.c:7994
duk_uint8_t shift
Definition: duktape.c:7995
duk_hobject * buf_prop
Definition: duktape.c:7978
duk_uint_t offset
Definition: duktape.c:7993
duk_uint8_t is_typedarray
Definition: duktape.c:8002
duk_hobject obj
Definition: duktape.c:7972
duk_hbuffer * buf
Definition: duktape.c:7975
duk_hobject * lex_env
Definition: duktape.c:7722
duk_hobject obj
Definition: duktape.c:7670
duk_hobject ** funcs
Definition: duktape.c:7711
duk_uint16_t nargs
Definition: duktape.c:7749
duk_instr_t * bytecode
Definition: duktape.c:7712
duk_hbuffer * data
Definition: duktape.c:7697
duk_hobject * var_env
Definition: duktape.c:7723
duk_uint16_t nregs
Definition: duktape.c:7748
duk_hobject obj
Definition: duktape.c:8535
duk_hobject * varmap
Definition: duktape.c:8542
duk_size_t regbase_byteoff
Definition: duktape.c:8543
duk_hthread * thread
Definition: duktape.c:8541
duk_heaphdr * heap_allocated
Definition: duktape.c:9319
duk_uint32_t sym_counter[2]
Definition: duktape.c:9457
duk_int_t call_recursion_limit
Definition: duktape.c:9438
duk_hstring ** strtable
Definition: duktape.c:9513
duk_small_uint_t flags
Definition: duktape.c:9296
duk_heaphdr * refzero_list
Definition: duktape.c:9328
duk_fatal_function fatal_func
Definition: duktape.c:9313
duk_catcher * catcher_free
Definition: duktape.c:9345
duk_uint_t ms_recursion_depth
Definition: duktape.c:9359
duk_heaphdr * finalize_list
Definition: duktape.c:9333
void * heap_udata
Definition: duktape.c:9306
duk_hobject * heap_object
Definition: duktape.c:9434
duk_realloc_function realloc_func
Definition: duktape.c:9300
duk_uint_t pf_prevent_count
Definition: duktape.c:9387
duk_uint32_t st_mask
Definition: duktape.c:9515
duk_uint_t ms_running
Definition: duktape.c:9372
duk_litcache_entry litcache[DUK_USE_LITCACHE_SIZE]
Definition: duktape.c:9532
duk_uint_t ms_prevent_count
Definition: duktape.c:9380
duk_free_function free_func
Definition: duktape.c:9301
duk_hthread * heap_thread
Definition: duktape.c:9428
duk_activation * activation_free
Definition: duktape.c:9342
duk_uint32_t rnd_state
Definition: duktape.c:9446
duk_uint32_t st_size
Definition: duktape.c:9516
duk_hthread * curr_thread
Definition: duktape.c:9431
duk_bool_t creating_error
Definition: duktape.c:9414
duk_hstring * strs[DUK_HEAP_NUM_STRINGS]
Definition: duktape.c:9542
duk_bool_t augmenting_error
Definition: duktape.c:9421
duk_int_t call_recursion_depth
Definition: duktape.c:9437
duk_ljstate lj
Definition: duktape.c:9425
duk_alloc_function alloc_func
Definition: duktape.c:9299
duk_small_uint_t ms_base_flags
Definition: duktape.c:9362
duk_strcache_entry strcache[DUK_HEAP_STRCACHE_SIZE]
Definition: duktape.c:9525
duk_uint_t pf_skip_finalizers
Definition: duktape.c:9394
duk_int_t ms_trigger_counter
Definition: duktape.c:9353
duk_bool_t st_resizing
Definition: duktape.c:9520
duk_uint32_t st_count
Definition: duktape.c:9518
duk_uint32_t hash_seed
Definition: duktape.c:9441
duk_uint32_t h_flags
Definition: duktape.c:4644
duk_uint32_t h_refcount
Definition: duktape.c:4657
duk_hstring * h_next
Definition: duktape.c:4665
duk_uint32_t h_flags
Definition: duktape.c:4591
duk_heaphdr * h_prev
Definition: duktape.c:4620
duk_heaphdr * h_next
Definition: duktape.c:4612
duk_uint32_t h_refcount
Definition: duktape.c:4603
duk_int16_t nargs
Definition: duktape.c:7825
duk_int16_t magic
Definition: duktape.c:7826
duk_c_function func
Definition: duktape.c:7824
duk_hobject obj
Definition: duktape.c:7822
duk_heaphdr hdr
Definition: duktape.c:7289
duk_uint32_t a_size
Definition: duktape.c:7382
duk_uint32_t e_next
Definition: duktape.c:7381
duk_uint32_t e_size
Definition: duktape.c:7380
duk_uint32_t h_size
Definition: duktape.c:7384
duk_hobject * prototype
Definition: duktape.c:7369
duk_uint8_t * props
Definition: duktape.c:7362
duk_hobject obj
Definition: duktape.c:8548
duk_hobject * target
Definition: duktape.c:8551
duk_bool_t has_this
Definition: duktape.c:8557
duk_hobject obj
Definition: duktape.c:8931
duk_hobject * target
Definition: duktape.c:8934
duk_hobject * handler
Definition: duktape.c:8937
duk_hstring str
Definition: duktape.c:6523
const duk_uint8_t * extdata
Definition: duktape.c:6531
duk_uarridx_t arridx
Definition: duktape.c:6492
duk_uint32_t clen
Definition: duktape.c:6510
duk_uint32_t blen
Definition: duktape.c:6499
duk_uint32_t hash
Definition: duktape.c:6487
duk_heaphdr_string hdr
Definition: duktape.c:6481
duk_compiler_ctx * compile_ctx
Definition: duktape.c:8372
duk_instr_t ** ptr_curr_pc
Definition: duktape.c:8312
duk_tval * valstack_bottom
Definition: duktape.c:8358
duk_int_t interrupt_init
Definition: duktape.c:8383
duk_hobject * builtins[DUK_NUM_BUILTINS]
Definition: duktape.c:8397
duk_uint8_t state
Definition: duktape.c:8321
duk_heap * heap
Definition: duktape.c:8315
duk_tval * valstack_end
Definition: duktape.c:8356
duk_hstring ** strs
Definition: duktape.c:8406
duk_hthread * resumer
Definition: duktape.c:8369
duk_tval * valstack_alloc_end
Definition: duktape.c:8357
duk_size_t callstack_preventcount
Definition: duktape.c:8366
duk_tval * valstack_top
Definition: duktape.c:8359
duk_uint8_t unused1
Definition: duktape.c:8322
duk_uint8_t strict
Definition: duktape.c:8318
duk_tval * valstack
Definition: duktape.c:8355
duk_activation * callstack_curr
Definition: duktape.c:8364
duk_int_t interrupt_counter
Definition: duktape.c:8382
duk_hobject obj
Definition: duktape.c:8305
duk_uint8_t unused2
Definition: duktape.c:8323
duk_size_t callstack_top
Definition: duktape.c:8365
duk_int_t call_recursion_depth
Definition: duktape.c:17091
duk_uint8_t thread_state
Definition: duktape.c:17090
duk_hthread * curr_thread
Definition: duktape.c:17089
duk_idx_t valstack_idx
Definition: duktape.c:4286
duk_regconst_t regconst
Definition: duktape.c:4285
duk_small_uint_t t
Definition: duktape.c:4284
duk_small_uint_t t
Definition: duktape.c:4298
duk_small_uint_t op
Definition: duktape.c:4299
duk_ispec x2
Definition: duktape.c:4301
duk_ispec x1
Definition: duktape.c:4300
DUK_JMPBUF_TYPE jb
Definition: duktape.c:718
duk_hthread * thr
Definition: duktape.c:11070
const duk_uint8_t * p_end
Definition: duktape.c:11073
duk_small_uint_t flags
Definition: duktape.c:11075
duk_small_uint_t flag_ext_custom
Definition: duktape.c:11077
duk_small_uint_t flag_ext_compatible
Definition: duktape.c:11078
duk_int_t recursion_depth
Definition: duktape.c:11081
duk_int_t recursion_limit
Definition: duktape.c:11082
duk_idx_t idx_reviver
Definition: duktape.c:11074
duk_small_uint_t flag_ext_custom_or_compatible
Definition: duktape.c:11079
const duk_uint8_t * p_start
Definition: duktape.c:11072
const duk_uint8_t * p
Definition: duktape.c:11071
duk_hthread * thr
Definition: duktape.c:11042
duk_small_uint_t stridx_custom_function
Definition: duktape.c:11064
duk_hobject * visiting[DUK_JSON_ENC_LOOPARRAY]
Definition: duktape.c:11066
duk_hstring * h_gap
Definition: duktape.c:11045
duk_small_uint_t flag_avoid_key_quotes
Definition: duktape.c:11050
duk_bufwriter_ctx bw
Definition: duktape.c:11043
duk_uint_t mask_for_undefined
Definition: duktape.c:11058
duk_small_uint_t stridx_custom_undefined
Definition: duktape.c:11060
duk_small_uint_t flag_ext_custom_or_compatible
Definition: duktape.c:11054
duk_uint_t recursion_limit
Definition: duktape.c:11057
duk_hobject * h_replacer
Definition: duktape.c:11044
duk_uint_t recursion_depth
Definition: duktape.c:11056
duk_small_uint_t flag_ascii_only
Definition: duktape.c:11049
duk_small_uint_t flags
Definition: duktape.c:11048
duk_idx_t idx_loop
Definition: duktape.c:11047
duk_small_uint_t flag_ext_custom
Definition: duktape.c:11052
duk_small_uint_t stridx_custom_posinf
Definition: duktape.c:11063
duk_small_uint_t stridx_custom_nan
Definition: duktape.c:11061
duk_small_uint_t stridx_custom_neginf
Definition: duktape.c:11062
duk_small_uint_t flag_ext_compatible
Definition: duktape.c:11053
duk_idx_t idx_proplist
Definition: duktape.c:11046
duk_small_uint_t flags
Definition: duktape.c:4329
duk_int_t label_id
Definition: duktape.c:4330
duk_int_t catch_depth
Definition: duktape.c:4332
duk_int_t pc_label
Definition: duktape.c:4333
duk_hstring * h_label
Definition: duktape.c:4331
duk_size_t offset
Definition: duktape.c:4188
duk_int_t line
Definition: duktape.c:4189
duk_codepoint_t codepoint
Definition: duktape.c:4187
duk_lexer_codepoint * window
Definition: duktape.c:4195
duk_small_uint_t flags
Definition: duktape.c:4217
duk_hbuffer_dynamic * buf
Definition: duktape.c:4211
duk_size_t input_offset
Definition: duktape.c:4205
duk_hthread * thr
Definition: duktape.c:4201
duk_idx_t buf_idx
Definition: duktape.c:4210
duk_bufwriter_ctx bw
Definition: duktape.c:4212
duk_idx_t slot1_idx
Definition: duktape.c:4208
duk_int_t input_line
Definition: duktape.c:4206
duk_size_t input_length
Definition: duktape.c:4204
duk_int_t token_limit
Definition: duktape.c:4215
const duk_uint8_t * input
Definition: duktape.c:4203
duk_lexer_codepoint buffer[DUK_LEXER_BUFFER_SIZE]
Definition: duktape.c:4196
duk_int_t token_count
Definition: duktape.c:4214
duk_idx_t slot2_idx
Definition: duktape.c:4209
duk_int_t line
Definition: duktape.c:4182
duk_size_t offset
Definition: duktape.c:4181
Definition: duktape.c:9274
duk_hstring * h
Definition: duktape.c:9276
const duk_uint8_t * addr
Definition: duktape.c:9275
duk_small_uint_t type
Definition: duktape.c:9250
duk_bool_t iserror
Definition: duktape.c:9251
duk_tval value2
Definition: duktape.c:9253
duk_jmpbuf * jmpbuf_ptr
Definition: duktape.c:9249
duk_tval value1
Definition: duktape.c:9252
duk_free_function free_func
Definition: duktape.h:273
duk_realloc_function realloc_func
Definition: duktape.h:272
duk_alloc_function alloc_func
Definition: duktape.h:271
Definition: duktape.h:283
duk_double_t value
Definition: duktape.h:285
const char * key
Definition: duktape.h:284
duk_hobject * get
Definition: duktape.c:7263
duk_hobject * set
Definition: duktape.c:7264
duk_hobject * set
Definition: duktape.c:7280
duk_int_t h_idx
Definition: duktape.c:7284
duk_small_uint_t flags
Definition: duktape.c:7278
duk_int_t e_idx
Definition: duktape.c:7283
duk_hobject * get
Definition: duktape.c:7279
duk_int_t a_idx
Definition: duktape.c:7285
duk_re_token curr_token
Definition: duktape.c:4534
duk_hthread * thr
Definition: duktape.c:4530
duk_uint32_t highest_backref
Definition: duktape.c:4537
duk_uint32_t re_flags
Definition: duktape.c:4532
duk_uint32_t recursion_depth
Definition: duktape.c:4538
duk_uint32_t nranges
Definition: duktape.c:4540
duk_lexer_ctx lex
Definition: duktape.c:4533
duk_bufwriter_ctx bw
Definition: duktape.c:4535
duk_uint32_t recursion_limit
Definition: duktape.c:4539
duk_uint32_t captures
Definition: duktape.c:4536
const duk_uint8_t * input_end
Definition: duktape.c:4518
duk_hthread * thr
Definition: duktape.c:4514
duk_uint32_t nsaved
Definition: duktape.c:4522
duk_uint32_t re_flags
Definition: duktape.c:4516
const duk_uint8_t * input
Definition: duktape.c:4517
const duk_uint8_t ** saved
Definition: duktape.c:4521
duk_uint32_t steps_count
Definition: duktape.c:4525
duk_uint32_t recursion_depth
Definition: duktape.c:4523
const duk_uint8_t * bytecode_end
Definition: duktape.c:4520
const duk_uint8_t * bytecode
Definition: duktape.c:4519
duk_uint32_t recursion_limit
Definition: duktape.c:4524
duk_uint32_t steps_limit
Definition: duktape.c:4526
duk_small_uint_t t
Definition: duktape.c:4172
duk_uint32_t qmin
Definition: duktape.c:4175
duk_uint32_t qmax
Definition: duktape.c:4176
duk_uint32_t num
Definition: duktape.c:4174
duk_small_uint_t greedy
Definition: duktape.c:4173
Definition: duktape.c:9237
duk_uint32_t cidx
Definition: duktape.c:9240
duk_hstring * h
Definition: duktape.c:9238
duk_uint32_t bidx
Definition: duktape.c:9239
duk_double_t month
Definition: duktape.h:290
duk_double_t seconds
Definition: duktape.h:294
duk_double_t year
Definition: duktape.h:289
duk_double_t hours
Definition: duktape.h:292
duk_double_t milliseconds
Definition: duktape.h:295
duk_double_t minutes
Definition: duktape.h:293
duk_double_t day
Definition: duktape.h:291
duk_double_t weekday
Definition: duktape.h:296
duk_small_uint_t t
Definition: duktape.c:4156
duk_size_t start_offset
Definition: duktape.c:4161
duk_bool_t lineterm
Definition: duktape.c:4164
duk_int_t start_line
Definition: duktape.c:4162
duk_double_t num
Definition: duktape.c:4158
duk_int_t num_escapes
Definition: duktape.c:4163
duk_bool_t allow_auto_semi
Definition: duktape.c:4165
duk_small_uint_t t_nores
Definition: duktape.c:4157
duk_hstring * str1
Definition: duktape.c:4159
duk_hstring * str2
Definition: duktape.c:4160
duk_hcompfunc * hcompfunc
Definition: duktape.c:1233
duk_double_t d
Definition: duktape.c:1225
duk_int64_t fi
Definition: duktape.c:1228
duk_hthread * hthread
Definition: duktape.c:1235
duk_heaphdr * heaphdr
Definition: duktape.c:1237
duk_small_int_t i
Definition: duktape.c:1226
duk_hbuffer * hbuffer
Definition: duktape.c:1236
duk_small_uint_t t
Definition: duktape.c:1222
duk_c_function lightfunc
Definition: duktape.c:1238
duk_small_uint_t v_extra
Definition: duktape.c:1223
duk_hnatfunc * hnatfunc
Definition: duktape.c:1234
duk_hobject * hobject
Definition: duktape.c:1232
union duk_tval_struct::@128 v
void * voidptr
Definition: duktape.c:1230
duk_hstring * hstring
Definition: duktape.c:1231
duk_small_uint_t t
Definition: duktape.c:1243
duk_small_uint_t v_extra
Definition: duktape.c:1244
duk_double_t d
Definition: duktape.c:1250
duk_uint16_t x
Definition: duktape.c:13881
duk_uint8_t b[2]
Definition: duktape.c:13880
duk_uint32_t x
Definition: duktape.c:13887
duk_uint8_t b[4]
Definition: duktape.c:13886
duk_uint8_t uc[8]
Definition: duktape.c:275
duk_uint16_t us[4]
Definition: duktape.c:274
duk_uint32_t ui[2]
Definition: duktape.c:273
float f[2]
Definition: duktape.c:269
duk_uint32_t ui[1]
Definition: duktape.c:640
duk_uint16_t us[2]
Definition: duktape.c:641
duk_uint8_t uc[4]
Definition: duktape.c:642
duk_tval v
Definition: duktape.c:7272
duk_propaccessor a
Definition: duktape.c:7273
#define max(x, y)
Definition: utils.h:50
static nserror line(const struct redraw_context *ctx, const plot_style_t *style, const struct rect *line)
Plots a line.
Definition: plot.c:579